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