Skip to content

Commit a486d70

Browse files
authored
Merge pull request #2186 from JulienTant/highlight-locked-world-map-areas
Highlight locked areas on the world map
2 parents 2b09004 + 57c6504 commit a486d70

4 files changed

Lines changed: 83 additions & 12 deletions

File tree

GWToolboxdll/Utils/ToolboxUtils.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ namespace {
4646

4747
GW::Array<GW::AvailableCharacterInfo>* available_chars_ptr = nullptr;
4848

49+
constexpr uint32_t bogus_area_info_flags = 0x5000000; // e.g. "wrong" Augury Rock is map 119, no NPCs.
50+
constexpr uint32_t debug_area_info_flag = 0x80000000;
51+
4952
bool IsInfused(const GW::Item* item)
5053
{
5154
return item && item->info_string && wcschr(item->info_string, 0xAC9);
@@ -79,6 +82,18 @@ namespace {
7982
namespace GW {
8083

8184
namespace Map {
85+
bool HasMapDisplayInfo(const GW::AreaInfo* map_info)
86+
{
87+
return map_info && map_info->thumbnail_id && map_info->name_id && (map_info->x || map_info->y);
88+
}
89+
90+
bool IsExcludedMapInfo(const GW::AreaInfo* map_info)
91+
{
92+
return map_info
93+
&& ((map_info->flags & bogus_area_info_flags) == bogus_area_info_flags
94+
|| (map_info->flags & debug_area_info_flag) != 0);
95+
}
96+
8297
bool GetMapWorldMapBounds(GW::AreaInfo* map, ImRect* out)
8398
{
8499
if (!map) return false;

GWToolboxdll/Utils/ToolboxUtils.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ namespace GW {
146146
namespace Map {
147147
GW::Array<GW::MapProp*>* GetMapProps();
148148
bool GetMapWorldMapBounds(GW::AreaInfo* map, ImRect* out);
149+
bool HasMapDisplayInfo(const GW::AreaInfo* map_info);
150+
bool IsExcludedMapInfo(const GW::AreaInfo* map_info);
149151
std::vector<GW::Constants::TitleID> GetTitlesForMap(GW::Constants::MapID map_id);
150152
GW::Constants::TitleID GetTitleForMap(GW::Constants::MapID map_id);
151153

GWToolboxdll/Widgets/WorldMapWidget.cpp

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,14 @@
4040

4141
#include "Defines.h"
4242

43+
#include <Color.h>
4344
#include <GWCA/Managers/AgentMgr.h>
4445
#include <ImGuiAddons.h>
4546
#include <Modules/QuestModule.h>
4647
#include <Utils/ArenaNetFileParser.h>
4748
#include <Utils/TextUtils.h>
48-
#include <corecrt_math_defines.h>
4949
#include <Windows/Pathfinding/PathingMapDataLoader.h>
50+
#include <corecrt_math_defines.h>
5051

5152

5253

@@ -127,13 +128,15 @@ namespace {
127128
IDirect3DTexture9** zaishen_coin_texture = nullptr;
128129

129130
bool showing_all_outposts = false;
131+
bool highlight_locked_areas = false;
130132
bool apply_quest_colors = false;
131133
bool show_any_elite_capture_locations = false;
132134
bool show_elite_capture_locations[11];
133135
bool hide_captured_elites = false;
134136
bool drawn = false;
135137
bool show_lines_on_world_map = false;
136138
bool showing_all_quests = true;
139+
Color locked_area_highlight_color = IM_COL32(255, 160, 0, 96);
137140

138141
GW::MemoryPatcher view_all_outposts_patch;
139142
GW::MemoryPatcher view_all_carto_areas_patch;
@@ -371,9 +374,7 @@ namespace {
371374
bool IsValidOutpost(GW::Constants::MapID map_id)
372375
{
373376
const auto map_info = GW::Map::GetMapInfo(map_id);
374-
if (!map_info || !map_info->thumbnail_id || !map_info->name_id || !(map_info->x || map_info->y)) return false;
375-
if ((map_info->flags & 0x5000000) == 0x5000000) return false; // e.g. "wrong" augury rock is map 119, no NPCs
376-
if ((map_info->flags & 0x80000000) == 0x80000000) return false; // e.g. Debug map
377+
if (!GW::Map::HasMapDisplayInfo(map_info) || GW::Map::IsExcludedMapInfo(map_info)) return false;
377378
switch (map_info->type) {
378379
case GW::RegionType::City:
379380
case GW::RegionType::CompetitiveMission:
@@ -388,13 +389,28 @@ namespace {
388389
return true;
389390
}
390391

392+
bool IsHighlightableLockedArea(GW::Constants::MapID map_id, const GW::AreaInfo* map_info)
393+
{
394+
if (!(map_info && map_info->GetIsOnWorldMap())) return false;
395+
if (GW::Map::IsPreSearing(map_id) != GW::Map::IsPreSearing() || GW::Map::IsFestivalOutpost(map_id)) return false;
396+
if (GW::Map::IsExcludedMapInfo(map_info)) return false;
397+
switch (map_info->type) {
398+
case GW::RegionType::City:
399+
case GW::RegionType::CooperativeMission:
400+
case GW::RegionType::EliteMission:
401+
case GW::RegionType::MissionOutpost:
402+
case GW::RegionType::Outpost:
403+
return map_id != GW::Constants::MapID::Gate_of_Anguish_elite_mission;
404+
default:
405+
return false;
406+
}
407+
}
408+
391409
GW::Constants::MapID GetClosestMapToPoint(const GW::Vec2f& world_map_point)
392410
{
393411
for (size_t i = 0; i < (size_t)GW::Constants::MapID::Count; i++) {
394412
const auto map_info = GW::Map::GetMapInfo((GW::Constants::MapID)i);
395-
if (!map_info || !map_info->thumbnail_id || !map_info->name_id || !(map_info->x || map_info->y)) continue;
396-
if ((map_info->flags & 0x5000000) == 0x5000000) continue; // e.g. "wrong" augury rock is map 119, no NPCs
397-
if ((map_info->flags & 0x80000000) == 0x80000000) continue; // e.g. Debug map
413+
if (!GW::Map::HasMapDisplayInfo(map_info) || GW::Map::IsExcludedMapInfo(map_info)) continue;
398414
if (!map_info->GetIsOnWorldMap()) continue;
399415
(world_map_point);
400416
// TODO: distance from point to rect
@@ -849,6 +865,31 @@ namespace {
849865
}
850866
}
851867

868+
void DrawLockedAreaHighlights()
869+
{
870+
if (!(showing_all_outposts && highlight_locked_areas && world_map_context)) return;
871+
if (world_map_context->zoom != 1.f && world_map_context->zoom != .0f) return; // Map is animating
872+
if (!Colors::IsVisible(locked_area_highlight_color)) return;
873+
874+
std::unordered_set<uint32_t> highlighted_names;
875+
for (size_t i = 1; i < static_cast<size_t>(GW::Constants::MapID::Count); i++) {
876+
const auto map_id = static_cast<GW::Constants::MapID>(i);
877+
const auto map_info = GW::Map::GetMapInfo(map_id);
878+
if (!(IsHighlightableLockedArea(map_id, map_info) && map_info->continent == world_map_context->continent)) continue;
879+
if (map_info->name_id && highlighted_names.contains(map_info->name_id)) continue;
880+
if (GW::Map::GetIsMapUnlocked(map_id)) continue;
881+
882+
if (map_info->name_id) {
883+
highlighted_names.insert(map_info->name_id);
884+
}
885+
886+
const auto marker_pos = CalculateViewportPos(GetMapMarkerPoint(map_info), world_map_context->top_left);
887+
const auto radius = 8.f * ui_scale.x;
888+
draw_list->AddCircleFilled(marker_pos, radius, locked_area_highlight_color);
889+
draw_list->AddCircle(marker_pos, radius, Colors::FullAlpha(locked_area_highlight_color));
890+
}
891+
}
892+
852893
bool DrawPortalOnWorldMap(const MapPortal& portal)
853894
{
854895
if (!world_map_context) return false;
@@ -984,9 +1025,11 @@ void WorldMapWidget::LoadSettings(ToolboxIni* ini)
9841025
{
9851026
ToolboxWidget::LoadSettings(ini);
9861027
LOAD_BOOL(showing_all_outposts);
1028+
LOAD_BOOL(highlight_locked_areas);
9871029
LOAD_BOOL(show_lines_on_world_map);
9881030
LOAD_BOOL(showing_all_quests);
9891031
LOAD_BOOL(apply_quest_colors);
1032+
LOAD_COLOR(locked_area_highlight_color);
9901033
LOAD_BOOL(hide_captured_elites);
9911034
LOAD_BOOL(show_any_elite_capture_locations);
9921035
LOAD_BOOL(hide_captured_elites);
@@ -1040,9 +1083,11 @@ void WorldMapWidget::SaveSettings(ToolboxIni* ini)
10401083
{
10411084
ToolboxWidget::SaveSettings(ini);
10421085
SAVE_BOOL(showing_all_outposts);
1086+
SAVE_BOOL(highlight_locked_areas);
10431087
SAVE_BOOL(show_lines_on_world_map);
10441088
SAVE_BOOL(showing_all_quests);
10451089
SAVE_BOOL(apply_quest_colors);
1090+
SAVE_COLOR(locked_area_highlight_color);
10461091
SAVE_BOOL(show_any_elite_capture_locations);
10471092
SAVE_BOOL(hide_captured_elites);
10481093
uint32_t show_elite_capture_locations_val = 0;
@@ -1090,6 +1135,18 @@ void WorldMapWidget::Draw(IDirect3DDevice9*)
10901135
ShowAllOutposts(showing_all_outposts);
10911136
});
10921137
}
1138+
if (showing_all_outposts) {
1139+
ImGui::Indent();
1140+
ImGui::Checkbox("Highlight locked areas", &highlight_locked_areas);
1141+
if (highlight_locked_areas) {
1142+
ImGui::SameLine();
1143+
ImGui::ColorButtonPicker("Locked Areas", &locked_area_highlight_color, ImGuiColorEditFlags_NoLabel);
1144+
if (ImGui::IsItemHovered()) {
1145+
ImGui::SetTooltip("Color overlay for areas that aren't unlocked on this character.");
1146+
}
1147+
}
1148+
ImGui::Unindent();
1149+
}
10931150
if (GW::Map::GetInstanceType() == GW::Constants::InstanceType::Outpost) {
10941151
bool is_hard_mode = GW::PartyMgr::GetIsPartyInHardMode();
10951152
if (ImGui::Checkbox("Hard mode", &is_hard_mode)) {
@@ -1169,6 +1226,7 @@ void WorldMapWidget::Draw(IDirect3DDevice9*)
11691226
}
11701227
}
11711228
#endif
1229+
DrawLockedAreaHighlights();
11721230

11731231

11741232
hovered_boss = nullptr;

GWToolboxdll/Windows/TravelWindow.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,12 +143,8 @@ namespace {
143143
if (map_id == GW::Constants::MapID::Gate_of_Anguish_elite_mission)
144144
return false;
145145
const auto map_info = GW::Map::GetMapInfo(map_id);
146-
if (!map_info || !map_info->thumbnail_id || !map_info->name_id || !(map_info->x || map_info->y))
146+
if (!GW::Map::HasMapDisplayInfo(map_info) || GW::Map::IsExcludedMapInfo(map_info))
147147
return false;
148-
if ((map_info->flags & 0x5000000) == 0x5000000)
149-
return false; // e.g. "wrong" augury rock is map 119, no NPCs
150-
if ((map_info->flags & 0x80000000) == 0x80000000)
151-
return false; // e.g. Debug map)
152148
switch (map_info->type) {
153149
case GW::RegionType::City:
154150
case GW::RegionType::Challenge:

0 commit comments

Comments
 (0)