Server upload

RD Core / Commit #2

Commit Server upload

Alex Alex committed 18/10/2026 23:38 main Patch
1,106 files +223,404 -0
A src/map.h +290-0 View file
@@ -0,0 +1,290 @@
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+
33+class Creature;
34+class Player;
35+class Game;
36+class Tile;
37+class Map;
38+
39+static constexpr int32_t MAP_MAX_LAYERS = 16;
40+
41+struct FindPathParams;
42+struct AStarNode {
43+ AStarNode* parent;
44+ int_fast32_t f;
45+ uint16_t x, y;
46+};
47+
48+static constexpr int32_t MAX_NODES = 512;
49+
50+static constexpr int32_t MAP_NORMALWALKCOST = 10;
51+static constexpr int32_t MAP_DIAGONALWALKCOST = 25;
52+
53+class 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+
76+using SpectatorCache = std::map<Position, SpectatorVec>;
77+
78+static constexpr int32_t FLOOR_BITS = 3;
79+static constexpr int32_t FLOOR_SIZE = (1 << FLOOR_BITS);
80+static constexpr int32_t FLOOR_MASK = (FLOOR_SIZE - 1);
81+
82+struct 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+
93+class FrozenPathingConditionCall;
94+class QTreeLeafNode;
95+
96+class 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+
138+class 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+
173+class 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
A src/monster.h +258-0 View file
@@ -0,0 +1,258 @@
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_MONSTER_H_9F5EEFE64314418CA7DA41D1B9409DD0
21+#define FS_MONSTER_H_9F5EEFE64314418CA7DA41D1B9409DD0
22+
23+#include "monsters.h"
24+#include "tile.h"
25+
26+class Creature;
27+class Game;
28+class Spawn;
29+
30+using CreatureHashSet = std::unordered_set<Creature *>;
31+using CreatureList = std::list<Creature *>;
32+
33+enum TargetSearchType_t {
34+ TARGETSEARCH_DEFAULT,
35+ TARGETSEARCH_RANDOM,
36+ TARGETSEARCH_ATTACKRANGE,
37+ TARGETSEARCH_NEAREST,
38+};
39+
40+class Monster final : public Creature {
41+public:
42+ static Monster *createMonster(const std::string &name);
43+ static int32_t despawnRange;
44+ static int32_t despawnRadius;
45+
46+ explicit Monster(MonsterType *mType);
47+ ~Monster();
48+
49+ // non-copyable
50+ Monster(const Monster &) = delete;
51+ Monster &operator=(const Monster &) = delete;
52+
53+ Monster *getMonster() override { return this; }
54+ const Monster *getMonster() const override { return this; }
55+
56+ void setID() override {
57+ if (id == 0) {
58+ id = monsterAutoID++;
59+ }
60+ }
61+
62+ void removeList() override;
63+ void addList() override;
64+
65+ std::string name, nameDescription, altStrDesc;
66+ const std::string &getName() const final {
67+ if (!name.empty()) {
68+ return name;
69+ }
70+ return mType->name;
71+ }
72+ const std::string &getNameDescription() const final {
73+ if (nameDescription.empty()) {
74+ return mType->nameDescription;
75+ }
76+ return nameDescription;
77+ }
78+ std::string getDescription(int32_t) const final {
79+ if (!altStrDesc.empty()) {
80+ return altStrDesc + '.';
81+ }
82+ return strDescription + '.';
83+ }
84+ void setName(std::string n) { name = n; }
85+ void setDescription(std::string desc) { nameDescription = desc; }
86+ void setStrDescription(std::string altdesc) { altStrDesc = altdesc; }
87+ CreatureType_t getType() const override { return CREATURETYPE_MONSTER; }
88+
89+ const Position &getMasterPos() const { return masterPos; }
90+ void setMasterPos(Position pos) { masterPos = pos; }
91+
92+ RaceType_t getRace() const override { return mType->info.race; }
93+ int32_t getArmor() const override { return mType->info.armor; }
94+ int32_t getDefense() const override { return mType->info.defense; }
95+ bool isPushable() const override {
96+ return mType->info.pushable && baseSpeed != 0;
97+ }
98+ bool isAttackable() const override { return mType->info.isAttackable; }
99+
100+ bool canPushItems() const { return mType->info.canPushItems; }
101+ bool canPushCreatures() const { return mType->info.canPushCreatures; }
102+ bool isHostile() const { return mType->info.isHostile; }
103+ bool canSee(const Position &pos) const override;
104+ bool canSeeInvisibility() const override {
105+ return isImmune(CONDITION_INVISIBLE);
106+ }
107+ uint32_t getManaCost() const { return mType->info.manaCost; }
108+ void setSpawn(Spawn *spawn) { this->spawn = spawn; }
109+ bool canWalkOnFieldType(CombatType_t combatType) const;
110+
111+ void onAttackedCreatureDisappear(bool isLogout) override;
112+
113+ void onCreatureAppear(Creature *creature, bool isLogin) override;
114+ void onRemoveCreature(Creature *creature, bool isLogout) override;
115+ void onCreatureMove(Creature *creature, const Tile *newTile,
116+ const Position &newPos, const Tile *oldTile,
117+ const Position &oldPos, bool teleport) override;
118+ void onCreatureSay(Creature *creature, SpeakClasses type,
119+ const std::string &text) override;
120+
121+ void drainHealth(Creature *attacker, int32_t damage) override;
122+ void changeHealth(int32_t healthChange,
123+ bool sendHealthChange = true) override;
124+ void onWalk() override;
125+ bool getNextStep(Direction &direction, uint32_t &flags) override;
126+ void onFollowCreatureComplete(const Creature *creature) override;
127+
128+ void onThink(uint32_t interval) override;
129+
130+ bool challengeCreature(Creature *creature) override;
131+
132+ void setNormalCreatureLight() override;
133+ bool getCombatValues(int32_t &min, int32_t &max) override;
134+
135+ void doAttacking(uint32_t interval) override;
136+ uint16_t getAttackOutfitLookType() const override;
137+ bool hasExtraSwing() override { return extraMeleeAttack; }
138+
139+ bool searchTarget(TargetSearchType_t searchType = TARGETSEARCH_DEFAULT);
140+ bool selectTarget(Creature *creature);
141+
142+ const CreatureList &getTargetList() const { return targetList; }
143+ const CreatureHashSet &getFriendList() const { return friendList; }
144+
145+ bool isTarget(const Creature *creature) const;
146+ bool isFleeing() const {
147+ return !isSummon() && getHealth() <= mType->info.runAwayHealth &&
148+ challengeFocusDuration <= 0;
149+ }
150+
151+ bool getDistanceStep(const Position &targetPos, Direction &direction,
152+ bool flee = false);
153+ bool isTargetNearby() const { return stepDuration >= 1; }
154+ bool isIgnoringFieldDamage() const { return ignoreFieldDamage; }
155+
156+ BlockType_t blockHit(Creature *attacker, CombatType_t combatType,
157+ int32_t &damage, bool checkDefense = false,
158+ bool checkArmor = false, bool field = false) override;
159+
160+ static uint32_t monsterAutoID;
161+
162+private:
163+ CreatureHashSet friendList;
164+ CreatureList targetList;
165+
166+ std::string strDescription;
167+
168+ MonsterType *mType;
169+ Spawn *spawn = nullptr;
170+
171+ int64_t lastMeleeAttack = 0;
172+
173+ uint32_t attackTicks = 0;
174+ uint32_t targetTicks = 0;
175+ uint32_t targetChangeTicks = 0;
176+ uint32_t defenseTicks = 0;
177+ uint32_t yellTicks = 0;
178+ int32_t minCombatValue = 0;
179+ int32_t maxCombatValue = 0;
180+ int32_t targetChangeCooldown = 0;
181+ int32_t challengeFocusDuration = 0;
182+ int32_t stepDuration = 0;
183+
184+ Position masterPos;
185+
186+ bool isIdle = true;
187+ bool extraMeleeAttack = false;
188+ bool isMasterInRange = false;
189+ bool randomStepping = false;
190+ bool ignoreFieldDamage = false;
191+
192+ void onCreatureEnter(Creature *creature);
193+ void onCreatureLeave(Creature *creature);
194+ void onCreatureFound(Creature *creature, bool pushFront = false);
195+
196+ void updateLookDirection();
197+
198+ void addFriend(Creature *creature);
199+ void removeFriend(Creature *creature);
200+ void addTarget(Creature *creature, bool pushFront = false);
201+ void removeTarget(Creature *creature);
202+
203+ void updateTargetList();
204+ void clearTargetList();
205+ void clearFriendList();
206+
207+ void death(Creature *lastHitCreature) override;
208+ Item *getCorpse(Creature *lastHitCreature,
209+ Creature *mostDamageCreature) override;
210+
211+ void setIdle(bool idle);
212+ void updateIdleStatus();
213+ bool getIdleStatus() const { return isIdle; }
214+
215+ void onAddCondition(ConditionType_t type) override;
216+ void onEndCondition(ConditionType_t type) override;
217+
218+ bool canUseAttack(const Position &pos, const Creature *target) const;
219+ bool canUseSpell(const Position &pos, const Position &targetPos,
220+ const spellBlock_t &sb, uint32_t interval, bool &inRange,
221+ bool &resetTicks);
222+ bool getRandomStep(const Position &creaturePos, Direction &direction) const;
223+ bool getDanceStep(const Position &creaturePos, Direction &direction,
224+ bool keepAttack = true, bool keepDistance = true);
225+ bool isInSpawnRange(const Position &pos) const;
226+ bool canWalkTo(Position pos, Direction direction) const;
227+
228+ static bool pushItem(Item *item);
229+ static void pushItems(Tile *tile);
230+ static bool pushCreature(Creature *creature);
231+ static void pushCreatures(Tile *tile);
232+
233+ void onThinkTarget(uint32_t interval);
234+ void onThinkYell(uint32_t interval);
235+ void onThinkDefense(uint32_t interval);
236+
237+ bool isFriend(const Creature *creature) const;
238+ bool isOpponent(const Creature *creature) const;
239+
240+ uint64_t getLostExperience() const override {
241+ return skillLoss ? mType->info.experience : 0;
242+ }
243+ uint16_t getLookCorpse() const override { return mType->info.lookcorpse; }
244+ void dropLoot(Container *corpse, Creature *lastHitCreature) override;
245+ uint32_t getDamageImmunities() const override {
246+ return mType->info.damageImmunities;
247+ }
248+ uint32_t getConditionImmunities() const override {
249+ return mType->info.conditionImmunities;
250+ }
251+ void getPathSearchParams(const Creature *creature,
252+ FindPathParams &fpp) const override;
253+ bool useCacheMap() const override { return !randomStepping; }
254+
255+ friend class LuaScriptInterface;
256+};
257+
258+#endif
Top