00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifdef HAVE_CONFIG_H
00022 # include <config.h>
00023 #endif
00024
00025 #include "npctime.h"
00026 #include "gamewin.h"
00027 #include "gameclk.h"
00028 #include "actors.h"
00029 #include "items.h"
00030 #include "schedule.h"
00031 #include "game.h"
00032
00033 #ifndef UNDER_CE
00034 using std::rand;
00035 #endif
00036
00037 extern bool god_mode;
00038
00039
00040
00041
00042 class Npc_timer : public Time_sensitive, public Game_singletons
00043 {
00044 protected:
00045 Npc_timer_list *list;
00046 uint32 get_minute();
00047 public:
00048 Npc_timer(Npc_timer_list *l, int start_delay = 0);
00049 virtual ~Npc_timer();
00050 };
00051
00052
00053
00054
00055 class Npc_hunger_timer : public Npc_timer
00056 {
00057 uint32 last_time;
00058 public:
00059 Npc_hunger_timer(Npc_timer_list *l) : Npc_timer(l, 5000)
00060 { last_time = get_minute(); }
00061 virtual ~Npc_hunger_timer();
00062
00063 void handle_event(unsigned long curtime, long udata);
00064 };
00065
00066
00067
00068
00069 class Npc_poison_timer : public Npc_timer
00070 {
00071 uint32 end_time;
00072 public:
00073 Npc_poison_timer(Npc_timer_list *l);
00074 virtual ~Npc_poison_timer();
00075
00076 void handle_event(unsigned long curtime, long udata);
00077 };
00078
00079
00080
00081
00082 class Npc_sleep_timer : public Npc_timer
00083 {
00084 uint32 end_time;
00085 public:
00086 Npc_sleep_timer(Npc_timer_list *l) : Npc_timer(l)
00087 {
00088 end_time = Game::get_ticks() + 5000 + rand()%5000;
00089 }
00090 virtual ~Npc_sleep_timer()
00091 { list->sleep = 0; }
00092
00093 void handle_event(unsigned long curtime, long udata);
00094 };
00095
00096
00097
00098
00099 class Npc_invisibility_timer : public Npc_timer
00100 {
00101 uint32 end_time;
00102 public:
00103 Npc_invisibility_timer(Npc_timer_list *l) : Npc_timer(l)
00104 {
00105 end_time = Game::get_ticks() + 60000 + rand()%20000;
00106 }
00107 virtual ~Npc_invisibility_timer()
00108 { list->invisibility = 0; }
00109
00110 void handle_event(unsigned long curtime, long udata);
00111 };
00112
00113
00114
00115
00116 class Npc_protection_timer : public Npc_timer
00117 {
00118 uint32 end_time;
00119 public:
00120 Npc_protection_timer(Npc_timer_list *l) : Npc_timer(l)
00121 {
00122 end_time = Game::get_ticks() + 60000 + rand()%20000;
00123 }
00124 virtual ~Npc_protection_timer()
00125 { list->protection = 0; }
00126
00127 void handle_event(unsigned long curtime, long udata);
00128 };
00129
00130
00131
00132
00133 class Npc_flag_timer : public Npc_timer
00134 {
00135 int flag;
00136 uint32 end_time;
00137 Npc_flag_timer **listloc;
00138 public:
00139 Npc_flag_timer(Npc_timer_list *l, int f, Npc_flag_timer **loc)
00140 : Npc_timer(l), flag(f), listloc(loc)
00141 {
00142 end_time = Game::get_ticks() + 60000 + rand()%60000;
00143 }
00144 virtual ~Npc_flag_timer()
00145 { *listloc = 0; }
00146
00147 void handle_event(unsigned long curtime, long udata);
00148 };
00149
00150
00151
00152
00153
00154
00155 Npc_timer_list::~Npc_timer_list
00156 (
00157 )
00158 {
00159 delete hunger;
00160 delete poison;
00161 delete sleep;
00162 delete invisibility;
00163 delete protection;
00164 delete might;
00165 delete curse;
00166 delete paralyze;
00167 }
00168
00169
00170
00171
00172
00173 void Npc_timer_list::start_hunger
00174 (
00175 )
00176 {
00177 if (!hunger)
00178 hunger = new Npc_hunger_timer(this);
00179 }
00180
00181
00182
00183
00184
00185 void Npc_timer_list::start_poison
00186 (
00187 )
00188 {
00189 if (poison)
00190 delete poison;
00191 poison = new Npc_poison_timer(this);
00192 }
00193
00194
00195
00196
00197
00198 void Npc_timer_list::start_sleep
00199 (
00200 )
00201 {
00202 if (sleep)
00203 delete sleep;
00204 sleep = new Npc_sleep_timer(this);
00205 }
00206
00207
00208
00209
00210
00211 void Npc_timer_list::start_invisibility
00212 (
00213 )
00214 {
00215 if (invisibility)
00216 delete invisibility;
00217 invisibility = new Npc_invisibility_timer(this);
00218 }
00219
00220
00221
00222
00223
00224 void Npc_timer_list::start_protection
00225 (
00226 )
00227 {
00228 if (protection)
00229 delete protection;
00230 protection = new Npc_protection_timer(this);
00231 }
00232
00233
00234
00235
00236
00237
00238 void Npc_timer_list::start_might
00239 (
00240 )
00241 {
00242 if (might)
00243 delete might;
00244 might = new Npc_flag_timer(this, Obj_flags::might, &might);
00245 }
00246
00247
00248
00249
00250
00251 void Npc_timer_list::start_curse
00252 (
00253 )
00254 {
00255 if (curse)
00256 delete curse;
00257 curse = new Npc_flag_timer(this, Obj_flags::cursed, &curse);
00258 }
00259
00260
00261
00262
00263
00264 void Npc_timer_list::start_paralyze
00265 (
00266 )
00267 {
00268 if (paralyze)
00269 delete paralyze;
00270 paralyze = new Npc_flag_timer(this, Obj_flags::paralyzed, ¶lyze);
00271 }
00272
00273
00274
00275
00276
00277 uint32 Npc_timer::get_minute
00278 (
00279 )
00280 {
00281 Game_window *gwin = Game_window::get_instance();
00282 return 60*gclock->get_total_hours() + gclock->get_minute();
00283 }
00284
00285
00286
00287
00288
00289 Npc_timer::Npc_timer
00290 (
00291 Npc_timer_list *l,
00292 int start_delay
00293 ) : list(l)
00294 {
00295 gwin->get_tqueue()->add(Game::get_ticks() + start_delay, this, 0L);
00296 }
00297
00298
00299
00300
00301
00302 Npc_timer::~Npc_timer
00303 (
00304 )
00305 {
00306 if (in_queue())
00307 {
00308 Time_queue *tq = Game_window::get_instance()->get_tqueue();
00309 tq->remove(this);
00310 }
00311 }
00312
00313
00314
00315
00316
00317 Npc_hunger_timer::~Npc_hunger_timer
00318 (
00319 )
00320 {
00321 list->hunger = 0;
00322 }
00323
00324
00325
00326
00327
00328 void Npc_hunger_timer::handle_event
00329 (
00330 unsigned long curtime,
00331 long udata
00332 )
00333 {
00334 Actor *npc = list->npc;
00335
00336 if (!npc->is_in_party() ||
00337
00338 npc->get_property(static_cast<int>(Actor::food_level)) >= 0 ||
00339 npc->is_dead())
00340 {
00341 delete this;
00342 return;
00343 }
00344 uint32 minute = get_minute();
00345
00346 if (minute >= last_time + 60)
00347 {
00348 int hp = rand()%3;
00349 if (rand()%4)
00350 npc->say(first_starving, first_starving + 2);
00351 npc->reduce_health(hp);
00352
00353
00354
00355 last_time = minute;
00356 }
00357 gwin->get_tqueue()->add(curtime + 30000, this, 0L);
00358 }
00359
00360
00361
00362
00363
00364 Npc_poison_timer::Npc_poison_timer
00365 (
00366 Npc_timer_list *l
00367 ) : Npc_timer(l, 5000)
00368 {
00369
00370 end_time = Game::get_ticks() + 60000 + rand()%120000;
00371 }
00372
00373
00374
00375
00376
00377 Npc_poison_timer::~Npc_poison_timer
00378 (
00379 )
00380 {
00381 list->poison = 0;
00382 }
00383
00384
00385
00386
00387
00388 void Npc_poison_timer::handle_event
00389 (
00390 unsigned long curtime,
00391 long udata
00392 )
00393 {
00394 Actor *npc = list->npc;
00395 if (curtime >= end_time ||
00396 npc->get_flag(Obj_flags::poisoned) == 0 ||
00397 npc->is_dead())
00398 {
00399 npc->clear_flag(Obj_flags::poisoned);
00400 delete this;
00401 return;
00402 }
00403 int penalty = rand()%3;
00404 npc->reduce_health(penalty);
00405
00406
00407
00408
00409 gwin->get_tqueue()->add(curtime + 10000 + rand()%10000, this, 0L);
00410 }
00411
00412
00413
00414
00415
00416 void Npc_sleep_timer::handle_event
00417 (
00418 unsigned long curtime,
00419 long udata
00420 )
00421 {
00422 Actor *npc = list->npc;
00423 if (curtime >= end_time ||
00424 npc->get_flag(Obj_flags::asleep) == 0)
00425 {
00426
00427 if (npc->get_schedule_type() != Schedule::sleep &&
00428 !npc->is_dead())
00429 {
00430 npc->clear_flag(Obj_flags::asleep);
00431 int frnum = npc->get_framenum();
00432 if ((frnum&0xf) == Actor::sleep_frame &&
00433
00434 !npc->get_info().has_strange_movement())
00435
00436 npc->change_frame(
00437 Actor::standing | (frnum&0x30));
00438 }
00439 delete this;
00440 return;
00441 }
00442
00443 gwin->get_tqueue()->add(curtime + 2000, this, 0L);
00444 }
00445
00446
00447
00448
00449
00450 inline int Wearing_ring
00451 (
00452 Actor *actor,
00453 int shnum,
00454 int frnum
00455 )
00456 {
00457
00458 Game_object *ring = actor->get_readied(Actor::lfinger);
00459 if (ring && ring->get_shapenum() == shnum &&
00460 ring->get_framenum() == frnum)
00461 return 1;
00462 ring = actor->get_readied(Actor::rfinger);
00463 if (ring && ring->get_shapenum() == shnum &&
00464 ring->get_framenum() == frnum)
00465 return 1;
00466 return 0;
00467 }
00468
00469
00470
00471
00472
00473 void Npc_invisibility_timer::handle_event
00474 (
00475 unsigned long curtime,
00476 long udata
00477 )
00478 {
00479 Actor *npc = list->npc;
00480 if (Wearing_ring(npc, 296, 0))
00481 {
00482 delete this;
00483 return;
00484 }
00485 if (curtime >= end_time ||
00486 npc->get_flag(Obj_flags::invisible) == 0)
00487 {
00488 npc->clear_flag(Obj_flags::invisible);
00489 if (!npc->is_dead())
00490 gwin->add_dirty(npc);
00491 delete this;
00492 return;
00493 }
00494
00495 gwin->get_tqueue()->add(curtime + 2000, this, 0L);
00496 }
00497
00498
00499
00500
00501
00502 void Npc_protection_timer::handle_event
00503 (
00504 unsigned long curtime,
00505 long udata
00506 )
00507 {
00508 Actor *npc = list->npc;
00509 if (Wearing_ring(npc, 297, 0))
00510 {
00511 delete this;
00512 return;
00513 }
00514 if (curtime >= end_time ||
00515 npc->get_flag(Obj_flags::protection) == 0)
00516 {
00517 npc->clear_flag(Obj_flags::protection);
00518 if (!npc->is_dead())
00519 gwin->add_dirty(npc);
00520 delete this;
00521 return;
00522 }
00523
00524 gwin->get_tqueue()->add(curtime + 2000, this, 0L);
00525 }
00526
00527
00528
00529
00530
00531 void Npc_flag_timer::handle_event
00532 (
00533 unsigned long curtime,
00534 long udata
00535 )
00536 {
00537 Actor *npc = list->npc;
00538 if (curtime >= end_time ||
00539 npc->get_flag(flag) == 0)
00540 {
00541 npc->clear_flag(flag);
00542 delete this;
00543 }
00544 else
00545 gwin->get_tqueue()->add(curtime + 10000, this, 0L);
00546 }
00547