map.h

main 291 lines · 8.1 KB Raw
Alex Alex Commit Server upload 18/10/2026 23:38
1/**
2 * The Forgotten Server - a free and open-source MMORPG server emulator
3 * Copyright (C) 2019 Mark Samman <mark.samman@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20#ifndef FS_MAP_H_E3953D57C058461F856F5221D359DAFA
21#define FS_MAP_H_E3953D57C058461F856F5221D359DAFA
22
23#include "position.h"
24#include "item.h"
25#include "fileloader.h"
26
27#include "tools.h"
28#include "tile.h"
29#include "town.h"
30#include "house.h"
31#include "spawn.h"
32
33class Creature;
34class Player;
35class Game;
36class Tile;
37class Map;
38
39static constexpr int32_t MAP_MAX_LAYERS = 16;
40
41struct FindPathParams;
42struct AStarNode {
43 AStarNode* parent;
44 int_fast32_t f;
45 uint16_t x, y;
46};
47
48static constexpr int32_t MAX_NODES = 512;
49
50static constexpr int32_t MAP_NORMALWALKCOST = 10;
51static constexpr int32_t MAP_DIAGONALWALKCOST = 25;
52
53class AStarNodes
54{
55 public:
56 AStarNodes(uint32_t x, uint32_t y);
57
58 AStarNode* createOpenNode(AStarNode* parent, uint32_t x, uint32_t y, int_fast32_t f);
59 AStarNode* getBestNode();
60 void closeNode(AStarNode* node);
61 void openNode(AStarNode* node);
62 int_fast32_t getClosedNodes() const;
63 AStarNode* getNodeByPosition(uint32_t x, uint32_t y);
64
65 static int_fast32_t getMapWalkCost(AStarNode* node, const Position& neighborPos);
66 static int_fast32_t getTileWalkCost(const Creature& creature, const Tile* tile);
67
68 private:
69 AStarNode nodes[MAX_NODES];
70 bool openNodes[MAX_NODES];
71 std::unordered_map<uint32_t, AStarNode*> nodeTable;
72 size_t curNode;
73 int_fast32_t closedNodes;
74};
75
76using SpectatorCache = std::map<Position, SpectatorVec>;
77
78static constexpr int32_t FLOOR_BITS = 3;
79static constexpr int32_t FLOOR_SIZE = (1 << FLOOR_BITS);
80static constexpr int32_t FLOOR_MASK = (FLOOR_SIZE - 1);
81
82struct Floor {
83 constexpr Floor() = default;
84 ~Floor();
85
86 // non-copyable
87 Floor(const Floor&) = delete;
88 Floor& operator=(const Floor&) = delete;
89
90 Tile* tiles[FLOOR_SIZE][FLOOR_SIZE] = {};
91};
92
93class FrozenPathingConditionCall;
94class QTreeLeafNode;
95
96class QTreeNode
97{
98 public:
99 constexpr QTreeNode() = default;
100 virtual ~QTreeNode();
101
102 // non-copyable
103 QTreeNode(const QTreeNode&) = delete;
104 QTreeNode& operator=(const QTreeNode&) = delete;
105
106 bool isLeaf() const {
107 return leaf;
108 }
109
110 QTreeLeafNode* getLeaf(uint32_t x, uint32_t y);
111
112 template<typename Leaf, typename Node>
113 static Leaf getLeafStatic(Node node, uint32_t x, uint32_t y)
114 {
115 do {
116 node = node->child[((x & 0x8000) >> 15) | ((y & 0x8000) >> 14)];
117 if (!node) {
118 return nullptr;
119 }
120
121 x <<= 1;
122 y <<= 1;
123 } while (!node->leaf);
124 return static_cast<Leaf>(node);
125 }
126
127 QTreeLeafNode* createLeaf(uint32_t x, uint32_t y, uint32_t level);
128
129 protected:
130 bool leaf = false;
131
132 private:
133 QTreeNode* child[4] = {};
134
135 friend class Map;
136};
137
138class QTreeLeafNode final : public QTreeNode
139{
140 public:
141 QTreeLeafNode() { leaf = true; newLeaf = true; }
142 ~QTreeLeafNode();
143
144 // non-copyable
145 QTreeLeafNode(const QTreeLeafNode&) = delete;
146 QTreeLeafNode& operator=(const QTreeLeafNode&) = delete;
147
148 Floor* createFloor(uint32_t z);
149 Floor* getFloor(uint8_t z) const {
150 return array[z];
151 }
152
153 void addCreature(Creature* c);
154 void removeCreature(Creature* c);
155
156 private:
157 static bool newLeaf;
158 QTreeLeafNode* leafS = nullptr;
159 QTreeLeafNode* leafE = nullptr;
160 Floor* array[MAP_MAX_LAYERS] = {};
161 CreatureVector creature_list;
162 CreatureVector player_list;
163
164 friend class Map;
165 friend class QTreeNode;
166};
167
168/**
169 * Map class.
170 * Holds all the actual map-data
171 */
172
173class Map
174{
175 public:
176 static constexpr int32_t maxClientViewportX = 16;
177 static constexpr int32_t maxClientViewportY = 9;
178 static constexpr int32_t maxViewportX = maxClientViewportX + 8;
179 static constexpr int32_t maxViewportY = maxClientViewportY + 6;
180
181 uint32_t clean() const;
182
183 /**
184 * Load a map.
185 * \returns true if the map was loaded successfully
186 */
187 bool loadMap(const std::string& identifier, bool loadHouses);
188
189 /**
190 * Save a map.
191 * \returns true if the map was saved successfully
192 */
193 static bool save();
194
195 /**
196 * Get a single tile.
197 * \returns A pointer to that tile.
198 */
199 Tile* getTile(uint16_t x, uint16_t y, uint8_t z) const;
200 Tile* getTile(const Position& pos) const {
201 return getTile(pos.x, pos.y, pos.z);
202 }
203
204 /**
205 * Set a single tile.
206 */
207 void setTile(uint16_t x, uint16_t y, uint8_t z, Tile* newTile);
208 void setTile(const Position& pos, Tile* newTile) {
209 setTile(pos.x, pos.y, pos.z, newTile);
210 }
211
212 /**
213 * Place a creature on the map
214 * \param centerPos The position to place the creature
215 * \param creature Creature to place on the map
216 * \param extendedPos If true, the creature will in first-hand be placed 2 tiles away
217 * \param forceLogin If true, placing the creature will not fail becase of obstacles (creatures/chests)
218 */
219 bool placeCreature(const Position& centerPos, Creature* creature, bool extendedPos = false, bool forceLogin = false);
220
221 void moveCreature(Creature& creature, Tile& newTile, bool forceTeleport = false);
222
223 void getSpectators(SpectatorVec& spectators, const Position& centerPos, bool multifloor = false, bool onlyPlayers = false,
224 int32_t minRangeX = 0, int32_t maxRangeX = 0,
225 int32_t minRangeY = 0, int32_t maxRangeY = 0);
226
227 void clearSpectatorCache();
228 void clearPlayersSpectatorCache();
229
230 /**
231 * Checks if you can throw an object to that position
232 * \param fromPos from Source point
233 * \param toPos Destination point
234 * \param rangex maximum allowed range horizontially
235 * \param rangey maximum allowed range vertically
236 * \param checkLineOfSight checks if there is any blocking objects in the way
237 * \returns The result if you can throw there or not
238 */
239 bool canThrowObjectTo(const Position& fromPos, const Position& toPos, bool checkLineOfSight = true,
240 int32_t rangex = Map::maxClientViewportX, int32_t rangey = Map::maxClientViewportY) const;
241
242 /**
243 * Checks if path is clear from fromPos to toPos
244 * Notice: This only checks a straight line if the path is clear, for path finding use getPathTo.
245 * \param fromPos from Source point
246 * \param toPos Destination point
247 * \param floorCheck if true then view is not clear if fromPos.z is not the same as toPos.z
248 * \returns The result if there is no obstacles
249 */
250 bool isSightClear(const Position& fromPos, const Position& toPos, bool floorCheck) const;
251 bool checkSightLine(const Position& fromPos, const Position& toPos) const;
252
253 const Tile* canWalkTo(const Creature& creature, const Position& pos) const;
254
255 bool getPathMatching(const Creature& creature, std::list<Direction>& dirList,
256 const FrozenPathingConditionCall& pathCondition, const FindPathParams& fpp) const;
257
258 std::map<std::string, Position> waypoints;
259
260 QTreeLeafNode* getQTNode(uint16_t x, uint16_t y) {
261 return QTreeNode::getLeafStatic<QTreeLeafNode*, QTreeNode*>(&root, x, y);
262 }
263
264 Spawns spawns;
265 Towns towns;
266 Houses houses;
267
268 private:
269 SpectatorCache spectatorCache;
270 SpectatorCache playersSpectatorCache;
271
272 QTreeNode root;
273
274 std::string spawnfile;
275 std::string housefile;
276
277 uint32_t width = 0;
278 uint32_t height = 0;
279
280 // Actually scans the map for spectators
281 void getSpectatorsInternal(SpectatorVec& spectators, const Position& centerPos,
282 int32_t minRangeX, int32_t maxRangeX,
283 int32_t minRangeY, int32_t maxRangeY,
284 int32_t minRangeZ, int32_t maxRangeZ, bool onlyPlayers) const;
285
286 friend class Game;
287 friend class IOMap;
288};
289
290#endif
291
Top