1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #ifndef NUVIE_CORE_TIMED_EVENT_H
24 #define NUVIE_CORE_TIMED_EVENT_H
25 
26 #include "ultima/shared/std/string.h"
27 #include "ultima/nuvie/misc/call_back.h"
28 #include "ultima/nuvie/core/obj_manager.h"
29 
30 namespace Ultima {
31 namespace Nuvie {
32 
33 class Actor;
34 class CallBack;
35 class Events;
36 class GameClock;
37 class MapCoord;
38 class MapWindow;
39 class MsgScroll;
40 class Party;
41 class TimedCallbackTarget;
42 class TimedEvent;
43 
44 /* A queue for our events.
45  */
46 class TimeQueue {
47 	Std::list<TimedEvent *> tq;
48 public:
TimeQueue()49 	TimeQueue() : tq() { }
~TimeQueue()50 	~TimeQueue() {
51 		clear();
52 	}
53 
empty()54 	bool empty() const {
55 		return (tq.empty());
56 	}
57 	void clear();
58 	void add_timer(TimedEvent *tevent);
59 	void remove_timer(TimedEvent *tevent);
60 	TimedEvent *pop_timer();
61 	bool delete_timer(TimedEvent *tevent);
62 
63 	bool call_timer(uint32 now); // activate
64 	void call_timers(uint32 now); // activate all
65 };
66 
67 
68 #define TIMER_IMMEDIATE true
69 #define TIMER_DELAYED false
70 #define TIMER_REALTIME true
71 #define TIMER_GAMETIME false
72 
73 /* Events activated by a timer. Add to one of the Events time-queues to start.
74  * (THERE IS ONLY ONE SET)  The timed() method is called on activation,
75  * and the timer may be automatically deleted or repeated.
76  */
77 class TimedEvent {
78 	friend class TimeQueue;
79 	friend class Events;
80 protected:
81 	TimeQueue *tq; // the TimeQueue; so we can add ourself
82 	uint32 delay, time; // timer delay, and next absolute time to activate
83 	sint8 repeat_count; // repeat how many times? (-1=infinite;0=stop)
84 	bool ignore_pause; // activates even if game is paused
85 	bool real_time; // time and delay is in milliseconds (false=game ticks/turns)
86 	bool tq_can_delete; // can TimeQueue delete this TimedEvent when done?
87 	bool defunct; // deleted; don't activate (use to stop timers from outside)
88 
89 public:
90 	TimedEvent(uint32 reltime, bool immediate = TIMER_DELAYED, bool realtime = TIMER_REALTIME);
~TimedEvent()91 	virtual ~TimedEvent() { }
timed(uint32 evtime)92 	virtual void timed(uint32 evtime) {
93 		DEBUG(0, LEVEL_ERROR, "TimedEvent: undefined timer method\n");
94 	}
95 
96 protected:
97 	// stop repeating, remove from tq if it won't delete it
98 	// NOTE: potential for bug here, this doesn't prevent it from being called once more
stop()99 	void stop() {
100 		repeat_count = 0;
101 		if (!tq_can_delete) dequeue();
102 	}
103 	// repeat once (or for requested count)
104 	void repeat(uint32 count = 1) {
105 		repeat_count = count;
106 	}
107 
108 public:
109 	void queue(); // set tq, add to tq
110 	void dequeue(); // remove from tq, clear tq
111 
112 	void set_time(); // set `time' from `delay'
stop_timer()113 	void stop_timer() {
114 		stop();
115 		defunct = true;
116 	}
117 };
118 
119 
120 /* Print to stdout. (timer test)
121  */
122 class TimedMessage : public TimedEvent {
123 	Std::string msg;
124 public:
125 	TimedMessage(uint32 reltime, const char *m, bool repeating = false)
TimedEvent(reltime)126 		: TimedEvent(reltime), msg(m) {
127 		repeat_count = repeating ? -1 : 0;
128 	}
timed(uint32 evtime)129 	void timed(uint32 evtime) override {
130 		DEBUG(0, LEVEL_NOTIFICATION, "Activate! evtime=%d msg=\"%s\"\n", evtime, msg.c_str());
131 	}
132 };
133 
134 
135 /* Move the party to/from a dungeon or ladder or moongate. Characters off-screen
136  * will teleport.
137  */
138 class TimedPartyMove : public TimedEvent, public CallBack {
139 protected:
140 	MapWindow *map_window;
141 	Party *party; // the party
142 	MapCoord *dest; // destination, where all actors walk to and disappear
143 	MapCoord *target; // where they reappear at the new plane
144 	uint32 moves_left; // walk timeout
145 	Obj *moongate; // if using a moongate
146 	uint8 wait_for_effect; // waiting for a visual effect to complete if not 0
147 	Actor *actor_to_hide; // this actor has reached exit and should be hidden
148 	bool falling_in;
149 
150 public:
151 	TimedPartyMove(MapCoord *d, MapCoord *t, uint32 step_delay = 500);
152 	TimedPartyMove(MapCoord *d, MapCoord *t, Obj *use_obj, uint32 step_delay = 500);
153 	TimedPartyMove(uint32 step_delay = 500);
154 	~TimedPartyMove() override;
155 	void init(MapCoord *d, MapCoord *t, Obj *use_obj);
156 	void timed(uint32 evtime) override;
157 
158 	uint16 callback(uint16 msg, CallBack *caller, void *data = NULL) override;
159 
160 protected:
161 	bool move_party();
162 	bool fall_in();
163 	void hide_actor(Actor *person);
164 	void change_location();
165 };
166 
167 
168 /* Move the party into a vehicle and start it when everyone is there.
169  */
170 class TimedPartyMoveToVehicle : public TimedPartyMove {
171 	Obj *ship_obj; // vehicle center
172 public:
173 	TimedPartyMoveToVehicle(MapCoord *d, Obj *obj, uint32 step_delay = 125);
174 	void timed(uint32 evtime) override;
175 };
176 
177 
178 #if 0
179 class TimedRTC : public TimedEvent {
180 public:
181 	TimedRTC() : TimedEvent(1000) {
182 		repeat_count = -1;
183 	}
184 	void timed(uint32 evtime) {
185 //        Game::get_game()->get_player()->pass();
186 	}
187 };
188 #endif
189 
190 
191 //FIXME: It isnt container search. Its a msgscroll effect to print one line at a time.
192 /* Dump one item at a time out of a container, and print it's name to MsgScroll.
193  */
194 class TimedContainerSearch : public TimedEvent {
195 	MsgScroll *scroll;
196 	UseCode *uc;
197 	ObjManager *om;
198 	Obj *container_obj;
199 	Obj *prev_obj; // removed from container
200 public:
201 	TimedContainerSearch(Obj *obj);
202 	void timed(uint32 evtime) override;
203 };
204 
205 
206 /* Send timer message to callback target after `wait_time' is up, passing it
207  * some target-defined data.
208  *  new TimedCallback(PowderKeg, (void *)my_powderkeg_data, time_to_explode);
209  */
210 class TimedCallback : public TimedEvent, public CallBack {
211 public:
212 	TimedCallback(CallBack *t, void *d, uint32 wait_time,
213 	              bool repeat = false);
~TimedCallback()214 	~TimedCallback() override {  }
215 	void timed(uint32 evtime) override;
clear_target()216 	void clear_target() {
217 		set_target(NULL);
218 	}
219 };
220 
221 
222 class GameTimedCallback : public TimedCallback {
223 public:
224 	GameTimedCallback(CallBack *t, void *d, uint32 wait_time, bool repeat = false);
~GameTimedCallback()225 	~GameTimedCallback() override {  }
226 };
227 
228 
229 /* Advance gameclock up to 24hours from start time. The callback is used every
230  * hour from the start time, up to and including the stop time.
231  */
232 class TimedAdvance : public TimedCallback {
233 	GameClock *_clock;
234 	uint16 advance; // minutes requested
235 	uint8 minutes_this_hour;
236 protected:
237 	uint16 minutes; // minutes advanced
238 	uint16 rate; // rate is minutes-per-second
239 	uint32 prev_evtime; // last time the timer was called
240 
241 public:
242 	TimedAdvance(uint8 hours, uint16 r = 60);
243 	TimedAdvance(Std::string timestring, uint16 r = 60); // "HH:MM"
~TimedAdvance()244 	~TimedAdvance() override { }
245 
246 	void init(uint16 min, uint16 r); // start time advance
247 
248 	void timed(uint32 evtime) override;
249 	bool time_passed(); // returns true if stop time has passed
250 	void get_time_from_string(uint8 &hour, uint8 &minute, Std::string timestring);
251 };
252 
253 
254 /* Camping in the wilderness. Move everyone into a circle and place a campfire
255  * in the center.
256  */
257 class TimedRestGather : public TimedPartyMove {
258 public:
259 	TimedRestGather(uint16 x, uint16 y);
260 
261 	void timed(uint32 evtime) override;
262 
263 protected:
264 	bool move_party();
265 	void check_campfire();
266 };
267 
268 /* Camping in the wilderness. Do a TimedAdvance until the requested time. The
269  * camp can be broken by nearby foes.
270  */
271 class TimedRest : public TimedAdvance {
272 	Party *party;
273 	MsgScroll *scroll;
274 	Actor *lookout;
275 	bool sleeping; // false: mealtime, true: sleeping
276 	uint8 print_message; // which message is to be printed next
277 	Obj *campfire;
278 	uint8 number_that_had_food;
279 public:
280 	TimedRest(uint8 hours, Actor *lookout, Obj *campfire_obj);
281 	~TimedRest() override;
282 
283 	void timed(uint32 evtime) override;
284 	void eat(Actor *actor);
285 	void bard_play();
286 	void sleep();
287 };
288 
289 } // End of namespace Nuvie
290 } // End of namespace Ultima
291 
292 #endif
293