1 /** 2 * @file 3 * @brief General dungeon events. 4 **/ 5 6 #pragma once 7 8 #include <list> 9 10 #include "player.h" 11 12 // Keep event names in l-dgnevt.cc in sync. 13 enum dgn_event_type 14 { 15 DET_NONE = 0x0000, 16 17 DET_TURN_ELAPSED = 0x0001, 18 DET_MONSTER_MOVED = 0x0002, 19 DET_PLAYER_MOVED = 0x0004, 20 DET_LEAVING_LEVEL = 0x0008, 21 DET_ENTERING_LEVEL = 0x0010, 22 DET_ENTERED_LEVEL = 0x0020, 23 DET_PLAYER_IN_LOS = 0x0040, // Player just entered LOS. 24 DET_PLAYER_CLIMBS = 0x0080, // Player climbing stairs. 25 DET_MONSTER_DIED = 0x0100, 26 DET_ITEM_PICKUP = 0x0200, 27 DET_ITEM_MOVED = 0x0400, 28 DET_FEAT_CHANGE = 0x0800, 29 DET_UNUSED = 0x1000, // open for grabs 30 DET_DOOR_OPENED = 0x2000, 31 DET_DOOR_CLOSED = 0x4000, 32 DET_HP_WARNING = 0x8000, 33 DET_PRESSURE_PLATE = 0x10000, 34 35 DET_GLOBAL_MASK = DET_TURN_ELAPSED | DET_LEAVING_LEVEL 36 | DET_ENTERING_LEVEL | DET_ENTERED_LEVEL 37 | DET_MONSTER_DIED | DET_HP_WARNING, 38 39 DET_POSITION_MASK = DET_MONSTER_MOVED | DET_PLAYER_MOVED 40 | DET_PLAYER_IN_LOS | DET_ITEM_PICKUP 41 | DET_ITEM_MOVED | DET_FEAT_CHANGE 42 | DET_DOOR_OPENED | DET_DOOR_CLOSED 43 | DET_PRESSURE_PLATE, 44 }; 45 46 class dgn_event 47 { 48 public: 49 dgn_event_type type; 50 coord_def place; 51 int elapsed_ticks; 52 int arg1, arg2; 53 coord_def dest; 54 55 public: 56 dgn_event(dgn_event_type t, const coord_def &p = coord_def(), 57 int ticks = you.time_taken, int a1 = 0, int a2 = 0, 58 const coord_def &d = coord_def()) type(t)59 : type(t), place(p), elapsed_ticks(ticks), arg1(a1), 60 arg2(a2), dest(d) 61 { 62 } 63 }; 64 65 class dgn_event_listener 66 { 67 public: 68 virtual ~dgn_event_listener(); 69 // For vetoable events, return false to veto. 70 virtual bool notify_dgn_event(const dgn_event &e) = 0; 71 }; 72 73 // Alarm goes off when something enters this square. 74 struct dgn_square_alarm 75 { dgn_square_alarmdgn_square_alarm76 dgn_square_alarm() : eventmask(0), listeners() { } 77 78 unsigned eventmask; 79 list<dgn_event_listener*> listeners; 80 }; 81 82 struct dgn_listener_def 83 { dgn_listener_defdgn_listener_def84 dgn_listener_def(unsigned mask, dgn_event_listener *l) 85 : eventmask(mask), listener(l) 86 { 87 } 88 89 unsigned eventmask; 90 dgn_event_listener *listener; 91 }; 92 93 // Listeners are not saved here. Map markers have their own 94 // persistence and activation mechanisms. Other listeners must make 95 // their own persistence arrangements. 96 class dgn_event_dispatcher 97 { 98 public: dgn_event_dispatcher()99 dgn_event_dispatcher() : global_event_mask(0), grid_triggers() 100 { 101 } 102 103 void clear(); 104 void clear_listeners_at(const coord_def &pos); 105 bool has_listeners_at(const coord_def &pos) const; 106 void move_listeners(const coord_def &from, const coord_def &to); 107 108 // Returns false if the event is vetoed. 109 bool fire_vetoable_position_event(const dgn_event &e, 110 const coord_def &pos); 111 112 bool fire_vetoable_position_event(dgn_event_type et, 113 const coord_def &pos); 114 115 void fire_position_event(dgn_event_type et, const coord_def &pos); 116 void fire_position_event(const dgn_event &e, const coord_def &pos); 117 void fire_event(dgn_event_type et); 118 void fire_event(const dgn_event &e); 119 120 void register_listener(unsigned evmask, dgn_event_listener *, 121 const coord_def &pos = coord_def()); 122 void remove_listener(dgn_event_listener *, 123 const coord_def &pos = coord_def()); 124 private: 125 void register_listener_at(unsigned mask, const coord_def &pos, 126 dgn_event_listener *l); 127 void remove_listener_at(const coord_def &pos, dgn_event_listener *l); 128 129 private: 130 unsigned global_event_mask; 131 unique_ptr<dgn_square_alarm> grid_triggers[GXM][GYM]; 132 list<dgn_listener_def> listeners; 133 }; 134 135 extern dgn_event_dispatcher dungeon_events; 136