ScummVM API documentation
events.h
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 modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (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, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #ifndef NUVIE_CORE_EVENT_H
23 #define NUVIE_CORE_EVENT_H
24 
25 #include "ultima/shared/std/containers.h"
26 #include "ultima/shared/std/string.h"
27 #include "ultima/nuvie/misc/call_back.h"
28 #include "ultima/nuvie/keybinding/keys_enum.h"
29 #include "ultima/nuvie/core/obj_manager.h"
30 
31 namespace Ultima {
32 namespace Nuvie {
33 
34 class Actor;
35 class CallbackTarget;
36 class Configuration;
37 class Converse;
38 class Book;
39 class Game;
40 class TimeQueue;
41 class MapWindow;
42 class MsgScroll;
43 class GameClock;
44 class Player;
45 class ViewManager;
46 class UseCode;
47 class GUI;
48 class GUI_Dialog;
49 class Magic;
50 class KeyBinder;
51 class FpsCounter;
52 class ScriptThread;
53 
54 #define NUVIE_INTERVAL 50
55 #define PUSH_FROM_PLAYER false
56 #define PUSH_FROM_OBJECT true
57 
58 #define BUTTON_MASK(MB) (1 << ((int)(MB) - 1))
59 
60 enum EventMode {
61  LOOK_MODE = 0,
62  USE_MODE,
63  GET_MODE,
64  MOVE_MODE,
65  DROP_MODE,
66  TALK_MODE, /* finding an actor to talk to */
67  ATTACK_MODE,
68  PUSH_MODE,
69  REST_MODE, /* modes before this need targets if using the command bar selected action */
70  CAST_MODE,
71  COMBAT_MODE, /* only used to cancel previous actions */
72  SPELL_MODE, //direct spell casting without spell select etc.
73  EQUIP_MODE,
74  WAIT_MODE, /* waiting for something, optionally display prompt when finished */
75  INPUT_MODE,
76  MULTIUSE_MODE,
77  KEYINPUT_MODE,
78  SCRIPT_MODE
79 };
80 
81 extern uint32 nuvieGameCounter;
82 
83 // type of input that event may collect and send somewhere
84 #define EVENTINPUT_MAPCOORD 0
85 #define EVENTINPUT_KEY 1
86 #define EVENTINPUT_STRING 2
87 #define EVENTINPUT_OBJECT 3
88 #define EVENTINPUT_MAPCOORD_DIR 4
89 #define EVENTINPUT_SPELL_NUM 5
90 
94 const Common::KeyCode FIRST_JOY = (Common::KeyCode)400;
95 const Common::KeyCode JOY_UP = FIRST_JOY; // PS d-pad when analog is disabled. left stick when enabled
96 const Common::KeyCode JOY_DOWN = (Common::KeyCode)(FIRST_JOY + 1);
97 const Common::KeyCode JOY_LEFT = (Common::KeyCode)(FIRST_JOY + 2);
98 const Common::KeyCode JOY_RIGHT = (Common::KeyCode)(FIRST_JOY + 3);
99 const Common::KeyCode JOY_RIGHTUP = (Common::KeyCode)(FIRST_JOY + 4);
100 const Common::KeyCode JOY_RIGHTDOWN = (Common::KeyCode)(FIRST_JOY + 5);
101 const Common::KeyCode JOY_LEFTUP = (Common::KeyCode)(FIRST_JOY + 6);
102 const Common::KeyCode JOY_LEFTDOWN = (Common::KeyCode)(FIRST_JOY + 7);
103 const Common::KeyCode JOY_UP2 = (Common::KeyCode)(FIRST_JOY + 8); // PS right stick when analog is enabled
104 const Common::KeyCode JOY_DOWN2 = (Common::KeyCode)(FIRST_JOY + 9);
105 const Common::KeyCode JOY_LEFT2 = (Common::KeyCode)(FIRST_JOY + 10);
106 const Common::KeyCode JOY_RIGHT2 = (Common::KeyCode)(FIRST_JOY + 11);
107 const Common::KeyCode JOY_RIGHTUP2 = (Common::KeyCode)(FIRST_JOY + 12);
108 const Common::KeyCode JOY_RIGHTDOWN2 = (Common::KeyCode)(FIRST_JOY + 13);
109 const Common::KeyCode JOY_LEFTUP2 = (Common::KeyCode)(FIRST_JOY + 14);
110 const Common::KeyCode JOY_LEFTDOWN2 = (Common::KeyCode)(FIRST_JOY + 15);
111 const Common::KeyCode JOY_UP3 = (Common::KeyCode)(FIRST_JOY + 16);
112 const Common::KeyCode JOY_DOWN3 = (Common::KeyCode)(FIRST_JOY + 17);
113 const Common::KeyCode JOY_LEFT3 = (Common::KeyCode)(FIRST_JOY + 18);
114 const Common::KeyCode JOY_RIGHT3 = (Common::KeyCode)(FIRST_JOY + 19);
115 const Common::KeyCode JOY_RIGHTUP3 = (Common::KeyCode)(FIRST_JOY + 20);
116 const Common::KeyCode JOY_RIGHTDOWN3 = (Common::KeyCode)(FIRST_JOY + 21);
117 const Common::KeyCode JOY_LEFTUP3 = (Common::KeyCode)(FIRST_JOY + 22);
118 const Common::KeyCode JOY_LEFTDOWN3 = (Common::KeyCode)(FIRST_JOY + 23);
119 const Common::KeyCode JOY_UP4 = (Common::KeyCode)(FIRST_JOY + 24);
120 const Common::KeyCode JOY_DOWN4 = (Common::KeyCode)(FIRST_JOY + 25);
121 const Common::KeyCode JOY_LEFT4 = (Common::KeyCode)(FIRST_JOY + 26);
122 const Common::KeyCode JOY_RIGHT4 = (Common::KeyCode)(FIRST_JOY + 27);
123 const Common::KeyCode JOY_RIGHTUP4 = (Common::KeyCode)(FIRST_JOY + 28);
124 const Common::KeyCode JOY_RIGHTDOWN4 = (Common::KeyCode)(FIRST_JOY + 29);
125 const Common::KeyCode JOY_LEFTUP4 = (Common::KeyCode)(FIRST_JOY + 30);
126 const Common::KeyCode JOY_LEFTDOWN4 = (Common::KeyCode)(FIRST_JOY + 31);
127 const Common::KeyCode JOY_HAT_UP = (Common::KeyCode)(FIRST_JOY + 32); // PS d-pad when analog is enabled
128 const Common::KeyCode JOY_HAT_DOWN = (Common::KeyCode)(FIRST_JOY + 33);
129 const Common::KeyCode JOY_HAT_LEFT = (Common::KeyCode)(FIRST_JOY + 34);
130 const Common::KeyCode JOY_HAT_RIGHT = (Common::KeyCode)(FIRST_JOY + 35);
131 const Common::KeyCode JOY_HAT_RIGHTUP = (Common::KeyCode)(FIRST_JOY + 36);
132 const Common::KeyCode JOY_HAT_RIGHTDOWN = (Common::KeyCode)(FIRST_JOY + 37);
133 const Common::KeyCode JOY_HAT_LEFTUP = (Common::KeyCode)(FIRST_JOY + 38);
134 const Common::KeyCode JOY_HAT_LEFTDOWN = (Common::KeyCode)(FIRST_JOY + 39);
135 const Common::KeyCode JOY0 = (Common::KeyCode)(FIRST_JOY + 40); // PS triangle
136 const Common::KeyCode JOY1 = (Common::KeyCode)(FIRST_JOY + 41); // PS circle
137 const Common::KeyCode JOY2 = (Common::KeyCode)(FIRST_JOY + 42); // PS x
138 const Common::KeyCode JOY3 = (Common::KeyCode)(FIRST_JOY + 43); // PS square
139 const Common::KeyCode JOY4 = (Common::KeyCode)(FIRST_JOY + 44); // PS L2
140 const Common::KeyCode JOY5 = (Common::KeyCode)(FIRST_JOY + 45); // PS R2
141 const Common::KeyCode JOY6 = (Common::KeyCode)(FIRST_JOY + 46); // PS L1
142 const Common::KeyCode JOY7 = (Common::KeyCode)(FIRST_JOY + 47); // PS R1
143 const Common::KeyCode JOY8 = (Common::KeyCode)(FIRST_JOY + 48); // PS select
144 const Common::KeyCode JOY9 = (Common::KeyCode)(FIRST_JOY + 49); // PS start
145 const Common::KeyCode JOY10 = (Common::KeyCode)(FIRST_JOY + 50); // PS L3 (analog must be enabled)
146 const Common::KeyCode JOY11 = (Common::KeyCode)(FIRST_JOY + 51); // PS R3 (analog must be enabled)
147 const Common::KeyCode JOY12 = (Common::KeyCode)(FIRST_JOY + 52);
148 const Common::KeyCode JOY13 = (Common::KeyCode)(FIRST_JOY + 53);
149 const Common::KeyCode JOY14 = (Common::KeyCode)(FIRST_JOY + 54);
150 const Common::KeyCode JOY15 = (Common::KeyCode)(FIRST_JOY + 55);
151 const Common::KeyCode JOY16 = (Common::KeyCode)(FIRST_JOY + 56);
152 const Common::KeyCode JOY17 = (Common::KeyCode)(FIRST_JOY + 57);
153 const Common::KeyCode JOY18 = (Common::KeyCode)(FIRST_JOY + 58);
154 const Common::KeyCode JOY19 = (Common::KeyCode)(FIRST_JOY + 59);
155 
156 
157 struct EventInput_s {
158  uint8 type; // 0=loc,1=key,2=str,3=obj,4=actor
159 // union
160 // {
161  Common::KeyCode key; // last key entered, if capturing input
162  ActionKeyType action_key_type; // last ActionKeyType entered if capturing input
163  MapCoord *loc; // target location, or direction if relative ???
164  Std::string *str; // ???
165 // };
166  void set_loc(const MapCoord &c);
167  EventInput_s() : loc(0), str(0), obj(0), actor(0), get_direction(false), get_text(false),
168  target_init(0), select_from_inventory(false), select_range(0), key(Common::KEYCODE_INVALID),
169  action_key_type(ActionKeyType::CANCEL_ACTION_KEY), spell_num(0), type(0) {
170  }
171  ~EventInput_s();
172 
173  Obj *obj; // top object at loc (or object from inventory)
174  Actor *actor; // actor at loc
175  bool get_direction; // if true, entering directions selects a target
176  bool get_text; // if true, the MsgScroll is polled for text input
177  MapCoord *target_init; // where MapWindow cursor is centered when targeting
178  bool select_from_inventory; // if true, objects from inventory will be selected (and not from the map)
179  uint8 select_range; // limits movement of MapWindow cursor from center
180  sint16 spell_num;
181 };
182 typedef struct EventInput_s EventInput;
183 
184 class Events : public CallBack {
185  friend class Magic; // FIXME
186 private:
187  const Configuration *config;
188  GUI *gui;
189  Game *game;
190  ObjManager *obj_manager;
191  MapWindow *map_window;
192  MsgScroll *scroll;
193  GameClock *clock;
194  Player *player;
195  Converse *converse;
196  ViewManager *view_manager;
197  UseCode *usecode;
198  Magic *magic;
199  KeyBinder *keybinder;
200  GUI_Dialog *gamemenu_dialog;
201  GUI_Dialog *assetviewer_dialog;
202 
203  Common::Event event;
204  EventMode mode, last_mode;
205  EventInput input; // collected/received input (of any type)
206 // Std::vector<EventMode> mode_stack; // current mode is at the end of the list
207  int ts; //timestamp for TimeLeft() method.
208  int altCodeVal;
209  uint16 active_alt_code; // alt-code that needs more input
210  uint8 alt_code_input_num; // alt-code can get multiple inputs
211 
212  TimeQueue *time_queue, *game_time_queue;
213  Obj *drop_obj;
214  uint16 drop_qty;
215  sint32 drop_x, drop_y; // only to allow pre-targeting from MapWindow, feel free to ignore this
216  uint8 rest_time; // How many hours?
217  uint8 rest_guard; // Who will guard?
218  Obj *push_obj;
219  Actor *push_actor;
220 
221  bool drop_from_key;
222  bool showingDialog;
223  bool showingQuitDialog;
224  bool ignore_timeleft; // do not wait for NUVIE_INTERVAL
225  bool move_in_inventory;
226  bool in_control_cheat;
227  bool looking_at_spellbook;
228  bool direction_selects_target;
229  bool _keymapperStateBeforeKEYINPUT;
230 
231  uint32 fps_timestamp;
232  uint16 fps_counter;
233  FpsCounter *fps_counter_widget;
234  ScriptThread *scriptThread;
235 
236  Common::Point _mousePos;
237  uint8 _buttonsDown;
238 
239  static Events *g_events;
240 protected:
241  inline uint32 TimeLeft();
242 
243  uint16 callback(uint16 msg, CallBack *caller, void *data = nullptr) override;
244  bool handleSDL_KEYDOWN(const Common::Event *event);
245  const char *print_mode(EventMode mode);
246  void try_next_attack();
247 
248 public:
249  enum MouseButton {
250  BUTTON_NONE = 0,
251  BUTTON_LEFT = 1,
252  BUTTON_RIGHT = 2,
253  BUTTON_MIDDLE = 3,
254  MOUSE_LAST
255  };
256 
257  Events(const Configuration *cfg);
258  ~Events() override;
259 
260  void clear();
261 
262  bool init(ObjManager *om, MapWindow *mw, MsgScroll *ms, Player *p, Magic *mg,
263  GameClock *gc, ViewManager *vm, UseCode *uc, GUI *g, KeyBinder *kb);
264  GUI_Dialog *get_gamemenu_dialog() {
265  return gamemenu_dialog;
266  }
267  TimeQueue *get_time_queue() {
268  return time_queue;
269  }
270  TimeQueue *get_game_time_queue() {
271  return game_time_queue;
272  }
273  EventMode get_mode() const {
274  return mode;
275  }
276  EventMode get_last_mode() const {
277  return last_mode;
278  }
279  void set_mode(EventMode new_mode);
280 
281  bool is_direction_selecting_targets() const {
282  return direction_selects_target;
283  }
284  void set_direction_selects_target(bool val) {
285  direction_selects_target = val;
286  }
287 
292  return _mousePos;
293  }
294 
298  byte getButtonState() const {
299  return _buttonsDown;
300  }
301 
302  bool using_pickpocket_cheat;
303  bool cursor_mode;
304  void update_timers();
305  bool update();
306  static MouseButton whichButton(Common::EventType type);
307  bool pollEvent(Common::Event &event);
308  bool handleEvent(const Common::Event *event);
309  void request_input(CallBack *caller, void *user_data = nullptr);
310  void target_spell();
311  void close_spellbook();
312 // Prompt for input.
313 // obsolete:
314 // void useselect_mode(Obj *src, const char *prompt = nullptr); // deprecated
315 // void freeselect_mode(Obj *src, const char *prompt = nullptr); // deprecated
316  void get_scroll_input(const char *allowed = nullptr, bool can_escape = true, bool using_target_cursor = false, bool set_numbers_only_to_true = true);
317  void get_inventory_obj(Actor *actor, bool getting_target = true);
318  void get_spell_num(Actor *caster, Obj *spell_container);
319 // void get_amount();
320  void get_direction(const char *prompt);
321  void get_direction(const MapCoord &from, const char *prompt);
322  void get_target(const char *prompt);
323  void get_target(const MapCoord &init, const char *prompt);
324 // void get_obj_from_inventory(Actor *actor, const char *prompt);
325  void display_portrait(Actor *actor, const char *name = nullptr);
326 // Start a new action, setting a new mode and prompting for input.
327  bool newAction(EventMode new_mode);
328 // void doAction(sint16 rel_x = 0, sint16 rel_y = 0);
329 // void doAction(Obj *obj);
330  void doAction();
331  void cancelAction();
332  void endAction(bool prompt = false);
333 // Send input back to Events, performing an action for the current mode.
334  bool select_obj(Obj *obj, Actor *actor = nullptr);
335  bool select_view_obj(Obj *obj, Actor *actor);
336  bool select_actor(Actor *actor);
337  bool select_direction(sint16 rel_x, sint16 rel_y);
338  bool select_target(uint16 x, uint16 y, uint8 z = 0);
339  bool select_party_member(uint8 num);
340  bool select_spell_num(sint16 spell_num);
341 // bool select_obj(Obj *obj = nullptr, Actor *actor = nullptr);
342 // bool select_obj(sint16 rel_x, sint16 rel_y);
343 // There is no "select_text", as Events polls MsgScroll for new input.
344 // Similarly, a "select_key" is unnecessary. The following method
345 // starts sending all keyboard input to 'caller'. (with the CB_DATA_READY message)
346  void key_redirect(CallBack *caller, void *user_data);
347  void cancel_key_redirect();
348 
349  /* These will be replaced in the future with an InputAction class. */
350  bool move(sint16 rel_x, sint16 rel_y);
351 
352  bool use_start();
353  bool use(sint16 rel_x, sint16 rel_y);
354  bool use(const MapCoord &coord);
355  bool use(Obj *obj);
356  bool use(Actor *actor, uint16 x, uint16 y);
357 
358  bool get_start();
359  bool get(const MapCoord &coord);
360  bool get(sint16 rel_x, sint16 rel_y);
361  bool perform_get(Obj *obj, Obj *container_obj = nullptr, Actor *actor = nullptr);
362 
363  bool look_start();
364  bool lookAtCursor(bool delayed = false, uint16 x = 0, uint16 y = 0, uint8 z = 0, Obj *obj = nullptr, Actor *actor = nullptr);
365  bool look(Obj *obj);
366  bool look(Actor *actor);
367  bool search(Obj *obj);
368 
369  bool talk_start();
370  bool talk_cursor();
371  bool talk(Actor *actor);
372  bool talk(Obj *obj);
373  bool perform_talk(Actor *actor);
374 
375  bool attack();
376 
377  bool push_start();
378  bool pushFrom(Obj *obj);
379  bool pushFrom(sint16 rel_x, sint16 rel_y);
380  bool pushFrom(const MapCoord &target);
381  bool pushTo(Obj *obj, Actor *actor);
382  bool pushTo(sint16 rel_x, sint16 rel_y, bool push_from = PUSH_FROM_PLAYER);
383 
384  void solo_mode(uint32 actor_num);
385  bool party_mode();
386  bool toggle_combat();
387 
388  bool ready(Obj *obj, Actor *actor = nullptr);
389  bool unready(Obj *obj);
390 
391  bool drop_start();
392  bool drop_select(Obj *obj, uint16 qty = 0);
393  bool drop_count(uint16 qty);
394  bool perform_drop();
395  void set_drop_from_key(bool closing_gumps) {
396  drop_from_key = closing_gumps;
397  }
398  bool drop(Obj *obj, uint16 qty, uint16 x, uint16 y);
399  bool drop(uint16 x, uint16 y) {
400  return (drop(drop_obj, drop_qty, x, y));
401  }
402  void set_drop_target(uint16 x, uint16 y) {
403  drop_x = sint32(x);
404  drop_y = sint32(y);
405  }
406  bool can_move_obj_between_actors(Obj *obj, Actor *src_actor, Actor *target_actor, bool display_name = false);
407  void display_not_aboard_vehicle(bool show_prompt = true);
408  void display_move_text(Actor *target_actor, Obj *obj);
409  bool can_get_to_actor(const Actor *actor, uint16 x, uint16 y);
410  bool using_control_cheat() const {
411  return in_control_cheat;
412  }
413  void set_control_cheat(bool control_cheat) {
414  in_control_cheat = control_cheat;
415  }
416  bool is_looking_at_spellbook() const {
417  return looking_at_spellbook;
418  }
419  void set_looking_at_spellbook(bool looking) {
420  looking_at_spellbook = looking;
421  }
422 
423  bool rest();
424  bool rest_input(uint16 input);
425 
426  void cast_spell_directly(uint8 spell_num);
427  bool can_target_icon(); // Target the actor or container tile in inventory and party view
428 
429 // these are both for mouse-using convenience
430  void walk_to_mouse_cursor(uint32 mx, uint32 my);
431  void multiuse(uint16 wx, uint16 wy);
432 
433  void alt_code(int c);
434  void alt_code_input(const char *in);
435  void clear_alt_code() { altCodeVal = 0; }
436 
437  void toggleAltCodeMode(bool enable);
438  void appendAltCode(int code);
439 
440  bool alt_code_teleport(const char *location_string);
441  void alt_code_infostring();
442  void alt_code_teleport_menu(uint32 selection);
443  bool alt_code_teleport_to_person(uint32 npc);
444 
445  void wait();
446  void set_ignore_timeleft(bool newsetting) {
447  ignore_timeleft = newsetting;
448  }
449  EventInput *get_input() {
450  return &input;
451  }
452 // These cursor methods are use to make sure Events knows where the cursor is
453 // when objects are selected with ENTER. (since MapWindow and InventoryView
454 // may each independently show/hide their own cursors)
455  void moveCursorToMapWindow(bool ToggleCursor = false);
456  void moveCursorToInventory();
457 
458  void toggleFpsDisplay();
459  void close_gumps();
460  bool do_not_show_target_cursor;
461  bool dont_show_target_cursor() const;
462  bool input_really_needs_directon() const;
463  void quitDialog();
464  void gameMenuDialog();
465  void assetViewer();
466  bool actor_exists(const Actor *a) const;
467 
468  /* FIXME: Some of the above (action) functions can be removed from public, so
469  that we don't need to check for WAIT mode in all of them. */
470 
474  static Events *get() { return g_events; }
475 };
476 
477 extern bool shouldQuit();
478 
479 } // End of namespace Nuvie
480 } // End of namespace Ultima
481 
482 #endif
byte getButtonState() const
Definition: events.h:298
Definition: map_window.h:73
Definition: actor.h:178
Definition: msg_scroll.h:93
Definition: magic.h:79
Definition: obj.h:84
Definition: configuration.h:61
Definition: keys.h:60
Definition: usecode.h:151
EventType
Definition: events.h:49
Definition: game_clock.h:49
Definition: gui_dialog.h:36
Definition: player.h:41
Definition: events.h:184
Definition: system.h:46
Definition: events.h:157
Definition: detection.h:27
Definition: timed_event.h:45
Definition: call_back.h:50
Definition: string.h:30
Definition: events.h:210
Definition: rect.h:144
Definition: map.h:84
Out move(In first, In last, Out dst)
Definition: algorithm.h:109
Definition: obj_manager.h:75
Definition: script.h:59
Common::Point getMousePos() const
Definition: events.h:291
Definition: fps_counter.h:33
Definition: view_manager.h:57
Definition: game.h:73
Definition: converse.h:81