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_RAIDS_H_3583C7C054584881856D55765DEDAFA9
21#define FS_RAIDS_H_3583C7C054584881856D55765DEDAFA9
22
23#include "const.h"
24#include "position.h"
25#include "baseevents.h"
26
27enum RaidState_t {
28 RAIDSTATE_IDLE,
29 RAIDSTATE_EXECUTING,
30};
31
32struct MonsterSpawn {
33 MonsterSpawn(std::string name, uint32_t minAmount, uint32_t maxAmount) :
34 name(std::move(name)), minAmount(minAmount), maxAmount(maxAmount) {}
35
36 std::string name;
37 uint32_t minAmount;
38 uint32_t maxAmount;
39};
40
41//How many times it will try to find a tile to add the monster to before giving up
42static constexpr int32_t MAXIMUM_TRIES_PER_MONSTER = 10;
43static constexpr int32_t CHECK_RAIDS_INTERVAL = 60;
44static constexpr int32_t RAID_MINTICKS = 1000;
45
46class Raid;
47class RaidEvent;
48
49class Raids
50{
51 public:
52 Raids();
53 ~Raids();
54
55 // non-copyable
56 Raids(const Raids&) = delete;
57 Raids& operator=(const Raids&) = delete;
58
59 bool loadFromXml();
60 bool startup();
61
62 void clear();
63 bool reload();
64
65 bool isLoaded() const {
66 return loaded;
67 }
68 bool isStarted() const {
69 return started;
70 }
71
72 Raid* getRunning() {
73 return running;
74 }
75 void setRunning(Raid* newRunning) {
76 running = newRunning;
77 }
78
79 Raid* getRaidByName(const std::string& name);
80
81 uint64_t getLastRaidEnd() const {
82 return lastRaidEnd;
83 }
84 void setLastRaidEnd(uint64_t newLastRaidEnd) {
85 lastRaidEnd = newLastRaidEnd;
86 }
87
88 void checkRaids();
89
90 LuaScriptInterface& getScriptInterface() {
91 return scriptInterface;
92 }
93
94 private:
95 LuaScriptInterface scriptInterface{"Raid Interface"};
96
97 std::list<Raid*> raidList;
98 Raid* running = nullptr;
99 uint64_t lastRaidEnd = 0;
100 uint32_t checkRaidsEvent = 0;
101 bool loaded = false;
102 bool started = false;
103};
104
105class Raid
106{
107 public:
108 Raid(std::string name, uint32_t interval, uint32_t marginTime, bool repeat) :
109 name(std::move(name)), interval(interval), margin(marginTime), repeat(repeat) {}
110 ~Raid();
111
112 // non-copyable
113 Raid(const Raid&) = delete;
114 Raid& operator=(const Raid&) = delete;
115
116 bool loadFromXml(const std::string& filename);
117
118 void startRaid();
119
120 void executeRaidEvent(RaidEvent* raidEvent);
121 void resetRaid();
122
123 RaidEvent* getNextRaidEvent();
124 void setState(RaidState_t newState) {
125 state = newState;
126 }
127 const std::string& getName() const {
128 return name;
129 }
130
131 bool isLoaded() const {
132 return loaded;
133 }
134 uint64_t getMargin() const {
135 return margin;
136 }
137 uint32_t getInterval() const {
138 return interval;
139 }
140 bool canBeRepeated() const {
141 return repeat;
142 }
143
144 void stopEvents();
145
146 private:
147 std::vector<RaidEvent*> raidEvents;
148 std::string name;
149 uint32_t interval;
150 uint32_t nextEvent = 0;
151 uint64_t margin;
152 RaidState_t state = RAIDSTATE_IDLE;
153 uint32_t nextEventEvent = 0;
154 bool loaded = false;
155 bool repeat;
156};
157
158class RaidEvent
159{
160 public:
161 virtual ~RaidEvent() = default;
162
163 virtual bool configureRaidEvent(const pugi::xml_node& eventNode);
164
165 virtual bool executeEvent() = 0;
166 uint32_t getDelay() const {
167 return delay;
168 }
169
170 private:
171 uint32_t delay;
172};
173
174class AnnounceEvent final : public RaidEvent
175{
176 public:
177 AnnounceEvent() = default;
178
179 bool configureRaidEvent(const pugi::xml_node& eventNode) override;
180
181 bool executeEvent() override;
182
183 private:
184 std::string message;
185 MessageClasses messageType = MESSAGE_EVENT_ADVANCE;
186};
187
188class SingleSpawnEvent final : public RaidEvent
189{
190 public:
191 bool configureRaidEvent(const pugi::xml_node& eventNode) override;
192
193 bool executeEvent() override;
194
195 private:
196 std::string monsterName;
197 Position position;
198};
199
200class AreaSpawnEvent final : public RaidEvent
201{
202 public:
203 bool configureRaidEvent(const pugi::xml_node& eventNode) override;
204
205 bool executeEvent() override;
206
207 private:
208 std::list<MonsterSpawn> spawnList;
209 Position fromPos, toPos;
210};
211
212class ScriptEvent final : public RaidEvent, public Event
213{
214 public:
215 explicit ScriptEvent(LuaScriptInterface* interface) : Event(interface) {}
216
217 bool configureRaidEvent(const pugi::xml_node& eventNode) override;
218 bool configureEvent(const pugi::xml_node&) override {
219 return false;
220 }
221
222 bool executeEvent() override;
223
224 private:
225 std::string getScriptEventName() const override;
226};
227
228#endif
229