Map Editor

RD Core / Commit #3

Commit Map Editor

Alex Alex committed 18/10/2026 23:40 main Patch
436 files +250,791 -0
A RD_Map_Editor/source/map_display.h +234-0 View file
@@ -0,0 +1,234 @@
1+//////////////////////////////////////////////////////////////////////
2+// This file is part of Remere's Map Editor
3+//////////////////////////////////////////////////////////////////////
4+// Remere's Map Editor is free software: you can redistribute it and/or modify
5+// it under the terms of the GNU General Public License as published by
6+// the Free Software Foundation, either version 3 of the License, or
7+// (at your option) any later version.
8+//
9+// Remere's Map Editor is distributed in the hope that it will be useful,
10+// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+// GNU General Public License for more details.
13+//
14+// You should have received a copy of the GNU General Public License
15+// along with this program. If not, see <http://www.gnu.org/licenses/>.
16+//////////////////////////////////////////////////////////////////////
17+
18+#ifndef RME_DISPLAY_WINDOW_H_
19+#define RME_DISPLAY_WINDOW_H_
20+
21+#include "action.h"
22+#include "tile.h"
23+#include "creature.h"
24+
25+class Item;
26+class Creature;
27+class MapWindow;
28+class MapPopupMenu;
29+class AnimationTimer;
30+class MapDrawer;
31+
32+class MapCanvas : public wxGLCanvas {
33+public:
34+ MapCanvas(MapWindow* parent, Editor& editor, int* attriblist);
35+ virtual ~MapCanvas();
36+ void Reset();
37+
38+ // All events
39+ void OnPaint(wxPaintEvent& event);
40+ void OnEraseBackground(wxEraseEvent& event) { }
41+
42+ void OnMouseMove(wxMouseEvent& event);
43+ void OnMouseLeftRelease(wxMouseEvent& event);
44+ void OnMouseLeftClick(wxMouseEvent& event);
45+ void OnMouseLeftDoubleClick(wxMouseEvent& event);
46+ void OnMouseCenterClick(wxMouseEvent& event);
47+ void OnMouseCenterRelease(wxMouseEvent& event);
48+ void OnMouseRightClick(wxMouseEvent& event);
49+ void OnMouseRightRelease(wxMouseEvent& event);
50+
51+ void OnKeyDown(wxKeyEvent& event);
52+ void OnKeyUp(wxKeyEvent& event);
53+ void OnWheel(wxMouseEvent& event);
54+ void OnGainMouse(wxMouseEvent& event);
55+ void OnLoseMouse(wxMouseEvent& event);
56+
57+
58+ // Mouse events handlers (called by the above)
59+ void OnMouseActionRelease(wxMouseEvent& event);
60+ void OnMouseActionClick(wxMouseEvent& event);
61+ void OnMouseCameraClick(wxMouseEvent& event);
62+ void OnMouseCameraRelease(wxMouseEvent& event);
63+ void OnMousePropertiesClick(wxMouseEvent& event);
64+ void OnMousePropertiesRelease(wxMouseEvent& event);
65+
66+ //
67+ void OnCut(wxCommandEvent& event);
68+ void OnCopy(wxCommandEvent& event);
69+ void OnCopyPosition(wxCommandEvent& event);
70+ void OnCopyServerId(wxCommandEvent& event);
71+ void OnCopyClientId(wxCommandEvent& event);
72+ void OnCopyName(wxCommandEvent& event);
73+ void OnBrowseTile(wxCommandEvent& event);
74+ void OnPaste(wxCommandEvent& event);
75+ void OnDelete(wxCommandEvent& event);
76+ // ----
77+ void OnGotoDestination(wxCommandEvent& event);
78+ void OnRotateItem(wxCommandEvent& event);
79+ void OnSwitchDoor(wxCommandEvent& event);
80+ // ----
81+ void OnSelectRAWBrush(wxCommandEvent& event);
82+ void OnSelectGroundBrush(wxCommandEvent& event);
83+ void OnSelectDoodadBrush(wxCommandEvent& event);
84+ void OnSelectDoorBrush(wxCommandEvent& event);
85+ void OnSelectWallBrush(wxCommandEvent& event);
86+ void OnSelectCarpetBrush(wxCommandEvent& event);
87+ void OnSelectTableBrush(wxCommandEvent& event);
88+ void OnSelectCreatureBrush(wxCommandEvent& event);
89+ void OnSelectSpawnBrush(wxCommandEvent& event);
90+ void OnSelectHouseBrush(wxCommandEvent& event);
91+ void OnSelectCollectionBrush(wxCommandEvent& event);
92+ void OnSelectMoveTo(wxCommandEvent& event);
93+
94+ void OnFindSimilarItems(wxCommandEvent& event);
95+ void OnGenerateIsland(wxCommandEvent& event);
96+ void OnCreateHouse(wxCommandEvent& event);
97+
98+ void OnSelectionToDoodad(wxCommandEvent& event);
99+ // ---
100+ void OnProperties(wxCommandEvent& event);
101+ void OnFill(wxCommandEvent& event);
102+
103+ void Refresh();
104+
105+ void ScreenToMap(int screen_x, int screen_y, int* map_x, int* map_y);
106+ void GetScreenCenter(int* map_x, int* map_y);
107+
108+ void StartPasting();
109+ void EndPasting();
110+ void EnterSelectionMode();
111+ void EnterDrawingMode();
112+
113+ void UpdatePositionStatus(int x = -1, int y = -1);
114+ void UpdateZoomStatus();
115+
116+ void ChangeFloor(int new_floor);
117+ int GetFloor() const {
118+ return floor;
119+ }
120+ double GetZoom() const {
121+ return zoom;
122+ }
123+ void SetZoom(double value);
124+ void GetViewBox(int* view_scroll_x, int* view_scroll_y, int* screensize_x, int* screensize_y) const;
125+
126+ Position GetCursorPosition() const;
127+
128+ void TakeScreenshot(wxFileName path, wxString format);
129+
130+ void MouseToMap(int* map_x, int* map_y) {
131+ ScreenToMap(cursor_x, cursor_y, map_x, map_y);
132+ }
133+
134+protected:
135+ void getTilesToDraw(int mouse_map_x, int mouse_map_y, int floor, PositionVector* tilestodraw, PositionVector* tilestoborder, bool fill = false);
136+ bool floodFill(Map* map, const Position& center, int x, int y, GroundBrush* brush, PositionVector* positions);
137+ bool hasHouseWall(Tile* tile);
138+ bool hasDoor(Tile* tile);
139+ bool hasStairsOrLadder(Tile* tile);
140+
141+private:
142+ enum {
143+ BLOCK_SIZE = 100
144+ };
145+
146+ inline int getFillIndex(int x, int y) const {
147+ return x + BLOCK_SIZE * y;
148+ }
149+
150+ static bool processed[BLOCK_SIZE * BLOCK_SIZE];
151+
152+ Editor& editor;
153+ MapDrawer* drawer;
154+ int keyCode;
155+ int countMaxFills = 0;
156+
157+ // View related
158+ int floor;
159+ double zoom;
160+ int cursor_x;
161+ int cursor_y;
162+
163+ bool dragging;
164+ bool boundbox_selection;
165+ bool screendragging;
166+ bool isPasting() const;
167+ bool drawing;
168+ bool dragging_draw;
169+ bool replace_dragging;
170+
171+ uint8_t* screenshot_buffer;
172+
173+ int drag_start_x;
174+ int drag_start_y;
175+ int drag_start_z;
176+
177+ int last_cursor_map_x;
178+ int last_cursor_map_y;
179+ int last_cursor_map_z;
180+
181+ int last_click_map_x;
182+ int last_click_map_y;
183+ int last_click_map_z;
184+ int last_click_abs_x;
185+ int last_click_abs_y;
186+ int last_click_x;
187+ int last_click_y;
188+
189+ int last_mmb_click_x;
190+ int last_mmb_click_y;
191+
192+ int view_scroll_x;
193+ int view_scroll_y;
194+
195+ uint32_t current_house_id;
196+
197+ wxStopWatch refresh_watch;
198+ MapPopupMenu* popup_menu;
199+ AnimationTimer* animation_timer;
200+
201+ bool show_fill_warning = true;
202+
203+ friend class MapDrawer;
204+
205+ DECLARE_EVENT_TABLE()
206+};
207+
208+// Right-click popup menu
209+class MapPopupMenu : public wxMenu {
210+public:
211+ MapPopupMenu(Editor& editor);
212+ virtual ~MapPopupMenu();
213+
214+ void Update();
215+
216+protected:
217+ Editor& editor;
218+};
219+
220+class AnimationTimer : public wxTimer {
221+public:
222+ AnimationTimer(MapCanvas* canvas);
223+ ~AnimationTimer();
224+
225+ void Notify();
226+ void Start();
227+ void Stop();
228+
229+private:
230+ MapCanvas* map_canvas;
231+ bool started;
232+};
233+
234+#endif
A RD_Map_Editor/source/map_drawer.h +289-0 View file
@@ -0,0 +1,289 @@
1+//////////////////////////////////////////////////////////////////////
2+// This file is part of Remere's Map Editor
3+//////////////////////////////////////////////////////////////////////
4+// Remere's Map Editor is free software: you can redistribute it and/or modify
5+// it under the terms of the GNU General Public License as published by
6+// the Free Software Foundation, either version 3 of the License, or
7+// (at your option) any later version.
8+//
9+// Remere's Map Editor is distributed in the hope that it will be useful,
10+// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+// GNU General Public License for more details.
13+//
14+// You should have received a copy of the GNU General Public License
15+// along with this program. If not, see <http://www.gnu.org/licenses/>.
16+//////////////////////////////////////////////////////////////////////
17+
18+#include "lod_manager.h"
19+#ifndef RME_MAP_DRAWER_H_
20+#define RME_MAP_DRAWER_H_
21+
22+#include <iostream>
23+#include <unordered_set>
24+#include <unordered_map>
25+#include <memory>
26+
27+class GameSprite;
28+
29+struct MapTooltip {
30+ enum TextLength {
31+ MAX_CHARS_PER_LINE = 40,
32+ MAX_CHARS = 255,
33+ };
34+
35+ MapTooltip(int x, int y, std::string text, uint8_t r, uint8_t g, uint8_t b) :
36+ x(x), y(y), text(text), r(r), g(g), b(b) {
37+ ellipsis = (text.length() - 3) > MAX_CHARS;
38+ }
39+
40+ void checkLineEnding() {
41+ if (text.at(text.size() - 1) == '\n') {
42+ text.resize(text.size() - 1);
43+ }
44+ }
45+
46+ int x, y;
47+ std::string text;
48+ uint8_t r, g, b;
49+ bool ellipsis;
50+};
51+
52+// Storage during drawing, for option caching
53+struct DrawingOptions {
54+ DrawingOptions();
55+
56+ void SetIngame();
57+ void SetDefault();
58+ bool isDrawLight() const noexcept;
59+
60+ bool transparent_floors;
61+ bool transparent_items;
62+ bool show_ingame_box;
63+ bool show_lights;
64+ bool show_light_str;
65+ bool show_tech_items;
66+ bool show_waypoints;
67+ bool ingame;
68+ bool dragging;
69+
70+ int show_grid;
71+ bool show_all_floors;
72+ bool show_creatures;
73+ bool show_spawns;
74+ bool show_houses;
75+ bool show_shade;
76+ bool show_special_tiles;
77+ bool show_zone_areas;
78+ bool show_items;
79+
80+ bool highlight_items;
81+ bool highlight_locked_doors;
82+ bool show_blocking;
83+ bool show_tooltips;
84+ bool show_as_minimap;
85+ bool show_only_colors;
86+ bool show_only_modified;
87+ bool show_preview;
88+ bool show_hooks;
89+ bool hide_items_when_zoomed;
90+ bool show_towns;
91+ bool always_show_zones;
92+ bool extended_house_shader;
93+
94+ bool experimental_fog;
95+};
96+
97+class MapCanvas;
98+class LightDrawer;
99+
100+struct FinderPosition {
101+ FinderPosition() { }
102+ FinderPosition(int _x, int _y, int _z) :
103+ x(_x), y(_y), z(_z) { }
104+ int x, y, z;
105+
106+ bool operator==(const FinderPosition& other) const {
107+ return x == other.x && y == other.y && z == other.z;
108+ }
109+
110+ double distance(const FinderPosition& b) const {
111+ return std::sqrt(std::pow(x - b.x, 2) + std::pow(y - b.y, 2));
112+ }
113+
114+ struct Hash {
115+ size_t operator()(const FinderPosition& p) const {
116+ return p.x ^ p.y ^ p.z;
117+ }
118+ };
119+};
120+
121+class ZoneFinder {
122+private:
123+ std::unordered_set<FinderPosition, FinderPosition::Hash> positions;
124+ std::vector<std::vector<FinderPosition>> zones;
125+ std::unordered_set<FinderPosition, FinderPosition::Hash> visited;
126+
127+ bool isValid(const FinderPosition& pos) {
128+ return positions.find(pos) != positions.end() && visited.find(pos) == visited.end();
129+ }
130+
131+ void dfs(const FinderPosition& pos, std::vector<FinderPosition>& zone) {
132+ if (visited.find(pos) != visited.end()) {
133+ return;
134+ }
135+
136+ visited.insert(pos);
137+ zone.push_back(pos);
138+
139+ std::vector<FinderPosition> neighbors = {
140+ { pos.x + 1, pos.y, pos.z },
141+ { pos.x - 1, pos.y, pos.z },
142+ { pos.x, pos.y + 1, pos.z },
143+ { pos.x, pos.y - 1, pos.z }
144+ };
145+
146+ for (const auto& next : neighbors) {
147+ if (isValid(next)) {
148+ dfs(next, zone);
149+ }
150+ }
151+ }
152+
153+public:
154+ ZoneFinder(const std::vector<FinderPosition>& inputPositions) :
155+ positions(inputPositions.begin(), inputPositions.end()) { }
156+
157+ std::vector<std::vector<FinderPosition>> findZones() {
158+ for (const auto& pos : positions) {
159+ if (visited.find(pos) == visited.end()) {
160+ std::vector<FinderPosition> zone;
161+ dfs(pos, zone);
162+ zones.push_back(zone);
163+ }
164+ }
165+
166+ return zones;
167+ }
168+
169+ FinderPosition findClosestToCenter(const std::vector<FinderPosition>& zone) {
170+ FinderPosition centroid = { 0, 0, 0 };
171+ for (const auto& pos : zone) {
172+ centroid.x += pos.x;
173+ centroid.y += pos.y;
174+ centroid.z += pos.z;
175+ }
176+
177+ centroid.x /= zone.size();
178+ centroid.y /= zone.size();
179+ centroid.z /= zone.size();
180+
181+ double minDistance = std::numeric_limits<double>::max();
182+ FinderPosition closestPosition;
183+ for (const auto& pos : zone) {
184+ const double dist = pos.distance(centroid);
185+ if (dist < minDistance) {
186+ minDistance = dist;
187+ closestPosition = pos;
188+ }
189+ }
190+
191+ return closestPosition;
192+ }
193+};
194+
195+class MapDrawer {
196+ MapCanvas* canvas;
197+ Editor& editor;
198+ DrawingOptions options;
199+ std::shared_ptr<LightDrawer> light_drawer;
200+ LODManager lod_manager;
201+
202+ float zoom;
203+
204+ uint32_t current_house_id;
205+
206+ int mouse_map_x, mouse_map_y;
207+ int start_x, start_y, start_z;
208+ int end_x, end_y, end_z, superend_z;
209+ int view_scroll_x, view_scroll_y;
210+ int screensize_x, screensize_y;
211+ int tile_size;
212+ int floor;
213+
214+protected:
215+ std::unordered_map<uint16_t, std::vector<FinderPosition>> zoneTiles;
216+ std::vector<MapTooltip*> tooltips;
217+ std::ostringstream tooltip;
218+
219+public:
220+ MapDrawer(MapCanvas* canvas);
221+ ~MapDrawer();
222+
223+ bool dragging;
224+ bool dragging_draw;
225+
226+ void SetupVars();
227+ void SetupGL();
228+ void Release();
229+
230+ void Draw();
231+ void DrawBackground();
232+ void DrawMap();
233+ void DrawDraggingShadow();
234+ void DrawHigherFloors();
235+ void DrawSelectionBox();
236+ void DrawLiveCursors();
237+ void DrawBrush();
238+ void DrawIngameBox();
239+ void DrawGrid();
240+ void DrawTooltips();
241+ void DrawLight();
242+
243+
244+
245+ void TakeScreenshot(uint8_t* screenshot_buffer);
246+
247+ DrawingOptions& getOptions() {
248+ return options;
249+ }
250+
251+protected:
252+ void BlitItem(int& screenx, int& screeny, const Tile* tile, Item* item, bool ephemeral = false, int red = 255, int green = 255, int blue = 255, int alpha = 255);
253+ void BlitItem(int& screenx, int& screeny, const Position& pos, Item* item, bool ephemeral = false, int red = 255, int green = 255, int blue = 255, int alpha = 255, const Tile* tile = nullptr);
254+ void BlitSpriteType(int screenx, int screeny, uint32_t spriteid, int red = 255, int green = 255, int blue = 255, int alpha = 255);
255+ void BlitSpriteType(int screenx, int screeny, GameSprite* spr, int red = 255, int green = 255, int blue = 255, int alpha = 255);
256+ void BlitCreature(int screenx, int screeny, const Creature* c, int red = 255, int green = 255, int blue = 255, int alpha = 255);
257+ void BlitCreature(int screenx, int screeny, const Outfit& outfit, Direction dir, int red = 255, int green = 255, int blue = 255, int alpha = 255);
258+ void BlitSquare(int sx, int sy, int red, int green, int blue, int alpha, int size = 0);
259+ void DrawRawBrush(int screenx, int screeny, ItemType* itemType, uint8_t r, uint8_t g, uint8_t b, uint8_t alpha);
260+ void DrawTile(TileLocation* tile);
261+ void DrawBrushIndicator(int x, int y, Brush* brush, uint8_t r, uint8_t g, uint8_t b);
262+ void DrawHookIndicator(int x, int y, const ItemType& type);
263+ void WriteTooltip(Tile* tile, Item* item, std::ostringstream& stream, bool isHouseTile);
264+ void WriteTooltip(Waypoint* item, std::ostringstream& stream);
265+ void MakeTooltip(int screenx, int screeny, const std::string& text, uint8_t r = 255, uint8_t g = 255, uint8_t b = 255);
266+ void AddLight(TileLocation* location);
267+
268+ enum BrushColor {
269+ COLOR_BRUSH,
270+ COLOR_HOUSE_BRUSH,
271+ COLOR_FLAG_BRUSH,
272+ COLOR_SPAWN_BRUSH,
273+ COLOR_ERASER,
274+ COLOR_VALID,
275+ COLOR_INVALID,
276+ COLOR_BLANK,
277+ };
278+
279+ void getColor(Brush* brush, const Position& position, uint8_t& r, uint8_t& g, uint8_t& b);
280+ void glBlitTexture(int sx, int sy, int texture_number, int red, int green, int blue, int alpha);
281+ void glBlitSquare(int sx, int sy, int red, int green, int blue, int alpha, int size = 0);
282+ void glColor(wxColor color);
283+ void glColor(BrushColor color);
284+ void glColorCheck(Brush* brush, const Position& pos);
285+ void drawRect(int x, int y, int w, int h, const wxColor& color, int width = 1);
286+ void drawFilledRect(int x, int y, int w, int h, const wxColor& color);
287+};
288+
289+#endif
A RD_Map_Editor/source/map_region.cpp +258-0 View file
@@ -0,0 +1,258 @@
1+//////////////////////////////////////////////////////////////////////
2+// This file is part of Remere's Map Editor
3+//////////////////////////////////////////////////////////////////////
4+// Remere's Map Editor is free software: you can redistribute it and/or modify
5+// it under the terms of the GNU General Public License as published by
6+// the Free Software Foundation, either version 3 of the License, or
7+// (at your option) any later version.
8+//
9+// Remere's Map Editor is distributed in the hope that it will be useful,
10+// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+// GNU General Public License for more details.
13+//
14+// You should have received a copy of the GNU General Public License
15+// along with this program. If not, see <http://www.gnu.org/licenses/>.
16+//////////////////////////////////////////////////////////////////////
17+
18+#include "main.h"
19+
20+#include "map_region.h"
21+#include "basemap.h"
22+#include "position.h"
23+#include "tile.h"
24+
25+//**************** Tile Location **********************
26+
27+TileLocation::TileLocation() :
28+ tile(nullptr),
29+ position(0, 0, 0),
30+ spawn_count(0),
31+ waypoint_count(0),
32+ town_count(0),
33+ house_exits(nullptr) {
34+ ////
35+}
36+
37+TileLocation::~TileLocation() {
38+ delete tile;
39+ delete house_exits;
40+}
41+
42+int TileLocation::size() const {
43+ if (tile) {
44+ return tile->size();
45+ }
46+ return spawn_count + waypoint_count + (house_exits ? 1 : 0);
47+}
48+
49+bool TileLocation::empty() const {
50+ return size() == 0;
51+}
52+
53+//**************** Floor **********************
54+
55+Floor::Floor(int sx, int sy, int z) {
56+ sx = sx & ~3;
57+ sy = sy & ~3;
58+
59+ for (int i = 0; i < MAP_LAYERS; ++i) {
60+ locs[i].position.x = sx + (i >> 2);
61+ locs[i].position.y = sy + (i & 3);
62+ locs[i].position.z = z;
63+ }
64+}
65+
66+//**************** QTreeNode **********************
67+
68+QTreeNode::QTreeNode(BaseMap& map) :
69+ map(map),
70+ visible(0),
71+ isLeaf(false) {
72+ // Doesn't matter if we're leaf or node
73+ for (int i = 0; i < MAP_LAYERS; ++i) {
74+ child[i] = nullptr;
75+ }
76+}
77+
78+QTreeNode::~QTreeNode() {
79+ if (isLeaf) {
80+ for (int i = 0; i < MAP_LAYERS; ++i) {
81+ delete array[i];
82+ }
83+ } else {
84+ for (int i = 0; i < MAP_LAYERS; ++i) {
85+ delete child[i];
86+ }
87+ }
88+}
89+
90+QTreeNode* QTreeNode::getLeaf(int x, int y) {
91+ QTreeNode* node = this;
92+ uint32_t cx = x, cy = y;
93+ while (node) {
94+ if (node->isLeaf) {
95+ return node;
96+ } else {
97+ uint32_t index = ((cx & 0xC000) >> 14) | ((cy & 0xC000) >> 12);
98+ if (node->child[index]) {
99+ node = node->child[index];
100+ cx <<= 2;
101+ cy <<= 2;
102+ } else {
103+ return nullptr;
104+ }
105+ }
106+ }
107+ return nullptr;
108+}
109+
110+QTreeNode* QTreeNode::getLeafForce(int x, int y) {
111+ QTreeNode* node = this;
112+ uint32_t cx = x, cy = y;
113+ int level = 6;
114+ while (node) {
115+ uint32_t index = ((cx & 0xC000) >> 14) | ((cy & 0xC000) >> 12);
116+
117+ QTreeNode*& qt = node->child[index];
118+ if (qt) {
119+ if (qt->isLeaf) {
120+ return qt;
121+ }
122+
123+ } else {
124+ if (level == 0) {
125+ qt = newd QTreeNode(map);
126+ qt->isLeaf = true;
127+ return qt;
128+ } else {
129+ qt = newd QTreeNode(map);
130+ }
131+ }
132+ node = node->child[index];
133+ cx <<= 2;
134+ cy <<= 2;
135+ level -= 1;
136+ }
137+
138+ return nullptr;
139+}
140+
141+Floor* QTreeNode::createFloor(int x, int y, int z) {
142+ ASSERT(isLeaf);
143+ if (!array[z]) {
144+ array[z] = newd Floor(x, y, z);
145+ }
146+ return array[z];
147+}
148+
149+bool QTreeNode::isVisible(bool underground) {
150+ return testFlags(visible, underground + 1);
151+}
152+
153+bool QTreeNode::isRequested(bool underground) {
154+ if (underground) {
155+ return testFlags(visible, 4);
156+ } else {
157+ return testFlags(visible, 8);
158+ }
159+}
160+
161+void QTreeNode::clearVisible(uint32_t u) {
162+ if (isLeaf) {
163+ visible &= u;
164+ } else {
165+ for (int i = 0; i < MAP_LAYERS; ++i) {
166+ if (child[i]) {
167+ child[i]->clearVisible(u);
168+ }
169+ }
170+ }
171+}
172+
173+bool QTreeNode::isVisible(uint32_t client, bool underground) {
174+ if (underground) {
175+ return testFlags(visible >> MAP_LAYERS, static_cast<uint64_t>(1) << client);
176+ } else {
177+ return testFlags(visible, static_cast<uint64_t>(1) << client);
178+ }
179+}
180+
181+void QTreeNode::setVisible(bool underground, bool value) {
182+ if (underground) {
183+ if (value) {
184+ visible |= 2;
185+ } else {
186+ visible &= ~2;
187+ }
188+ } else { // overground
189+ if (value) {
190+ visible |= 1;
191+ } else {
192+ visible &= 1;
193+ }
194+ }
195+}
196+
197+void QTreeNode::setRequested(bool underground, bool r) {
198+ if (r) {
199+ visible |= (underground ? 4 : 8);
200+ } else {
201+ visible &= ~(underground ? 4 : 8);
202+ }
203+}
204+
205+void QTreeNode::setVisible(uint32_t client, bool underground, bool value) {
206+ if (value) {
207+ visible |= (1 << client << (underground ? MAP_LAYERS : 0));
208+ } else {
209+ visible &= ~(1 << client << (underground ? MAP_LAYERS : 0));
210+ }
211+}
212+
213+TileLocation* QTreeNode::getTile(int x, int y, int z) {
214+ ASSERT(isLeaf);
215+ Floor* f = array[z];
216+ if (!f) {
217+ return nullptr;
218+ }
219+ return &f->locs[(x & 3) * 4 + (y & 3)];
220+}
221+
222+TileLocation* QTreeNode::createTile(int x, int y, int z) {
223+ ASSERT(isLeaf);
224+ Floor* f = createFloor(x, y, z);
225+ return &f->locs[(x & 3) * 4 + (y & 3)];
226+}
227+
228+Tile* QTreeNode::setTile(int x, int y, int z, Tile* newtile) {
229+ ASSERT(isLeaf);
230+ Floor* f = createFloor(x, y, z);
231+
232+ int offset_x = x & 3;
233+ int offset_y = y & 3;
234+
235+ TileLocation* tmp = &f->locs[offset_x * 4 + offset_y];
236+ Tile* oldtile = tmp->tile;
237+ tmp->tile = newtile;
238+
239+ if (newtile && !oldtile) {
240+ ++map.tilecount;
241+ } else if (oldtile && !newtile) {
242+ --map.tilecount;
243+ }
244+
245+ return oldtile;
246+}
247+
248+void QTreeNode::clearTile(int x, int y, int z) {
249+ ASSERT(isLeaf);
250+ Floor* f = createFloor(x, y, z);
251+
252+ int offset_x = x & 3;
253+ int offset_y = y & 3;
254+
255+ TileLocation* tmp = &f->locs[offset_x * 4 + offset_y];
256+ delete tmp->tile;
257+ tmp->tile = map.allocator(tmp);
258+}
Top