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_MONSTERS_H_776E8327BCE2450EB7C4A260785E6C0D
21#define FS_MONSTERS_H_776E8327BCE2450EB7C4A260785E6C0D
22
23#include "creature.h"
24
25const uint32_t MAX_LOOTCHANCE = 100000;
26
27struct LootBlock {
28 uint16_t id;
29 uint32_t countmax;
30 uint32_t chance;
31
32 // optional
33 int32_t subType;
34 int32_t actionId;
35 std::string text;
36
37 std::vector<LootBlock> childLoot;
38 LootBlock() {
39 id = 0;
40 countmax = 1;
41 chance = 0;
42
43 subType = -1;
44 actionId = -1;
45 }
46};
47
48class Loot {
49public:
50 Loot() = default;
51
52 // non-copyable
53 Loot(const Loot &) = delete;
54 Loot &operator=(const Loot &) = delete;
55
56 LootBlock lootBlock;
57};
58
59struct summonBlock_t {
60 std::string name;
61 uint32_t chance;
62 uint32_t speed;
63 uint32_t max;
64 bool force = false;
65};
66
67class BaseSpell;
68struct spellBlock_t {
69 constexpr spellBlock_t() = default;
70 ~spellBlock_t();
71 spellBlock_t(const spellBlock_t &other) = delete;
72 spellBlock_t &operator=(const spellBlock_t &other) = delete;
73 spellBlock_t(spellBlock_t &&other)
74 : spell(other.spell), chance(other.chance), speed(other.speed),
75 range(other.range), minCombatValue(other.minCombatValue),
76 maxCombatValue(other.maxCombatValue), combatSpell(other.combatSpell),
77 isMelee(other.isMelee) {
78 other.spell = nullptr;
79 }
80
81 BaseSpell *spell = nullptr;
82 uint32_t chance = 100;
83 uint32_t speed = 2000;
84 uint32_t range = 0;
85 int32_t minCombatValue = 0;
86 int32_t maxCombatValue = 0;
87 bool combatSpell = false;
88 bool isMelee = false;
89};
90
91struct voiceBlock_t {
92 std::string text;
93 bool yellText;
94};
95
96class MonsterType {
97 struct MonsterInfo {
98 LuaScriptInterface *scriptInterface;
99
100 std::map<CombatType_t, int32_t> elementMap;
101
102 std::vector<voiceBlock_t> voiceVector;
103
104 std::vector<LootBlock> lootItems;
105 std::vector<std::string> scripts;
106 std::vector<spellBlock_t> attackSpells;
107 std::vector<spellBlock_t> defenseSpells;
108 std::vector<summonBlock_t> summons;
109
110 Skulls_t skull = SKULL_NONE;
111 Outfit_t outfit = {};
112 RaceType_t race = RACE_BLOOD;
113
114 LightInfo light = {};
115 uint16_t lookcorpse = 0;
116
117 uint64_t experience = 0;
118
119 uint32_t manaCost = 0;
120 uint32_t yellChance = 0;
121 uint32_t yellSpeedTicks = 0;
122 uint32_t staticAttackChance = 95;
123 uint32_t maxSummons = 0;
124 uint32_t changeTargetSpeed = 0;
125 uint32_t conditionImmunities = 0;
126 uint32_t damageImmunities = 0;
127 uint32_t baseSpeed = 200;
128
129 int32_t creatureAppearEvent = -1;
130 int32_t creatureDisappearEvent = -1;
131 int32_t creatureMoveEvent = -1;
132 int32_t creatureSayEvent = -1;
133 int32_t thinkEvent = -1;
134 int32_t targetDistance = 1;
135 int32_t runAwayHealth = 0;
136 int32_t health = 100;
137 int32_t healthMax = 100;
138 int32_t changeTargetChance = 0;
139 int32_t defense = 0;
140 int32_t armor = 0;
141
142 bool canPushItems = false;
143 bool canPushCreatures = false;
144 bool pushable = true;
145 bool isSummonable = false;
146 bool isIllusionable = false;
147 bool isConvinceable = false;
148 bool isAttackable = true;
149 bool isHostile = true;
150 bool hiddenHealth = false;
151 bool isBoss = false;
152 bool canWalkOnEnergy = true;
153 bool canWalkOnFire = true;
154 bool canWalkOnPoison = true;
155
156 MonstersEvent_t eventType = MONSTERS_EVENT_NONE;
157 Outfit_t lookAttack = {}; // outfit temporal durante el ataque
158 Outfit_t lookAttackMelee = {}; // outfit para ataque cuerpo a cuerpo
159 Outfit_t lookAttackRange = {}; // outfit para ataque a distancia
160 };
161
162public:
163 MonsterType() = default;
164
165 // non-copyable
166 MonsterType(const MonsterType &) = delete;
167 MonsterType &operator=(const MonsterType &) = delete;
168
169 bool loadCallback(LuaScriptInterface *scriptInterface);
170
171 std::string name;
172 std::string nameDescription;
173
174 MonsterInfo info;
175
176 void loadLoot(MonsterType *monsterType, LootBlock lootblock);
177};
178
179class MonsterSpell {
180public:
181 MonsterSpell() = default;
182
183 MonsterSpell(const MonsterSpell &) = delete;
184 MonsterSpell &operator=(const MonsterSpell &) = delete;
185
186 std::string name = "";
187 std::string scriptName = "";
188
189 uint8_t chance = 100;
190 uint8_t range = 0;
191
192 uint16_t interval = 2000;
193
194 int32_t minCombatValue = 0;
195 int32_t maxCombatValue = 0;
196 int32_t attack = 0;
197 int32_t skill = 0;
198 int32_t length = 0;
199 int32_t spread = 0;
200 int32_t radius = 0;
201 int32_t conditionMinDamage = 0;
202 int32_t conditionMaxDamage = 0;
203 int32_t conditionStartDamage = 0;
204 int32_t tickInterval = 0;
205 int32_t minSpeedChange = 0;
206 int32_t maxSpeedChange = 0;
207 int32_t duration = 0;
208
209 bool isScripted = false;
210 bool needTarget = false;
211 bool needDirection = false;
212 bool combatSpell = false;
213 bool isMelee = false;
214
215 Outfit_t outfit = {};
216 ShootType_t shoot = CONST_ANI_NONE;
217 MagicEffectClasses effect = CONST_ME_NONE;
218 ConditionType_t conditionType = CONDITION_NONE;
219 CombatType_t combatType = COMBAT_UNDEFINEDDAMAGE;
220};
221
222class Monsters {
223public:
224 Monsters() = default;
225 // non-copyable
226 Monsters(const Monsters &) = delete;
227 Monsters &operator=(const Monsters &) = delete;
228
229 bool loadFromXml(bool reloading = false);
230 bool isLoaded() const { return loaded; }
231 bool reload();
232
233 MonsterType *getMonsterType(const std::string &name,
234 bool loadFromFile = true);
235 bool deserializeSpell(MonsterSpell *spell, spellBlock_t &sb,
236 const std::string &description = "");
237
238 std::unique_ptr<LuaScriptInterface> scriptInterface;
239 std::map<std::string, MonsterType> monsters;
240
241private:
242 ConditionDamage *getDamageCondition(ConditionType_t conditionType,
243 int32_t maxDamage, int32_t minDamage,
244 int32_t startDamage,
245 uint32_t tickInterval);
246 bool deserializeSpell(const pugi::xml_node &node, spellBlock_t &sb,
247 const std::string &description = "");
248
249 MonsterType *loadMonster(const std::string &file,
250 const std::string &monsterName,
251 bool reloading = false);
252
253 void loadLootContainer(const pugi::xml_node &node, LootBlock &);
254 bool loadLootItem(const pugi::xml_node &node, LootBlock &);
255
256 std::map<std::string, std::string> unloadedMonsters;
257
258 bool loaded = false;
259};
260
261#endif
262