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_MOVEMENT_H_5E0D2626D4634ACA83AC6509518E5F49
21#define FS_MOVEMENT_H_5E0D2626D4634ACA83AC6509518E5F49
22
23#include "baseevents.h"
24#include "item.h"
25#include "luascript.h"
26#include "vocation.h"
27
28extern Vocations g_vocations;
29
30enum MoveEvent_t {
31 MOVE_EVENT_STEP_IN,
32 MOVE_EVENT_STEP_OUT,
33 MOVE_EVENT_EQUIP,
34 MOVE_EVENT_DEEQUIP,
35 MOVE_EVENT_ADD_ITEM,
36 MOVE_EVENT_REMOVE_ITEM,
37 MOVE_EVENT_ADD_ITEM_ITEMTILE,
38 MOVE_EVENT_REMOVE_ITEM_ITEMTILE,
39
40 MOVE_EVENT_LAST,
41 MOVE_EVENT_NONE
42};
43
44class MoveEvent;
45using MoveEvent_ptr = std::unique_ptr<MoveEvent>;
46
47struct MoveEventList {
48 std::list<MoveEvent> moveEvent[MOVE_EVENT_LAST];
49};
50
51using VocEquipMap = std::map<uint16_t, bool>;
52
53class MoveEvents final : public BaseEvents
54{
55 public:
56 MoveEvents();
57 ~MoveEvents();
58
59 // non-copyable
60 MoveEvents(const MoveEvents&) = delete;
61 MoveEvents& operator=(const MoveEvents&) = delete;
62
63 uint32_t onCreatureMove(Creature* creature, const Tile* tile, MoveEvent_t eventType);
64 ReturnValue onPlayerEquip(Player* player, Item* item, slots_t slot, bool isCheck);
65 ReturnValue onPlayerDeEquip(Player* player, Item* item, slots_t slot);
66 uint32_t onItemMove(Item* item, Tile* tile, bool isAdd);
67
68 MoveEvent* getEvent(Item* item, MoveEvent_t eventType);
69
70 bool registerLuaEvent(MoveEvent* event);
71 bool registerLuaFunction(MoveEvent* event);
72 void clear(bool fromLua) override final;
73
74 private:
75 using MoveListMap = std::map<int32_t, MoveEventList>;
76 using MovePosListMap = std::map<Position, MoveEventList>;
77 void clearMap(MoveListMap& map, bool fromLua);
78 void clearPosMap(MovePosListMap& map, bool fromLua);
79
80 LuaScriptInterface& getScriptInterface() override;
81 std::string getScriptBaseName() const override;
82 Event_ptr getEvent(const std::string& nodeName) override;
83 bool registerEvent(Event_ptr event, const pugi::xml_node& node) override;
84
85 void addEvent(MoveEvent moveEvent, int32_t id, MoveListMap& map);
86
87 void addEvent(MoveEvent moveEvent, const Position& pos, MovePosListMap& map);
88 MoveEvent* getEvent(const Tile* tile, MoveEvent_t eventType);
89
90 MoveEvent* getEvent(Item* item, MoveEvent_t eventType, slots_t slot);
91
92 MoveListMap uniqueIdMap;
93 MoveListMap actionIdMap;
94 MoveListMap itemIdMap;
95 MovePosListMap positionMap;
96
97 LuaScriptInterface scriptInterface;
98};
99
100using StepFunction = std::function<uint32_t(Creature* creature, Item* item, const Position& pos)>;
101using MoveFunction = std::function<uint32_t(Item* item, Item* tileItem, const Position& pos)>;
102using EquipFunction = std::function<ReturnValue(MoveEvent* moveEvent, Player* player, Item* item, slots_t slot, bool boolean)>;
103
104class MoveEvent final : public Event
105{
106 public:
107 explicit MoveEvent(LuaScriptInterface* interface);
108
109 MoveEvent_t getEventType() const;
110 void setEventType(MoveEvent_t type);
111
112 bool configureEvent(const pugi::xml_node& node) override;
113 bool loadFunction(const pugi::xml_attribute& attr, bool isScripted) override;
114
115 uint32_t fireStepEvent(Creature* creature, Item* item, const Position& pos);
116 uint32_t fireAddRemItem(Item* item, Item* tileItem, const Position& pos);
117 ReturnValue fireEquip(Player* player, Item* item, slots_t slot, bool isCheck);
118
119 uint32_t getSlot() const {
120 return slot;
121 }
122
123 //scripting
124 bool executeStep(Creature* creature, Item* item, const Position& pos);
125 bool executeEquip(Player* player, Item* item, slots_t slot, bool isCheck);
126 bool executeAddRemItem(Item* item, Item* tileItem, const Position& pos);
127 //
128
129 //onEquip information
130 uint32_t getReqLevel() const {
131 return reqLevel;
132 }
133 uint32_t getReqMagLv() const {
134 return reqMagLevel;
135 }
136 bool isPremium() const {
137 return premium;
138 }
139 const std::string& getVocationString() const {
140 return vocationString;
141 }
142 void setVocationString(const std::string& str) {
143 vocationString = str;
144 }
145 uint32_t getWieldInfo() const {
146 return wieldInfo;
147 }
148 const VocEquipMap& getVocEquipMap() const {
149 return vocEquipMap;
150 }
151 void addVocEquipMap(std::string vocName) {
152 int32_t vocationId = g_vocations.getVocationId(vocName);
153 if (vocationId != -1) {
154 vocEquipMap[vocationId] = true;
155 }
156 }
157 bool getTileItem() const {
158 return tileItem;
159 }
160 void setTileItem(bool b) {
161 tileItem = b;
162 }
163 std::vector<uint32_t> getItemIdRange() {
164 return itemIdRange;
165 }
166 void addItemId(uint32_t id) {
167 itemIdRange.emplace_back(id);
168 }
169 std::vector<uint32_t> getActionIdRange() {
170 return actionIdRange;
171 }
172 void addActionId(uint32_t id) {
173 actionIdRange.emplace_back(id);
174 }
175 std::vector<uint32_t> getUniqueIdRange() {
176 return uniqueIdRange;
177 }
178 void addUniqueId(uint32_t id) {
179 uniqueIdRange.emplace_back(id);
180 }
181 std::vector<Position> getPosList() {
182 return posList;
183 }
184 void addPosList(Position pos) {
185 posList.emplace_back(pos);
186 }
187 std::string getSlotName() {
188 return slotName;
189 }
190 void setSlotName(std::string name) {
191 slotName = name;
192 }
193 void setSlot(uint32_t s) {
194 slot = s;
195 }
196 uint32_t getRequiredLevel() {
197 return reqLevel;
198 }
199 void setRequiredLevel(uint32_t level) {
200 reqLevel = level;
201 }
202 uint32_t getRequiredMagLevel() {
203 return reqMagLevel;
204 }
205 void setRequiredMagLevel(uint32_t level) {
206 reqMagLevel = level;
207 }
208 bool needPremium() {
209 return premium;
210 }
211 void setNeedPremium(bool b) {
212 premium = b;
213 }
214 uint32_t getWieldInfo() {
215 return wieldInfo;
216 }
217 void setWieldInfo(WieldInfo_t info) {
218 wieldInfo |= info;
219 }
220
221 static uint32_t StepInField(Creature* creature, Item* item, const Position& pos);
222 static uint32_t StepOutField(Creature* creature, Item* item, const Position& pos);
223
224 static uint32_t AddItemField(Item* item, Item* tileItem, const Position& pos);
225 static uint32_t RemoveItemField(Item* item, Item* tileItem, const Position& pos);
226
227 static ReturnValue EquipItem(MoveEvent* moveEvent, Player* player, Item* item, slots_t slot, bool boolean);
228 static ReturnValue DeEquipItem(MoveEvent* moveEvent, Player* player, Item* item, slots_t slot, bool boolean);
229
230 MoveEvent_t eventType = MOVE_EVENT_NONE;
231 StepFunction stepFunction;
232 MoveFunction moveFunction;
233 EquipFunction equipFunction;
234
235 private:
236 std::string getScriptEventName() const override;
237
238 uint32_t slot = SLOTP_WHEREEVER;
239 std::string slotName;
240
241 //onEquip information
242 uint32_t reqLevel = 0;
243 uint32_t reqMagLevel = 0;
244 bool premium = false;
245 std::string vocationString;
246 uint32_t wieldInfo = 0;
247 VocEquipMap vocEquipMap;
248 bool tileItem = false;
249
250 std::vector<uint32_t> itemIdRange;
251 std::vector<uint32_t> actionIdRange;
252 std::vector<uint32_t> uniqueIdRange;
253 std::vector<Position> posList;
254};
255
256#endif
257