diff --git a/common/repositories/base/base_zone_points_repository.h b/common/repositories/base/base_zone_points_repository.h index 80cb1be7c..f6182cc0d 100644 --- a/common/repositories/base/base_zone_points_repository.h +++ b/common/repositories/base/base_zone_points_repository.h @@ -56,6 +56,9 @@ public: int max_expansion; std::string content_flags; std::string content_flags_disabled; + int is_virtual; + int height; + int width; }; static std::string PrimaryKey() @@ -87,6 +90,9 @@ public: "max_expansion", "content_flags", "content_flags_disabled", + "is_virtual", + "height", + "width", }; } @@ -158,6 +164,9 @@ public: entry.max_expansion = 0; entry.content_flags = ""; entry.content_flags_disabled = ""; + entry.is_virtual = 0; + entry.height = 0; + entry.width = 0; return entry; } @@ -213,6 +222,9 @@ public: entry.max_expansion = atoi(row[18]); entry.content_flags = row[19] ? row[19] : ""; entry.content_flags_disabled = row[20] ? row[20] : ""; + entry.is_virtual = atoi(row[21]); + entry.height = atoi(row[22]); + entry.width = atoi(row[23]); return entry; } @@ -264,6 +276,9 @@ public: update_values.push_back(columns[18] + " = " + std::to_string(zone_points_entry.max_expansion)); update_values.push_back(columns[19] + " = '" + EscapeString(zone_points_entry.content_flags) + "'"); update_values.push_back(columns[20] + " = '" + EscapeString(zone_points_entry.content_flags_disabled) + "'"); + update_values.push_back(columns[21] + " = " + std::to_string(zone_points_entry.is_virtual)); + update_values.push_back(columns[22] + " = " + std::to_string(zone_points_entry.height)); + update_values.push_back(columns[23] + " = " + std::to_string(zone_points_entry.width)); auto results = content_db.QueryDatabase( fmt::format( @@ -304,6 +319,9 @@ public: insert_values.push_back(std::to_string(zone_points_entry.max_expansion)); insert_values.push_back("'" + EscapeString(zone_points_entry.content_flags) + "'"); insert_values.push_back("'" + EscapeString(zone_points_entry.content_flags_disabled) + "'"); + insert_values.push_back(std::to_string(zone_points_entry.is_virtual)); + insert_values.push_back(std::to_string(zone_points_entry.height)); + insert_values.push_back(std::to_string(zone_points_entry.width)); auto results = content_db.QueryDatabase( fmt::format( @@ -352,6 +370,9 @@ public: insert_values.push_back(std::to_string(zone_points_entry.max_expansion)); insert_values.push_back("'" + EscapeString(zone_points_entry.content_flags) + "'"); insert_values.push_back("'" + EscapeString(zone_points_entry.content_flags_disabled) + "'"); + insert_values.push_back(std::to_string(zone_points_entry.is_virtual)); + insert_values.push_back(std::to_string(zone_points_entry.height)); + insert_values.push_back(std::to_string(zone_points_entry.width)); insert_chunks.push_back("(" + implode(",", insert_values) + ")"); } @@ -406,6 +427,9 @@ public: entry.max_expansion = atoi(row[18]); entry.content_flags = row[19] ? row[19] : ""; entry.content_flags_disabled = row[20] ? row[20] : ""; + entry.is_virtual = atoi(row[21]); + entry.height = atoi(row[22]); + entry.width = atoi(row[23]); all_entries.push_back(entry); } @@ -451,6 +475,9 @@ public: entry.max_expansion = atoi(row[18]); entry.content_flags = row[19] ? row[19] : ""; entry.content_flags_disabled = row[20] ? row[20] : ""; + entry.is_virtual = atoi(row[21]); + entry.height = atoi(row[22]); + entry.width = atoi(row[23]); all_entries.push_back(entry); } diff --git a/common/version.h b/common/version.h index 0dd15a90f..a481fd1f4 100644 --- a/common/version.h +++ b/common/version.h @@ -34,7 +34,7 @@ * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9155 +#define CURRENT_BINARY_DATABASE_VERSION 9156 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9027 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 383293eac..58cb8930f 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -409,6 +409,7 @@ 9153|2020_05_09_items_subtype.sql|SHOW COLUMNS from `items` LIKE 'UNK219'|not_empty| 9154|2020_04_11_expansions_content_filters.sql|SHOW COLUMNS from `zone` LIKE 'min_expansion'|empty| 9155|2020_08_15_lootdrop_level_filtering.sql|SHOW COLUMNS from `lootdrop_entries` LIKE 'trivial_min_level'|empty| +9156|2020_08_16_virtual_zonepoints.sql|SHOW COLUMNS from `zone_points` LIKE 'is_virtual'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2020_08_16_virtual_zonepoints.sql b/utils/sql/git/required/2020_08_16_virtual_zonepoints.sql new file mode 100644 index 000000000..3fb21cd0a --- /dev/null +++ b/utils/sql/git/required/2020_08_16_virtual_zonepoints.sql @@ -0,0 +1,3 @@ +ALTER TABLE `zone_points` ADD COLUMN `is_virtual` tinyint NOT NULL DEFAULT '0' COMMENT '' AFTER `content_flags_disabled`; +ALTER TABLE `zone_points` ADD COLUMN `height` int NOT NULL DEFAULT '0' COMMENT ''; +ALTER TABLE `zone_points` ADD COLUMN `width` int NOT NULL DEFAULT '0' COMMENT ''; \ No newline at end of file diff --git a/zone/client.cpp b/zone/client.cpp index 406382662..a413c7899 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -56,6 +56,7 @@ extern volatile bool RunLoops; #include "quest_parser_collection.h" #include "queryserv.h" #include "mob_movement_manager.h" +#include "../common/content/world_content_service.h" extern QueryServ* QServ; extern EntityList entity_list; @@ -9345,3 +9346,101 @@ void Client::SendToGuildHall() AssignToInstance(instance_id); MovePC(345, instance_id, -1.00, -1.00, 3.34, 0, 1); } + +void Client::CheckVirtualZoneLines() +{ + for (auto &virtual_zone_point : zone->virtual_zone_point_list) { + float half_width = ((float) virtual_zone_point.width / 2); + + if ( + GetX() > (virtual_zone_point.x - half_width) && + GetX() < (virtual_zone_point.x + half_width) && + GetY() > (virtual_zone_point.y - half_width) && + GetY() < (virtual_zone_point.y + half_width) && + GetZ() >= (virtual_zone_point.z - 10) && + GetZ() < (virtual_zone_point.z + (float) virtual_zone_point.height) + ) { + + MovePC( + virtual_zone_point.target_zone_id, + virtual_zone_point.target_instance, + virtual_zone_point.target_x, + virtual_zone_point.target_y, + virtual_zone_point.target_z, + virtual_zone_point.target_heading + ); + + LogZonePoints( + "Virtual Zone Box Sending player [{}] to [{}]", + GetCleanName(), + zone_store.GetZoneLongName(virtual_zone_point.target_zone_id) + ); + } + } +} + +void Client::ShowDevToolsMenu() +{ + std::string menu_commands_search; + std::string menu_commands_show; + std::string reload_commands_show; + std::string window_toggle_command; + + /** + * Search entity commands + */ + menu_commands_search += "[" + EQ::SayLinkEngine::GenerateQuestSaylink("#list npcs", false, "NPC") + "] "; + menu_commands_search += "[" + EQ::SayLinkEngine::GenerateQuestSaylink("#list players", false, "Players") + "] "; + menu_commands_search += "[" + EQ::SayLinkEngine::GenerateQuestSaylink("#list corpses", false, "Corpses") + "] "; + menu_commands_search += "[" + EQ::SayLinkEngine::GenerateQuestSaylink("#list doors", false, "Doors") + "] "; + menu_commands_search += "[" + EQ::SayLinkEngine::GenerateQuestSaylink("#list objects", false, "Objects") + "] "; + menu_commands_search += "[" + EQ::SayLinkEngine::GenerateQuestSaylink("#fz", false, "Zones") + "] "; + menu_commands_search += "[" + EQ::SayLinkEngine::GenerateQuestSaylink("#fi", false, "Items") + "] "; + + /** + * Show + */ + menu_commands_show += "[" + EQ::SayLinkEngine::GenerateQuestSaylink("#showzonepoints", false, "Zone Points") + "] "; + menu_commands_show += "[" + EQ::SayLinkEngine::GenerateQuestSaylink("#showzonegloballoot", false, "Zone Global Loot") + "] "; + + /** + * Reload + */ + reload_commands_show += "[" + EQ::SayLinkEngine::GenerateQuestSaylink("#rq", false, "Quests") + "] "; + reload_commands_show += "[" + EQ::SayLinkEngine::GenerateQuestSaylink("#reloadmerchants", false, "Merchants") + "] "; + reload_commands_show += "[" + EQ::SayLinkEngine::GenerateQuestSaylink("#reloadallrules", false, "Rules Globally") + "] "; + reload_commands_show += "[" + EQ::SayLinkEngine::GenerateQuestSaylink("#reloadstatic", false, "Ground Spawns") + "] "; + reload_commands_show += "[" + EQ::SayLinkEngine::GenerateQuestSaylink("#reloadstatic", false, "Alternate Currencies") + "] "; + reload_commands_show += "[" + EQ::SayLinkEngine::GenerateQuestSaylink("#reloadstatic", false, "DB Emotes") + "] "; + reload_commands_show += "[" + EQ::SayLinkEngine::GenerateQuestSaylink("#reloadstatic", false, "Doors") + "] "; + reload_commands_show += "[" + EQ::SayLinkEngine::GenerateQuestSaylink("#reloadtraps", false, "Traps") + "] "; + reload_commands_show += "[" + EQ::SayLinkEngine::GenerateQuestSaylink("#reloadzps", false, "Zone Points") + "] "; + + /** + * Show window status + */ + window_toggle_command = "Disabled [" + EQ::SayLinkEngine::GenerateQuestSaylink("#devtools enable_window", false, "Enable") + "] "; + if (IsDevToolsWindowEnabled()) { + window_toggle_command = "Enabled [" + EQ::SayLinkEngine::GenerateQuestSaylink("#devtools disable_window", false, "Disable") + "] "; + } + + /** + * Print menu + */ + SendChatLineBreak(); + Message( + Chat::White, "| [Devtools] Window %s Show this menu with %s | Current expansion [%s]", + window_toggle_command.c_str(), + EQ::SayLinkEngine::GenerateQuestSaylink("#dev", false, "#dev").c_str(), + content_service.GetCurrentExpansionName().c_str() + ); + Message(Chat::White, "| [Devtools] Search %s", menu_commands_search.c_str()); + Message(Chat::White, "| [Devtools] Show %s", menu_commands_show.c_str()); + Message(Chat::White, "| [Devtools] Reload %s", reload_commands_show.c_str()); + Message(Chat::White, "| [Devtools] Search commands with #help "); + SendChatLineBreak(); +} + +void Client::SendChatLineBreak(uint16 color) { + Message(color, "------------------------------------------------"); +} diff --git a/zone/client.h b/zone/client.h index 036f03baa..d2778d55a 100644 --- a/zone/client.h +++ b/zone/client.h @@ -238,6 +238,8 @@ public: void SetPrimaryWeaponOrnamentation(uint32 model_id); void SetSecondaryWeaponOrnamentation(uint32 model_id); + void SendChatLineBreak(uint16 color = Chat::White); + bool GotoPlayer(std::string player_name); //abstract virtual function implementations required by base abstract class @@ -446,6 +448,8 @@ public: inline float ProximityZ() const { return m_Proximity.z; } inline void ClearAllProximities() { entity_list.ProcessMove(this, glm::vec3(FLT_MAX, FLT_MAX, FLT_MAX)); m_Proximity = glm::vec3(FLT_MAX,FLT_MAX,FLT_MAX); } + void CheckVirtualZoneLines(); + /* Begin client modifiers */ @@ -1317,6 +1321,8 @@ public: Raid *p_raid_instance; + void ShowDevToolsMenu(); + protected: friend class Mob; void CalcItemBonuses(StatBonuses* newbon); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index b88105aaf..19773f3a4 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -918,6 +918,11 @@ void Client::CompleteConnect() worldserver.RequestTellQueue(GetName()); entity_list.ScanCloseMobs(close_mobs, this, true); + + if (GetGM()) { + ShowDevToolsMenu(); + } + } // connecting opcode handlers @@ -4640,6 +4645,9 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) { } CheckRegionTypeChanges(); } + + CheckVirtualZoneLines(); + } void Client::Handle_OP_CombatAbility(const EQApplicationPacket *app) diff --git a/zone/command.cpp b/zone/command.cpp index 8ee74854b..0a240f33b 100755 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -387,6 +387,7 @@ int command_init(void) command_add("showspellslist", "Shows spell list of targeted NPC", 100, command_showspellslist) || command_add("showstats", "- Show details about you or your target", 50, command_showstats) || command_add("showzonegloballoot", "Show GlobalLoot entires on this zone", 50, command_showzonegloballoot) || + command_add("showzonepoints", "Show zone points for current zone", 50, command_showzonepoints) || command_add("shutdown", "- Shut this zone process down", 150, command_shutdown) || command_add("size", "[size] - Change size of you or your target", 50, command_size) || command_add("spawn", "[name] [race] [level] [material] [hp] [gender] [class] [priweapon] [secweapon] [merchantid] - Spawn an NPC", 10, command_spawn) || @@ -5364,7 +5365,6 @@ void command_memspell(Client *c, const Seperator *sep) } } } - void command_save(Client *c, const Seperator *sep) { if (c->GetTarget() == 0) @@ -5399,6 +5399,153 @@ void command_showzonegloballoot(Client *c, const Seperator *sep) zone->ShowZoneGlobalLoot(c); } +void command_showzonepoints(Client *c, const Seperator *sep) +{ + auto &mob_list = entity_list.GetMobList(); + for (auto itr : mob_list) { + Mob *mob = itr.second; + if (mob->IsNPC() && mob->GetRace() == 2254) { + mob->Depop(); + } + } + + int found_zone_points = 0; + + c->Message(Chat::White, "Listing zone points..."); + c->SendChatLineBreak(); + + for (auto &virtual_zone_point : zone->virtual_zone_point_list) { + std::string zone_long_name = zone_store.GetZoneLongName(virtual_zone_point.target_zone_id); + + c->Message( + Chat::White, + fmt::format( + "Virtual Zone Point x [{}] y [{}] z [{}] h [{}] width [{}] height [{}] | To [{}] ({}) x [{}] y [{}] z [{}] h [{}]", + virtual_zone_point.x, + virtual_zone_point.y, + virtual_zone_point.z, + virtual_zone_point.heading, + virtual_zone_point.width, + virtual_zone_point.height, + zone_long_name.c_str(), + virtual_zone_point.target_zone_id, + virtual_zone_point.target_x, + virtual_zone_point.target_y, + virtual_zone_point.target_z, + virtual_zone_point.target_heading + ).c_str() + ); + + std::string node_name = fmt::format("ZonePoint To [{}]", zone_long_name); + + float half_width = ((float) virtual_zone_point.width / 2); + + NPC::SpawnZonePointNodeNPC(node_name, glm::vec4( + (float) virtual_zone_point.x + half_width, + (float) virtual_zone_point.y + half_width, + virtual_zone_point.z, + virtual_zone_point.heading + )); + + NPC::SpawnZonePointNodeNPC(node_name, glm::vec4( + (float) virtual_zone_point.x + half_width, + (float) virtual_zone_point.y - half_width, + virtual_zone_point.z, + virtual_zone_point.heading + )); + + NPC::SpawnZonePointNodeNPC(node_name, glm::vec4( + (float) virtual_zone_point.x - half_width, + (float) virtual_zone_point.y - half_width, + virtual_zone_point.z, + virtual_zone_point.heading + )); + + NPC::SpawnZonePointNodeNPC(node_name, glm::vec4( + (float) virtual_zone_point.x - half_width, + (float) virtual_zone_point.y + half_width, + virtual_zone_point.z, + virtual_zone_point.heading + )); + + NPC::SpawnZonePointNodeNPC(node_name, glm::vec4( + (float) virtual_zone_point.x + half_width, + (float) virtual_zone_point.y + half_width, + (float) virtual_zone_point.z + (float) virtual_zone_point.height, + virtual_zone_point.heading + )); + + NPC::SpawnZonePointNodeNPC(node_name, glm::vec4( + (float) virtual_zone_point.x + half_width, + (float) virtual_zone_point.y - half_width, + (float) virtual_zone_point.z + (float) virtual_zone_point.height, + virtual_zone_point.heading + )); + + NPC::SpawnZonePointNodeNPC(node_name, glm::vec4( + (float) virtual_zone_point.x - half_width, + (float) virtual_zone_point.y - half_width, + (float) virtual_zone_point.z + (float) virtual_zone_point.height, + virtual_zone_point.heading + )); + + NPC::SpawnZonePointNodeNPC(node_name, glm::vec4( + (float) virtual_zone_point.x - half_width, + (float) virtual_zone_point.y + half_width, + (float) virtual_zone_point.z + (float) virtual_zone_point.height, + virtual_zone_point.heading + )); + + found_zone_points++; + } + + LinkedListIterator iterator(zone->zone_point_list); + iterator.Reset(); + while (iterator.MoreElements()) { + ZonePoint *zone_point = iterator.GetData(); + std::string zone_long_name = zone_store.GetZoneLongName(zone_point->target_zone_id); + std::string node_name = fmt::format("ZonePoint To [{}]", zone_long_name); + + NPC::SpawnZonePointNodeNPC( + node_name, glm::vec4( + zone_point->x, + zone_point->y, + zone_point->z, + zone_point->heading + ) + ); + + c->Message( + Chat::White, + fmt::format( + "Client Side Zone Point x [{}] y [{}] z [{}] h [{}] number [{}] | To [{}] ({}) x [{}] y [{}] z [{}] h [{}]", + zone_point->x, + zone_point->y, + zone_point->z, + zone_point->heading, + zone_point->number, + zone_long_name.c_str(), + zone_point->target_zone_id, + zone_point->target_x, + zone_point->target_y, + zone_point->target_z, + zone_point->target_heading + ).c_str() + ); + + iterator.Advance(); + + found_zone_points++; + } + + if (found_zone_points == 0) { + c->Message(Chat::White, "There were no zone points found..."); + } + + c->SendChatLineBreak(); + +} + void command_mystats(Client *c, const Seperator *sep) { if (c->GetTarget() && c->GetPet()) { @@ -5445,18 +5592,6 @@ void command_depopzone(Client *c, const Seperator *sep) void command_devtools(Client *c, const Seperator *sep) { - std::string menu_commands_search; - std::string window_toggle_command; - - /** - * Search entity commands - */ - menu_commands_search += "[" + EQ::SayLinkEngine::GenerateQuestSaylink("#list npcs", false, "NPC") + "] "; - menu_commands_search += "[" + EQ::SayLinkEngine::GenerateQuestSaylink("#list players", false, "Players") + "] "; - menu_commands_search += "[" + EQ::SayLinkEngine::GenerateQuestSaylink("#list corpses", false, "Corpses") + "] "; - menu_commands_search += "[" + EQ::SayLinkEngine::GenerateQuestSaylink("#list doors", false, "Doors") + "] "; - menu_commands_search += "[" + EQ::SayLinkEngine::GenerateQuestSaylink("#list objects", false, "Objects") + "] "; - std::string dev_tools_window_key = StringFormat("%i-dev-tools-window-disabled", c->AccountID()); /** @@ -5471,19 +5606,7 @@ void command_devtools(Client *c, const Seperator *sep) c->SetDevToolsWindowEnabled(true); } - /** - * Show window status - */ - window_toggle_command = "Disabled [" + EQ::SayLinkEngine::GenerateQuestSaylink("#devtools enable_window", false, "Enable") + "] "; - if (c->IsDevToolsWindowEnabled()) { - window_toggle_command = "Enabled [" + EQ::SayLinkEngine::GenerateQuestSaylink("#devtools disable_window", false, "Disable") + "] "; - } - - /** - * Print menu - */ - c->Message(Chat::White, "| [Devtools] Window %s", window_toggle_command.c_str()); - c->Message(Chat::White, "| [Devtools] Search %s", menu_commands_search.c_str()); + c->ShowDevToolsMenu(); } void command_repop(Client *c, const Seperator *sep) diff --git a/zone/command.h b/zone/command.h index 36f84d934..87e01ae49 100644 --- a/zone/command.h +++ b/zone/command.h @@ -290,6 +290,7 @@ void command_showskills(Client *c, const Seperator *sep); void command_showspellslist(Client *c, const Seperator *sep); void command_showstats(Client *c, const Seperator *sep); void command_showzonegloballoot(Client *c, const Seperator *sep); +void command_showzonepoints(Client *c, const Seperator *sep); void command_shutdown(Client *c, const Seperator *sep); void command_size(Client *c, const Seperator *sep); void command_spawn(Client *c, const Seperator *sep); diff --git a/zone/npc.cpp b/zone/npc.cpp index b0b9e65f7..2cd5cd095 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -1118,6 +1118,44 @@ void NPC::SpawnGridNodeNPC(const glm::vec4 &position, int32 grid_number, int32 z entity_list.AddNPC(npc); } +void NPC::SpawnZonePointNodeNPC(std::string name, const glm::vec4 &position) +{ + auto npc_type = new NPCType; + memset(npc_type, 0, sizeof(NPCType)); + + char node_name[64]; + strn0cpy(node_name, name.c_str(), 64); + + strcpy(npc_type->name, entity_list.MakeNameUnique(node_name)); + + npc_type->current_hp = 4000000; + npc_type->max_hp = 4000000; + npc_type->race = 2254; + npc_type->gender = 2; + npc_type->class_ = 9; + npc_type->deity = 1; + npc_type->level = 200; + npc_type->npc_id = 0; + npc_type->loottable_id = 0; + npc_type->texture = 1; + npc_type->light = 1; + npc_type->size = 5; + npc_type->runspeed = 0; + npc_type->merchanttype = 1; + npc_type->bodytype = 1; + npc_type->show_name = true; + npc_type->findable = true; + + auto node_position = glm::vec4(position.x, position.y, position.z, position.w); + auto npc = new NPC(npc_type, nullptr, node_position, GravityBehavior::Flying); + + npc->name[strlen(npc->name)-3] = (char) NULL; + + npc->GiveNPCTypeData(npc_type); + + entity_list.AddNPC(npc); +} + NPC * NPC::SpawnNodeNPC(std::string name, std::string last_name, const glm::vec4 &position) { auto npc_type = new NPCType; memset(npc_type, 0, sizeof(NPCType)); diff --git a/zone/npc.h b/zone/npc.h index 37bf88f8e..12c6df6fd 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -115,6 +115,7 @@ public: static NPC *SpawnNodeNPC(std::string name, std::string last_name, const glm::vec4 &position); static void SpawnGridNodeNPC(const glm::vec4 &position, int32 grid_number, int32 zoffset); + static void SpawnZonePointNodeNPC(std::string name, const glm::vec4 &position); //abstract virtual function implementations requird by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQ::skills::SkillType attack_skill); diff --git a/zone/spells.cpp b/zone/spells.cpp index 8e70df06d..282d8d0d4 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -101,6 +101,7 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) #endif #include "mob_movement_manager.h" +#include "client.h" extern Zone* zone; @@ -6004,3 +6005,4 @@ bool Client::IsLinkedSpellReuseTimerReady(uint32 timer_id) return GetPTimers().Expired(&database, pTimerLinkedSpellReuseStart + timer_id, false); } + diff --git a/zone/zone.cpp b/zone/zone.cpp index 01850dc93..9997f9ac9 100755 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -58,6 +58,7 @@ #include "zone_reload.h" #include "../common/repositories/criteria/content_filter_criteria.h" #include "../common/repositories/content_flags_repository.h" +#include "../common/repositories/zone_points_repository.h" #include #include @@ -1944,41 +1945,59 @@ bool ZoneDatabase::LoadStaticZonePoints(LinkedList *zone_point_list { zone_point_list->Clear(); zone->numzonepoints = 0; + zone->virtual_zone_point_list.clear(); - std::string query = StringFormat( - "SELECT x, y, z, target_x, target_y, " - "target_z, target_zone_id, heading, target_heading, " - "number, target_instance, client_version_mask " - "FROM zone_points WHERE zone='%s' AND (version=%i OR version=-1) %s" - "ORDER BY number", - zonename, - version, - ContentFilterCriteria::apply().c_str() + auto zone_points = ZonePointsRepository::GetWhere( + fmt::format( + "zone = '{}' AND (version = {} OR version = -1) {} ORDER BY number", + zonename, + version, + ContentFilterCriteria::apply() + ) ); - auto results = QueryDatabase(query); - if (!results.Success()) { - return false; - } - - for (auto row = results.begin(); row != results.end(); ++row) { + for (auto &zone_point : zone_points) { auto zp = new ZonePoint; - zp->x = atof(row[0]); - zp->y = atof(row[1]); - zp->z = atof(row[2]); - zp->target_x = atof(row[3]); - zp->target_y = atof(row[4]); - zp->target_z = atof(row[5]); - zp->target_zone_id = atoi(row[6]); - zp->heading = atof(row[7]); - zp->target_heading = atof(row[8]); - zp->number = atoi(row[9]); - zp->target_zone_instance = atoi(row[10]); - zp->client_version_mask = (uint32)strtoul(row[11], nullptr, 0); + zp->x = zone_point.x; + zp->y = zone_point.y; + zp->z = zone_point.z; + zp->target_x = zone_point.target_x; + zp->target_y = zone_point.target_y; + zp->target_z = zone_point.target_z; + zp->target_zone_id = zone_point.target_zone_id; + zp->heading = zone_point.heading; + zp->target_heading = zone_point.target_heading; + zp->number = zone_point.number; + zp->target_zone_instance = zone_point.target_instance; + zp->client_version_mask = zone_point.client_version_mask; + zp->is_virtual = zone_point.is_virtual > 0; + zp->height = zone_point.height; + zp->width = zone_point.width; + + LogZonePoints( + "Loading ZP x [{}] y [{}] z [{}] heading [{}] target x y z zone_id instance_id [{}] [{}] [{}] [{}] [{}] number [{}] is_virtual [{}] height [{}] width [{}]", + zp->x, + zp->y, + zp->z, + zp->heading, + zp->target_x, + zp->target_y, + zp->target_z, + zp->target_zone_id, + zp->target_zone_instance, + zp->number, + zp->is_virtual ? "true" : "false", + zp->height, + zp->width + ); + + if (zone_point.is_virtual) { + zone->virtual_zone_point_list.emplace_back(zone_point); + continue; + } zone_point_list->Insert(zp); - zone->numzonepoints++; } @@ -2671,3 +2690,4 @@ void Zone::SetInstanceTimeRemaining(uint32 instance_time_remaining) { Zone::instance_time_remaining = instance_time_remaining; } + diff --git a/zone/zone.h b/zone/zone.h index 75fd9d4cb..821165fe2 100755 --- a/zone/zone.h +++ b/zone/zone.h @@ -28,6 +28,7 @@ #include "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" @@ -48,6 +49,9 @@ struct ZonePoint { uint16 target_zone_id; int32 target_zone_instance; uint32 client_version_mask; + bool is_virtual; + int height; + int width; }; struct ZoneClientAuth_Struct { @@ -171,10 +175,12 @@ public: int SaveTempItem(uint32 merchantid, uint32 npcid, uint32 item, int32 charges, bool sold = false); int32 MobsAggroCount() { return aggroedmobs; } - IPathfinder *pathing; - LinkedList NPCEmoteList; - LinkedList spawn2_list; - LinkedList zone_point_list; + IPathfinder *pathing; + LinkedList NPCEmoteList; + LinkedList spawn2_list; + LinkedList zone_point_list; + std::vector virtual_zone_point_list; + Map *zonemap; MercTemplate *GetMercTemplate(uint32 template_id); NewZone_Struct newzone_data; diff --git a/zone/zoning.cpp b/zone/zoning.cpp index 2e0b46d78..ac8732e82 100644 --- a/zone/zoning.cpp +++ b/zone/zoning.cpp @@ -336,6 +336,10 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) { } } + if (content_service.GetCurrentExpansion() >= Expansion::Classic && GetGM()) { + LogInfo("[{}] Bypassing Expansion zone checks because GM status is set", GetCleanName()); + } + if(myerror == 1) { //we have successfully zoned DoZoneSuccess(zc, target_zone_id, target_instance_id, dest_x, dest_y, dest_z, dest_h, ignorerestrictions);