summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/dgnevent.h
blob: 8d77d03b96e36ebd372cfd3bfe037c7a897af888 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
 *  File:       dgnevent.h
 *  Summary:    General dungeon events.
 *  Created by: dshaligram on Sat Jul 21 12:17:29 2007 UTC
 */

#ifndef __DGNEVENT_H__
#define __DGNEVENT_H__

#include "externs.h"
#include "player.h"
#include <list>

// Keep event names in l_dgn.cc in sync.
enum dgn_event_type
{
    DET_NONE            = 0x0000,

    DET_TURN_ELAPSED    = 0x0001,
    DET_MONSTER_MOVED   = 0x0002,
    DET_PLAYER_MOVED    = 0x0004,
    DET_LEAVING_LEVEL   = 0x0008,
    DET_ENTERING_LEVEL  = 0x0010,
    DET_ENTERED_LEVEL   = 0x0020,
    DET_PLAYER_IN_LOS   = 0x0040,   // Player just entered LOS.
    DET_PLAYER_CLIMBS   = 0x0080,   // Player climbing stairs.
    DET_MONSTER_DIED    = 0x0100,
    DET_ITEM_PICKUP     = 0x0200,
    DET_ITEM_MOVED      = 0x0400,
    DET_FEAT_CHANGE     = 0x0800,
    DET_WALL_HIT        = 0x1000,

    DET_GLOBAL_MASK     = DET_TURN_ELAPSED | DET_LEAVING_LEVEL
                        | DET_ENTERING_LEVEL | DET_ENTERED_LEVEL
                        | DET_MONSTER_DIED,

    DET_POSITION_MASK   = DET_MONSTER_MOVED | DET_PLAYER_MOVED
                        | DET_PLAYER_IN_LOS | DET_ITEM_PICKUP
                        | DET_ITEM_MOVED | DET_FEAT_CHANGE | DET_WALL_HIT
};

class dgn_event
{
public:
    dgn_event_type type;
    coord_def      place;
    int            elapsed_ticks;
    long           arg1, arg2;
    coord_def      dest;

public:
    dgn_event(dgn_event_type t, const coord_def &p = coord_def(),
              int ticks = you.time_taken, long a1 = 0, long a2 = 0,
              const coord_def &d = coord_def())
        : type(t), place(p), elapsed_ticks(ticks), arg1(a1),
          arg2(a2), dest(d)
    {
    }
};

class dgn_event_listener
{
public:
    virtual ~dgn_event_listener();
    // For vetoable events, return false to veto.
    virtual bool notify_dgn_event(const dgn_event &e) = 0;
};

// Alarm goes off when something enters this square.
struct dgn_square_alarm
{
public:
    dgn_square_alarm() : eventmask(0), listeners() { }

public:
    unsigned eventmask;
    std::list<dgn_event_listener*> listeners;
};

struct dgn_listener_def
{
public:
    dgn_listener_def(unsigned mask, dgn_event_listener *l)
        : eventmask(mask), listener(l)
    {
    }

public:
    unsigned eventmask;
    dgn_event_listener *listener;
};

// Listeners are not saved here. Map markers have their own
// persistence and activation mechanisms. Other listeners must make
// their own persistence arrangements.
class dgn_event_dispatcher
{
public:
    dgn_event_dispatcher() : global_event_mask(0), grid_triggers()
    {
    }

    void clear();
    void clear_listeners_at(const coord_def &pos);
    bool has_listeners_at(const coord_def &pos) const;
    void move_listeners(const coord_def &from, const coord_def &to);

    // Returns false if the event is vetoed.
    bool fire_vetoable_position_event(const dgn_event &e,
                                      const coord_def &pos);

    bool fire_vetoable_position_event(dgn_event_type et,
                                      const coord_def &pos);

    void fire_position_event(dgn_event_type et, const coord_def &pos);
    void fire_position_event(const dgn_event &e, const coord_def &pos);
    void fire_event(dgn_event_type et);
    void fire_event(const dgn_event &e);

    void register_listener(unsigned evmask, dgn_event_listener *,
                           const coord_def &pos = coord_def());
    void remove_listener(dgn_event_listener *,
                         const coord_def &pos = coord_def());
private:
    void register_listener_at(unsigned mask, const coord_def &pos,
                              dgn_event_listener *l);
    void remove_listener_at(const coord_def &pos, dgn_event_listener *l);

private:
    unsigned global_event_mask;
    std::auto_ptr<dgn_square_alarm> grid_triggers[GXM][GYM];
    std::list<dgn_listener_def> listeners;
};

extern dgn_event_dispatcher dungeon_events;

#endif