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 /*
24 * Based on the Reverse Engineering work of Christophe Fontanel,
25 * maintainer of the Dungeon Master Encyclopaedia (http://dmweb.free.fr/)
26 */
27 
28 #include "common/system.h"
29 #include "graphics/cursorman.h"
30 #include "graphics/thumbnail.h"
31 
32 #include "dm/eventman.h"
33 #include "dm/dungeonman.h"
34 #include "dm/movesens.h"
35 #include "dm/objectman.h"
36 #include "dm/inventory.h"
37 #include "dm/menus.h"
38 #include "dm/timeline.h"
39 #include "dm/projexpl.h"
40 #include "dm/text.h"
41 #include "dm/group.h"
42 #include "dm/dialog.h"
43 #include "dm/sounds.h"
44 
45 
46 namespace DM {
47 
initArrays()48 void EventManager::initArrays() {
49 	KeyboardInput primaryKeyboardInputInterface[7] = { // @ G0458_as_Graphic561_PrimaryKeyboardInput_Interface
50 		/* { Command, Code } */
51 		KeyboardInput(kDMCommandToggleInventoryChampion0, Common::KEYCODE_F1, 0), /* F1 (<CSI>1~) Atari ST: Code = 0x3B00 */
52 		KeyboardInput(kDMCommandToggleInventoryChampion1, Common::KEYCODE_F2, 0), /* F2 (<CSI>2~) Atari ST: Code = 0x3C00 */
53 		KeyboardInput(kDMCommandToggleInventoryChampion2, Common::KEYCODE_F3, 0), /* F3 (<CSI>3~) Atari ST: Code = 0x3D00 */
54 		KeyboardInput(kDMCommandToggleInventoryChampion3, Common::KEYCODE_F4, 0), /* F4 (<CSI>4~) Atari ST: Code = 0x3E00 */
55 		KeyboardInput(kDMCommandSaveGame, Common::KEYCODE_s, Common::KBD_CTRL), /* CTRL-S       Atari ST: Code = 0x0013 */
56 		KeyboardInput(kDMCommandFreezeGame, Common::KEYCODE_ESCAPE, 0), /* Esc (0x1B)   Atari ST: Code = 0x001B */
57 		KeyboardInput(kDMCommandNone, Common::KEYCODE_INVALID, 0)
58 	};
59 
60 	KeyboardInput secondaryKeyboardInputMovement[19] = { // @ G0459_as_Graphic561_SecondaryKeyboardInput_Movement
61 		/* { Command, Code } */
62 		KeyboardInput(kDMCommandTurnLeft, Common::KEYCODE_KP4, 0), /* Numeric pad 4 Atari ST: Code = 0x5200 */
63 		KeyboardInput(kDMCommandMoveForward, Common::KEYCODE_KP5, 0), /* Numeric pad 5 Atari ST: Code = 0x4800 */
64 		KeyboardInput(kDMCommandTurnRight, Common::KEYCODE_KP6, 0), /* Numeric pad 6 Atari ST: Code = 0x4700 */
65 		KeyboardInput(kDMCommandMoveLeft, Common::KEYCODE_KP1, 0), /* Numeric pad 1 Atari ST: Code = 0x4B00 */
66 		KeyboardInput(kDMCommandMoveBackward, Common::KEYCODE_KP2, 0), /* Numeric pad 2 Atari ST: Code = 0x5000 */
67 		KeyboardInput(kDMCommandMoveRight, Common::KEYCODE_KP3, 0), /* Numeric pad 3 Atari ST: Code = 0x4D00. Remaining entries below not present */
68 		KeyboardInput(kDMCommandMoveForward, Common::KEYCODE_w, 0), /* Up Arrow (<CSI>A) */ /*Differs for testing convenience*/
69 		KeyboardInput(kDMCommandMoveForward, Common::KEYCODE_w, Common::KBD_SHIFT), /* Shift Up Arrow (<CSI>T) */ /*Differs for testing convenience*/
70 		KeyboardInput(kDMCommandMoveLeft, Common::KEYCODE_a, 0), /* Backward Arrow (<CSI>D) */ /*Differs for testing convenience*/
71 		KeyboardInput(kDMCommandMoveLeft, Common::KEYCODE_a, Common::KBD_SHIFT), /* Shift Forward Arrow (<CSI> A) */ /*Differs for testing convenience*/
72 		KeyboardInput(kDMCommandMoveRight, Common::KEYCODE_d, 0), /* Forward Arrow (<CSI>C) */ /*Differs for testing convenience*/
73 		KeyboardInput(kDMCommandMoveRight, Common::KEYCODE_d, Common::KBD_SHIFT), /* Shift Backward Arrow (<CSI> @) */ /*Differs for testing convenience*/
74 		KeyboardInput(kDMCommandMoveBackward, Common::KEYCODE_s, 0), /* Down arrow (<CSI>B) */ /*Differs for testing convenience*/
75 		KeyboardInput(kDMCommandMoveBackward, Common::KEYCODE_s, Common::KBD_SHIFT), /* Shift Down arrow (<CSI>S) */ /*Differs for testing convenience*/
76 		KeyboardInput(kDMCommandTurnLeft, Common::KEYCODE_q, 0), /* Del (0x7F) */ /*Differs for testing convenience*/
77 		KeyboardInput(kDMCommandTurnLeft, Common::KEYCODE_q, Common::KBD_SHIFT), /* Shift Del (0x7F) */ /*Differs for testing convenience*/
78 		KeyboardInput(kDMCommandTurnRight, Common::KEYCODE_e, 0), /* Help (<CSI>?~) */ /*Differs for testing convenience*/
79 		KeyboardInput(kDMCommandTurnRight, Common::KEYCODE_e, Common::KBD_SHIFT), /* Shift Help (<CSI>?~) */ /*Differs for testing convenience*/
80 		KeyboardInput(kDMCommandNone, Common::KEYCODE_INVALID, 0)
81 	};
82 	KeyboardInput primaryKeyboardInputPartySleeping[3] = { // @ G0460_as_Graphic561_PrimaryKeyboardInput_PartySleeping
83 		/* { Command, Code } */
84 		KeyboardInput(kDMCommandWakeUp, Common::KEYCODE_RETURN, 0), /* Return */
85 		KeyboardInput(kDMCommandFreezeGame, Common::KEYCODE_ESCAPE, 0), /* Esc */
86 		KeyboardInput(kDMCommandNone, Common::KEYCODE_INVALID, 0)
87 	};
88 	KeyboardInput primaryKeyboardInputFrozenGame[2] = { // @ G0461_as_Graphic561_PrimaryKeyboardInput_FrozenGame
89 		/* { Command, Code } */
90 		KeyboardInput(kDMCommandUnfreezeGame, Common::KEYCODE_ESCAPE, 0), /* Esc */
91 		KeyboardInput(kDMCommandNone, Common::KEYCODE_INVALID, 0)
92 	};
93 	MouseInput primaryMouseInputEntrance[4] = { // @ G0445_as_Graphic561_PrimaryMouseInput_Entrance[4]
94 		/* { Command, Box.X1, Box.X2, Box.Y1, Box.Y2, Button } */
95 		MouseInput(kDMCommandEntranceEnterDungeon, 244, 298,  45,  58, kDMMouseButtonLeft),
96 		// Strangerke - C201_COMMAND_ENTRANCE_RESUME isn't present in the demo
97 		MouseInput(kDMCommandEntranceResume,        244, 298,  76,  93, kDMMouseButtonLeft),
98 		MouseInput(kDMCommandEntranceDrawCredits,  248, 293, 187, 199, kDMMouseButtonLeft),
99 		MouseInput(kDMCommandNone, 0, 0, 0, 0, kDMMouseButtonNone)
100 	};
101 	MouseInput primaryMouseInputRestartGame[2] = { // @ G0446_as_Graphic561_PrimaryMouseInput_RestartGame[2]
102 		/* { Command, Box.X1, Box.X2, Box.Y1, Box.Y2, Button } */
103 		MouseInput(kDMCommandRestartGame, 103, 217, 145, 159, kDMMouseButtonLeft),
104 		MouseInput(kDMCommandNone, 0, 0, 0, 0, kDMMouseButtonNone)
105 	};
106 	MouseInput primaryMouseInputInterface[20] = { // @ G0447_as_Graphic561_PrimaryMouseInput_Interface[20]
107 		/* { Command, Box.X1, Box.X2, Box.Y1, Box.Y2, Button } */
108 		MouseInput(kDMCommandClickInChampion0StatusBox,       0,  42,   0,  28, kDMMouseButtonLeft),
109 		MouseInput(kDMCommandClickInChampion1StatusBox,      69, 111,   0,  28, kDMMouseButtonLeft),
110 		MouseInput(kDMCommandClickInChampion2StatusBox,     138, 180,   0,  28, kDMMouseButtonLeft),
111 		MouseInput(kDMCommandClickInChampion3StatusBox,     207, 249,   0,  28, kDMMouseButtonLeft),
112 		MouseInput(kDMCommandClickOnChamptionIconTopLeft,    274, 299,   0,  13, kDMMouseButtonLeft),
113 		MouseInput(kDMCommandClickOnChamptionIconTopRight,   301, 319,   0,  13, kDMMouseButtonLeft),
114 		MouseInput(kDMCommandClickOnChamptionIconLowerRight, 301, 319,  15,  28, kDMMouseButtonLeft),
115 		MouseInput(kDMCommandClickOnChamptionIconLowerLeft,  274, 299,  15,  28, kDMMouseButtonLeft),
116 		MouseInput(kDMCommandToggleInventoryChampion0,         43,  66,   0,  28, kDMMouseButtonLeft), /* Atari ST: Only present in CSB 2.x and with Box.X1 =  44. swapped with 4 next entries */
117 		MouseInput(kDMCommandToggleInventoryChampion1,        112, 135,   0,  28, kDMMouseButtonLeft), /* Atari ST: Only present in CSB 2.x and with Box.X1 = 113. swapped with 4 next entries */
118 		MouseInput(kDMCommandToggleInventoryChampion2,        181, 204,   0,  28, kDMMouseButtonLeft), /* Atari ST: Only present in CSB 2.x and with Box.X1 = 182. swapped with 4 next entries */
119 		MouseInput(kDMCommandToggleInventoryChampion3,        250, 273,   0,  28, kDMMouseButtonLeft), /* Atari ST: Only present in CSB 2.x and with Box.X1 = 251. swapped with 4 next entries */
120 		MouseInput(kDMCommandToggleInventoryChampion0,          0,  66,   0,  28, kDMMouseButtonRight), /* Atari ST: swapped with 4 previous entries */
121 		MouseInput(kDMCommandToggleInventoryChampion1,         69, 135,   0,  28, kDMMouseButtonRight), /* Atari ST: swapped with 4 previous entries */
122 		MouseInput(kDMCommandToggleInventoryChampion2,        138, 204,   0,  28, kDMMouseButtonRight), /* Atari ST: swapped with 4 previous entries */
123 		MouseInput(kDMCommandToggleInventoryChampion3,        207, 273,   0,  28, kDMMouseButtonRight), /* Atari ST: swapped with 4 previous entries */
124 		MouseInput(kDMCommandClickInSpellArea,                233, 319,  42,  73, kDMMouseButtonLeft),
125 		MouseInput(kDMCommandClickInActionArea,               233, 319,  77, 121, kDMMouseButtonLeft),
126 		MouseInput(kDMCommandFreezeGame,                          0,   1, 198, 199, kDMMouseButtonLeft),
127 		MouseInput(kDMCommandNone, 0, 0, 0, 0, kDMMouseButtonNone)
128 	};
129 	MouseInput secondaryMouseInputMovement[9] = { // @ G0448_as_Graphic561_SecondaryMouseInput_Movement[9]
130 		/* { Command, Box.X1, Box.X2, Box.Y1, Box.Y2, Button } */
131 		MouseInput(kDMCommandTurnLeft,             234, 261, 125, 145, kDMMouseButtonLeft),
132 		MouseInput(kDMCommandMoveForward,          263, 289, 125, 145, kDMMouseButtonLeft),
133 		MouseInput(kDMCommandTurnRight,            291, 318, 125, 145, kDMMouseButtonLeft),
134 		MouseInput(kDMCommandMoveLeft,             234, 261, 147, 167, kDMMouseButtonLeft),
135 		MouseInput(kDMCommandMoveBackward,         263, 289, 147, 167, kDMMouseButtonLeft),
136 		MouseInput(kDMCommandMoveRight,            291, 318, 147, 167, kDMMouseButtonLeft),
137 		MouseInput(kDMCommandClickInDungeonView,   0, 223,  33, 168, kDMMouseButtonLeft),
138 		MouseInput(kDMCommandToggleInventoryLeader, 0, 319,  33, 199, kDMMouseButtonRight),
139 		MouseInput(kDMCommandNone, 0, 0, 0, 0, kDMMouseButtonNone)
140 	};
141 	MouseInput secondaryMouseInputChampionInventory[38] = { // @ G0449_as_Graphic561_SecondaryMouseInput_ChampionInventory[38]
142 		/* { Command, Box.X1, Box.X2, Box.Y1, Box.Y2, Button } */
143 		MouseInput(kDMCommandCloseInventory,                                   0, 319,   0, 199, kDMMouseButtonRight),
144 		MouseInput(kDMCommandSaveGame,                                       174, 182,  36,  44, kDMMouseButtonLeft),
145 		MouseInput(kDMCommandSleep,                                           188, 204,  36,  44, kDMMouseButtonLeft),
146 		MouseInput(kDMCommandCloseInventory,                                 210, 218,  36,  44, kDMMouseButtonLeft),
147 		MouseInput(kDMCommandClickOnSlotBoxInventoryReadyHand ,        6,  21,  86, 101, kDMMouseButtonLeft),
148 		MouseInput(kDMCommandClickOnSlotBoxInventoryActionHand,       62,  77,  86, 101, kDMMouseButtonLeft),
149 		MouseInput(kDMCommandClickOnSlotBoxInventoryHead,              34,  49,  59,  74, kDMMouseButtonLeft),
150 		MouseInput(kDMCommandClickOnSlotBoxInventoryTorso,             34,  49,  79,  94, kDMMouseButtonLeft),
151 		MouseInput(kDMCommandClickOnSlotBoxInventoryLegs,              34,  49,  99, 114, kDMMouseButtonLeft),
152 		MouseInput(kDMCommandClickOnSlotBoxInventoryFeet,              34,  49, 119, 134, kDMMouseButtonLeft),
153 		MouseInput(kDMCommandClickOnSlotBoxInventoryPouch2,            6,  21, 123, 138, kDMMouseButtonLeft),
154 		MouseInput(kDMCommandClickOnMouth,                                   56,  71,  46,  61, kDMMouseButtonLeft),
155 		MouseInput(kDMCommandClickOnEye,                                     12,  27,  46,  61, kDMMouseButtonLeft),
156 		MouseInput(kDMCommandClickOnSlotBoxInventoryQuiverLine2_1,    79,  94, 106, 121, kDMMouseButtonLeft),
157 		MouseInput(kDMCommandClickOnSlotBoxInventoryQuiverLine1_2,    62,  77, 123, 138, kDMMouseButtonLeft),
158 		MouseInput(kDMCommandClickOnSlotBoxInventoryQuiverLine2_2,    79,  94, 123, 138, kDMMouseButtonLeft),
159 		MouseInput(kDMCommandClickOnSlotBoxInventoryNeck,               6,  21,  66,  81, kDMMouseButtonLeft),
160 		MouseInput(kDMCommandClickOnSlotBoxInventoryPouch1,            6,  21, 106, 121, kDMMouseButtonLeft),
161 		MouseInput(kDMCommandClickOnSlotBoxInventoryQuiverLine1_1,    62,  77, 106, 121, kDMMouseButtonLeft),
162 		MouseInput(kDMCommandClickOnSlotBoxInventoryBackpackLine1_1,  66,  81,  66,  81, kDMMouseButtonLeft),
163 		MouseInput(kDMCommandClickOnSlotBoxInventoryBackpackLine2_2,  83,  98,  49,  64, kDMMouseButtonLeft),
164 		MouseInput(kDMCommandClickOnSlotBoxInventoryBackpackLine2_3, 100, 115,  49,  64, kDMMouseButtonLeft),
165 		MouseInput(kDMCommandClickOnSlotBoxInventoryBackpackLine2_4, 117, 132,  49,  64, kDMMouseButtonLeft),
166 		MouseInput(kDMCommandClickOnSlotBoxInventoryBackpackLine2_5, 134, 149,  49,  64, kDMMouseButtonLeft),
167 		MouseInput(kDMCommandClickOnSlotBoxInventoryBackpackLine2_6, 151, 166,  49,  64, kDMMouseButtonLeft),
168 		MouseInput(kDMCommandClickOnSlotBoxInventoryBackpackLine2_7, 168, 183,  49,  64, kDMMouseButtonLeft),
169 		MouseInput(kDMCommandClickOnSlotBoxInventoryBackpackLine2_8, 185, 200,  49,  64, kDMMouseButtonLeft),
170 		MouseInput(kDMCommandClickOnSlotBoxInventoryBackpackLine2_9, 202, 217,  49,  64, kDMMouseButtonLeft),
171 		MouseInput(kDMCommandClickOnSlotBoxInventoryBackpackLine1_2,  83,  98,  66,  81, kDMMouseButtonLeft),
172 		MouseInput(kDMCommandClickOnSlotBoxInventoryBackpackLine1_3, 100, 115,  66,  81, kDMMouseButtonLeft),
173 		MouseInput(kDMCommandClickOnSlotBoxInventoryBackpackLine1_4, 117, 132,  66,  81, kDMMouseButtonLeft),
174 		MouseInput(kDMCommandClickOnSlotBoxInventoryBackpackLine1_5, 134, 149,  66,  81, kDMMouseButtonLeft),
175 		MouseInput(kDMCommandClickOnSlotBoxInventoryBackpackLine1_6, 151, 166,  66,  81, kDMMouseButtonLeft),
176 		MouseInput(kDMCommandClickOnSlotBoxInventoryBackpackLine1_7, 168, 183,  66,  81, kDMMouseButtonLeft),
177 		MouseInput(kDMCommandClickOnSlotBoxInventoryBackpackLine1_8, 185, 200,  66,  81, kDMMouseButtonLeft),
178 		MouseInput(kDMCommandClickOnSlotBoxInventoryBackpackLine1_9, 202, 217,  66,  81, kDMMouseButtonLeft),
179 		MouseInput(kDMCommandClickInPanel,                                   96, 223,  83, 167, kDMMouseButtonLeft),
180 		MouseInput(kDMCommandNone, 0, 0, 0, 0, kDMMouseButtonNone)
181 	};
182 	MouseInput primaryMouseInputPartySleeping[3] = { // @ G0450_as_Graphic561_PrimaryMouseInput_PartySleeping[3]
183 		/* { Command, Box.X1, Box.X2, Box.Y1, Box.Y2, Button } */
184 		MouseInput(kDMCommandWakeUp, 0, 223, 33, 168, kDMMouseButtonLeft),
185 		MouseInput(kDMCommandWakeUp, 0, 223, 33, 168, kDMMouseButtonRight),
186 		MouseInput(kDMCommandNone, 0, 0, 0, 0, kDMMouseButtonNone)
187 	};
188 	MouseInput primaryMouseInputFrozenGame[3] = { // @ G0451_as_Graphic561_PrimaryMouseInput_FrozenGame[3]
189 		/* { Command, Box.X1, Box.X2, Box.Y1, Box.Y2, Button } */
190 		MouseInput(kDMCommandUnfreezeGame, 0, 319, 0, 199, kDMMouseButtonLeft),
191 		MouseInput(kDMCommandUnfreezeGame, 0, 319, 0, 199, kDMMouseButtonRight),
192 		MouseInput(kDMCommandNone, 0, 0, 0, 0, kDMMouseButtonNone)
193 	};
194 	MouseInput mouseInputActionAreaNames[5] = { // @ G0452_as_Graphic561_MouseInput_ActionAreaNames[5]
195 		/* { Command, Box.X1, Box.X2, Box.Y1, Box.Y2, Button } */
196 		MouseInput(kDMCommandClickInActionAreaPass,     285, 318,  77,  83, kDMMouseButtonLeft),
197 		MouseInput(kDMCommandClickInActionAreaAction0, 234, 318,  86,  96, kDMMouseButtonLeft),
198 		MouseInput(kDMCommandClickInActionAreaAction1, 234, 318,  98, 108, kDMMouseButtonLeft),
199 		MouseInput(kDMCommandClickInActionAreaAction2, 234, 318, 110, 120, kDMMouseButtonLeft),
200 		MouseInput(kDMCommandNone, 0, 0, 0, 0, kDMMouseButtonNone)
201 	};
202 	MouseInput mouseInputActionAreaIcons[5] = { // @ G0453_as_Graphic561_MouseInput_ActionAreaIcons[5]
203 		/* { Command, Box.X1, Box.X2, Box.Y1, Box.Y2, Button } */
204 		MouseInput(kDMCommandClickInActionAreaChampion0Action, 233, 252, 86, 120, kDMMouseButtonLeft),
205 		MouseInput(kDMCommandClickInActionAreaChampion1Action, 255, 274, 86, 120, kDMMouseButtonLeft),
206 		MouseInput(kDMCommandClickInActionAreaChampion2Action, 277, 296, 86, 120, kDMMouseButtonLeft),
207 		MouseInput(kDMCommandClickInActionAreaChampion3Action, 299, 318, 86, 120, kDMMouseButtonLeft),
208 		MouseInput(kDMCommandNone, 0, 0, 0, 0, kDMMouseButtonNone)
209 	};
210 	MouseInput mouseInputSpellArea[9] = { // @ G0454_as_Graphic561_MouseInput_SpellArea[9]
211 		/* { Command, Box.X1, Box.X2, Box.Y1, Box.Y2, Button } */
212 		MouseInput(kDMCommandClickInSpellAreaSymbol1,      235, 247, 51, 61, kDMMouseButtonLeft),
213 		MouseInput(kDMCommandClickInSpellAreaSymbol2,      249, 261, 51, 61, kDMMouseButtonLeft),
214 		MouseInput(kDMCommandClickInSpellAreaSymbol3,      263, 275, 51, 61, kDMMouseButtonLeft),
215 		MouseInput(kDMCommandClickInSpellAreaSymbol4,      277, 289, 51, 61, kDMMouseButtonLeft),
216 		MouseInput(kDMCommandClickInSpellAreaSymbol5,      291, 303, 51, 61, kDMMouseButtonLeft),
217 		MouseInput(kDMCommandClickInSpellAreaSymbol6,      305, 317, 51, 61, kDMMouseButtonLeft),
218 		MouseInput(kDMCommandClickInSpeallAreaCastSpell,    234, 303, 63, 73, kDMMouseButtonLeft),
219 		MouseInput(kDMCommandClickInSpellAreaRecantSymbol, 305, 318, 63, 73, kDMMouseButtonLeft),
220 		MouseInput(kDMCommandNone, 0, 0, 0, 0, kDMMouseButtonNone)
221 	};
222 	MouseInput mouseInputChampionNamesHands[13] = { // @ G0455_as_Graphic561_MouseInput_ChampionNamesHands[13]
223 		/* { Command, Box.X1, Box.X2, Box.Y1, Box.Y2, Button } */
224 		MouseInput(kDMCommandSetLeaderChampion0,                                    0,  42,  0,  6, kDMMouseButtonLeft),
225 		MouseInput(kDMCommandSetLeaderChampion1,                                   69, 111,  0,  6, kDMMouseButtonLeft),
226 		MouseInput(kDMCommandSetLeaderChampion2,                                  138, 180,  0,  6, kDMMouseButtonLeft),
227 		MouseInput(kDMCommandSetLeaderChampion3,                                  207, 249,  0,  6, kDMMouseButtonLeft),
228 		MouseInput(kDMCommandClickOnSlotBoxChampion0StatusBoxReadyHand,    4,  19, 10, 25, kDMMouseButtonLeft),
229 		MouseInput(kDMCommandClickOnSlotBoxChampion0StatusBoxActionHand,  24,  39, 10, 25, kDMMouseButtonLeft),
230 		MouseInput(kDMCommandClickOnSlotBoxChampion1StatusBoxReadyHand,   73,  88, 10, 25, kDMMouseButtonLeft),
231 		MouseInput(kDMCommandClickOnSlotBoxChampion1StatusBoxActionHand,  93, 108, 10, 25, kDMMouseButtonLeft),
232 		MouseInput(kDMCommandClickOnSlotBoxChampion2StatusBoxReadyHand,  142, 157, 10, 25, kDMMouseButtonLeft),
233 		MouseInput(kDMCommandClickOnSlotBoxChampion2StatusBoxActionHand, 162, 177, 10, 25, kDMMouseButtonLeft),
234 		MouseInput(kDMCommandClickOnSlotBoxChampion3StatusBoxReadyHand,  211, 226, 10, 25, kDMMouseButtonLeft),
235 		MouseInput(kDMCommandClickOnSlotBoxChampion3StatusBoxActionHand, 231, 246, 10, 25, kDMMouseButtonLeft),
236 		MouseInput(kDMCommandNone, 0, 0, 0, 0, kDMMouseButtonNone)
237 	};
238 	MouseInput mouseInputPanelChest[9] = { // @ G0456_as_Graphic561_MouseInput_PanelChest[9]
239 		/* { Command, Box.X1, Box.X2, Box.Y1, Box.Y2, Button } */
240 		MouseInput(kDMCommandClickOnSlotBoxChest1, 117, 132,  92, 107, kDMMouseButtonLeft),
241 		MouseInput(kDMCommandClickOnSlotBoxChest2, 106, 121, 109, 124, kDMMouseButtonLeft),
242 		MouseInput(kDMCommandClickOnSlotBoxChest3, 111, 126, 126, 141, kDMMouseButtonLeft),
243 		MouseInput(kDMCommandClickOnSlotBoxChest4, 128, 143, 131, 146, kDMMouseButtonLeft),
244 		MouseInput(kDMCommandClickOnSlotBoxChest5, 145, 160, 134, 149, kDMMouseButtonLeft),
245 		MouseInput(kDMCommandClickOnSlotBoxChest6, 162, 177, 136, 151, kDMMouseButtonLeft),
246 		MouseInput(kDMCommandClickOnSlotBoxChest7, 179, 194, 137, 152, kDMMouseButtonLeft),
247 		MouseInput(kDMCommandClickOnSlotBoxChest8, 196, 211, 138, 153, kDMMouseButtonLeft),
248 		MouseInput(kDMCommandNone, 0, 0, 0, 0, kDMMouseButtonNone)
249 	};
250 	MouseInput mouseInputPanelResurrectReincarnateCancel[4] = { // @ G0457_as_Graphic561_MouseInput_PanelResurrectReincarnateCancel[4]
251 		/* { Command, Box.X1, Box.X2, Box.Y1, Box.Y2, Button } */
252 		MouseInput(kDMCommandClickInPanelResurrect,   108, 158,  90, 138, kDMMouseButtonLeft), /* Atari ST: Box = 104, 158,  86, 142 */
253 		MouseInput(kDMCommandClickInPanelReincarnate, 161, 211,  90, 138, kDMMouseButtonLeft), /* Atari ST: Box = 163, 217,  86, 142 */
254 		MouseInput(kDMCommandClickInPanelCancel,      108, 211, 141, 153, kDMMouseButtonLeft), /* Atari ST: Box = 104, 217, 146, 156 */
255 		MouseInput(kDMCommandNone, 0, 0, 0, 0, kDMMouseButtonNone)
256 	};
257 	MouseInput primaryMouseInputViewportDialog1Choice[2] = { // @ G0471_as_Graphic561_PrimaryMouseInput_ViewportDialog1Choice[2]
258 		MouseInput(kDMCommandClickOnDialogChoice1, 16, 207, 138, 152, kDMMouseButtonLeft), /* Bottom button */
259 		MouseInput(kDMCommandNone, 0, 0, 0, 0, kDMMouseButtonNone)
260 	};
261 	MouseInput primaryMouseInputViewportDialog2Choices[3] = { // @ G0472_as_Graphic561_PrimaryMouseInput_ViewportDialog2Choices[3]
262 		MouseInput(kDMCommandClickOnDialogChoice1, 16, 207, 101, 115, kDMMouseButtonLeft), /* Top button */
263 		MouseInput(kDMCommandClickOnDialogChoice2, 16, 207, 138, 152, kDMMouseButtonLeft), /* Bottom button */
264 		MouseInput(kDMCommandNone, 0, 0, 0, 0, kDMMouseButtonNone)
265 	};
266 	MouseInput primaryMouseInputViewportDialog3Choices[4] = { // @ G0473_as_Graphic561_PrimaryMouseInput_ViewportDialog3Choices[4]
267 		MouseInput(kDMCommandClickOnDialogChoice1,  16, 207, 101, 115, kDMMouseButtonLeft), /* Top button */
268 		MouseInput(kDMCommandClickOnDialogChoice2,  16, 101, 138, 152, kDMMouseButtonLeft), /* Lower left button */
269 		MouseInput(kDMCommandClickOnDialogChoice3, 123, 207, 138, 152, kDMMouseButtonLeft), /* Lower right button */
270 		MouseInput(kDMCommandNone, 0, 0, 0, 0, kDMMouseButtonNone)
271 	};
272 	MouseInput primaryMouseInputViewportDialog4Choices[5] = { // @ G0474_as_Graphic561_PrimaryMouseInput_ViewportDialog4Choices[5]
273 		MouseInput(kDMCommandClickOnDialogChoice1,  16, 101, 101, 115, kDMMouseButtonLeft), /* Top left button */
274 		MouseInput(kDMCommandClickOnDialogChoice2, 123, 207, 101, 115, kDMMouseButtonLeft), /* Top right button */
275 		MouseInput(kDMCommandClickOnDialogChoice3,  16, 101, 138, 152, kDMMouseButtonLeft), /* Lower left button */
276 		MouseInput(kDMCommandClickOnDialogChoice4, 123, 207, 138, 152, kDMMouseButtonLeft), /* Lower right button */
277 		MouseInput(kDMCommandNone, 0, 0, 0, 0, kDMMouseButtonNone)
278 	};
279 	MouseInput primaryMouseInputScreenDialog1Choice[2] = { // @ G0475_as_Graphic561_PrimaryMouseInput_ScreenDialog1Choice[2]
280 		MouseInput(kDMCommandClickOnDialogChoice1, 63, 254, 138, 152, kDMMouseButtonLeft), /* Bottom button */
281 		MouseInput(kDMCommandNone, 0, 0, 0, 0, kDMMouseButtonNone)
282 	};
283 	MouseInput primaryMouseInputScreenDialog2Choices[3] = { // @ G0476_as_Graphic561_PrimaryMouseInput_ScreenDialog2Choices[3]
284 		MouseInput(kDMCommandClickOnDialogChoice1, 63, 254, 101, 115, kDMMouseButtonLeft), /* Top button */
285 		MouseInput(kDMCommandClickOnDialogChoice2, 63, 254, 138, 152, kDMMouseButtonLeft), /* Bottom button */
286 		MouseInput(kDMCommandNone, 0, 0, 0, 0, kDMMouseButtonNone)
287 	};
288 	MouseInput primaryMouseInputScreenDialog3Choices[4] = { // @ G0477_as_Graphic561_PrimaryMouseInput_ScreenDialog3Choices[4]
289 		MouseInput(kDMCommandClickOnDialogChoice1,  63, 254, 101, 115, kDMMouseButtonLeft), /* Top button */
290 		MouseInput(kDMCommandClickOnDialogChoice2,  63, 148, 138, 152, kDMMouseButtonLeft), /* Lower left button */
291 		MouseInput(kDMCommandClickOnDialogChoice3, 170, 254, 138, 152, kDMMouseButtonLeft), /* Lower right button */
292 		MouseInput(kDMCommandNone, 0, 0, 0, 0, kDMMouseButtonNone)
293 	};
294 	MouseInput primaryMouseInputScreenDialog4Choices[5] = { // @ G0478_as_Graphic561_PrimaryMouseInput_ScreenDialog4Choices[5]
295 		MouseInput(kDMCommandClickOnDialogChoice1,  63, 148, 101, 115, kDMMouseButtonLeft), /* Top left button */
296 		MouseInput(kDMCommandClickOnDialogChoice2, 170, 254, 101, 115, kDMMouseButtonLeft), /* Top right button */
297 		MouseInput(kDMCommandClickOnDialogChoice3,  63, 148, 138, 152, kDMMouseButtonLeft), /* Lower left button */
298 		MouseInput(kDMCommandClickOnDialogChoice4, 170, 254, 138, 152, kDMMouseButtonLeft), /* Lower right button */
299 		MouseInput(kDMCommandNone, 0, 0, 0, 0, kDMMouseButtonNone)
300 	};
301 
302 	MouseInput *primaryMouseInputDialogSets[2][4] = { // @ G0480_aaps_PrimaryMouseInput_DialogSets
303 		{
304 			_primaryMouseInputViewportDialog1Choice,
305 			_primaryMouseInputViewportDialog2Choices,
306 			_primaryMouseInputViewportDialog3Choices,
307 			_primaryMouseInputViewportDialog4Choices
308 		},
309 		{
310 			_primaryMouseInputScreenDialog1Choice,
311 			_primaryMouseInputScreenDialog2Choices,
312 			_primaryMouseInputScreenDialog3Choices,
313 			_primaryMouseInputScreenDialog4Choices
314 		}
315 	};
316 
317 	for (int i = 0; i < 2; i++) {
318 		_primaryKeyboardInputFrozenGame[i] = primaryKeyboardInputFrozenGame[i];
319 		_primaryMouseInputRestartGame[i] = primaryMouseInputRestartGame[i];
320 		_primaryMouseInputViewportDialog1Choice[i] = primaryMouseInputViewportDialog1Choice[i];
321 		_primaryMouseInputScreenDialog1Choice[i] = primaryMouseInputScreenDialog1Choice[i];
322 		for (int j = 0; j < 4; j++)
323 			_primaryMouseInputDialogSets[i][j] = primaryMouseInputDialogSets[i][j];
324 	}
325 
326 	for (int i = 0; i < 3 ; i++) {
327 		_primaryKeyboardInputPartySleeping[i] = primaryKeyboardInputPartySleeping[i];
328 		_primaryMouseInputPartySleeping[i] = primaryMouseInputPartySleeping[i];
329 		_primaryMouseInputFrozenGame[i] = primaryMouseInputFrozenGame[i];
330 		_primaryMouseInputViewportDialog2Choices[i] = primaryMouseInputViewportDialog2Choices[i];
331 		_primaryMouseInputScreenDialog2Choices[i] = primaryMouseInputScreenDialog2Choices[i];
332 	}
333 
334 	for (int i = 0; i < 4; i++) {
335 		_primaryMouseInputEntrance[i] = primaryMouseInputEntrance[i];
336 		_mouseInputPanelResurrectReincarnateCancel[i] = mouseInputPanelResurrectReincarnateCancel[i];
337 		_primaryMouseInputViewportDialog3Choices[i] = primaryMouseInputViewportDialog3Choices[i];
338 		_primaryMouseInputScreenDialog3Choices[i] = primaryMouseInputScreenDialog3Choices[i];
339 	}
340 
341 	for (int i = 0; i < 5; i++) {
342 		_mouseInputActionAreaNames[i] = mouseInputActionAreaNames[i];
343 		_mouseInputActionAreaIcons[i] = mouseInputActionAreaIcons[i];
344 		_primaryMouseInputViewportDialog4Choices[i] = primaryMouseInputViewportDialog4Choices[i];
345 		_primaryMouseInputScreenDialog4Choices[i] = primaryMouseInputScreenDialog4Choices[i];
346 	}
347 
348 	for (int i = 0; i < 7; i++)
349 		_primaryKeyboardInputInterface[i] = primaryKeyboardInputInterface[i];
350 
351 	for (int i = 0; i < 9; i++) {
352 		_secondaryMouseInputMovement[i] = secondaryMouseInputMovement[i];
353 		_mouseInputSpellArea[i] = mouseInputSpellArea[i];
354 		_mouseInputPanelChest[i] = mouseInputPanelChest[i];
355 	}
356 
357 	for (int i = 0; i < 13; i++)
358 		_mouseInputChampionNamesHands[i] = mouseInputChampionNamesHands[i];
359 
360 	for (int i = 0; i < 19; i++)
361 		_secondaryKeyboardInputMovement[i] = secondaryKeyboardInputMovement[i];
362 
363 	for (int i = 0; i < 20; i++)
364 		_primaryMouseInputInterface[i] = primaryMouseInputInterface[i];
365 
366 	for (int i = 0; i < 38; i++)
367 		_secondaryMouseInputChampionInventory[i] = secondaryMouseInputChampionInventory[i];
368 }
EventManager(DMEngine * vm)369 EventManager::EventManager(DMEngine *vm) : _vm(vm) {
370 	_mousePos = Common::Point(0, 0);
371 	_dummyMapIndex = 0;
372 	_pendingClickPresent = false;
373 	_pendingClickPos = Common::Point(0, 0);
374 	_mousePointerOriginalColorsObject = nullptr;
375 	_mousePointerOriginalColorsChampionIcon = nullptr;
376 	_mousePointerTempBuffer = nullptr;
377 	_isCommandQueueLocked = true;
378 	_mousePointerType = 0;
379 	_previousMousePointerType = 0;
380 	_primaryMouseInput = nullptr;
381 	_secondaryMouseInput = nullptr;
382 	_mousePointerBitmapUpdated = true;
383 	_refreshMousePointerInMainLoop = false;
384 	_highlightBoxEnabled = false;
385 	_useChampionIconOrdinalAsMousePointerBitmap = 0;
386 	_pendingClickButton = kDMMouseButtonNone;
387 	_useObjectAsMousePointerBitmap = false;
388 	_useHandAsMousePointerBitmap = false;
389 	_preventBuildPointerScreenArea = false;
390 	_primaryKeyboardInput = nullptr;
391 	_secondaryKeyboardInput = nullptr;
392 	_ignoreMouseMovements = false;
393 	warning("_g587_hideMousePointerRequestCount should start with value 1");
394 	_hideMousePointerRequestCount = 0;
395 	_mouseButtonStatus = 0;
396 	_highlightScreenBox.setToZero();
397 
398 	initArrays();
399 }
400 
~EventManager()401 EventManager::~EventManager() {
402 	delete[] _mousePointerOriginalColorsObject;
403 	delete[] _mousePointerTempBuffer;
404 	delete[] _mousePointerOriginalColorsChampionIcon;
405 }
406 
initMouse()407 void EventManager::initMouse() {
408 	static uint16 gK150_PalMousePointer[16] = {0x000, 0x666, 0x888, 0x620, 0x0CC, 0x840, 0x080, 0x0C0, 0xF00, 0xFA0, 0xC86, 0xFF0, 0x000, 0xAAA, 0x00F, 0xFFF}; // @ K0150_aui_Palette_MousePointer
409 
410 	if (!_mousePointerOriginalColorsObject)
411 		_mousePointerOriginalColorsObject = new byte[32 * 18];
412 	if (!_mousePointerTempBuffer)
413 		_mousePointerTempBuffer = new byte[32 * 18];
414 	if (!_mousePointerOriginalColorsChampionIcon)
415 		_mousePointerOriginalColorsChampionIcon = new byte[32 * 18];
416 
417 	_mousePointerType = k0_pointerArrow;
418 	_previousMousePointerType = k1_pointerHand;
419 
420 	byte mousePalette[16 * 3];
421 	for (int i = 0; i < 16; ++i) {
422 		mousePalette[i * 3] = (gK150_PalMousePointer[i] >> 8) * (256 / 16);
423 		mousePalette[i * 3 + 1] = (gK150_PalMousePointer[i] >> 4) * (256 / 16);
424 		mousePalette[i * 3 + 2] = gK150_PalMousePointer[i] * (256 / 16);
425 	}
426 	CursorMan.pushCursorPalette(mousePalette, 0, 16);
427 
428 	_mousePos = Common::Point(0, 0);
429 	buildpointerScreenArea(_mousePos.x, _mousePos.y);
430 	CursorMan.showMouse(false);
431 
432 	setMousePos(Common::Point(320 / 2, 200 / 2));
433 }
434 
setMousePointerToNormal(int16 mousePointer)435 void EventManager::setMousePointerToNormal(int16 mousePointer) {
436 	_preventBuildPointerScreenArea = true;
437 	_useObjectAsMousePointerBitmap = false;
438 	_useHandAsMousePointerBitmap = (mousePointer == k1_pointerHand);
439 	_mousePointerBitmapUpdated = true;
440 	_preventBuildPointerScreenArea = false;
441 	buildpointerScreenArea(_mousePos.x, _mousePos.y);
442 }
443 
setPointerToObject(byte * bitmap)444 void EventManager::setPointerToObject(byte *bitmap) {
445 	static byte palChangesMousepointerOjbectIconShadow[16] = {120, 120, 120, 120, 120, 120, 120, 120,
446 		120, 120, 120, 120, 0, 120, 120, 120}; // @ K0027_auc_PaletteChanges_MousePointerObjectIconShadow
447 	static byte palChangesMousePointerIcon[16] = {120, 10, 20, 30, 40, 50, 60, 70, 80, 90,
448 		100, 110, 0, 130, 140, 150}; // @ G0044_auc_Graphic562_PaletteChanges_MousePointerIcon
449 	static Box boxMousePointerObjectShadow(2, 17, 2, 17); // @ G0619_s_Box_MousePointer_ObjectShadow
450 	static Box boxMousePointerObject(0, 15, 0, 15); // @ G0620_s_Box_MousePointer_Object
451 
452 	DisplayMan &displMan = *_vm->_displayMan;
453 
454 	_preventBuildPointerScreenArea = true;
455 	_useObjectAsMousePointerBitmap = true;
456 	_useHandAsMousePointerBitmap = false;
457 	_mousePointerBitmapUpdated = true;
458 	displMan._useByteBoxCoordinates = true;
459 	byte *L0051_puc_Bitmap = _mousePointerOriginalColorsObject;
460 	memset(L0051_puc_Bitmap, 0, 32 * 18);
461 
462 	displMan.blitToBitmapShrinkWithPalChange(bitmap, _mousePointerTempBuffer, 16, 16, 16, 16, palChangesMousepointerOjbectIconShadow);
463 	displMan.blitToBitmap(_mousePointerTempBuffer, L0051_puc_Bitmap, boxMousePointerObjectShadow, 0, 0, 8, 16, kDMColorNoTransparency, 16, 18);
464 	displMan.blitToBitmapShrinkWithPalChange(bitmap, _mousePointerTempBuffer, 16, 16, 16, 16, palChangesMousePointerIcon);
465 	displMan.blitToBitmap(_mousePointerTempBuffer, L0051_puc_Bitmap, boxMousePointerObject, 0, 0, 8, 16, kDMColorBlack, 16, 18);
466 
467 	_preventBuildPointerScreenArea = false;
468 	buildpointerScreenArea(_mousePos.x, _mousePos.y);
469 }
470 
mouseDropChampionIcon()471 void EventManager::mouseDropChampionIcon() {
472 	DisplayMan &displMan = *_vm->_displayMan;
473 
474 	_preventBuildPointerScreenArea = true;
475 	uint16 championIconIndex = _vm->ordinalToIndex(_useChampionIconOrdinalAsMousePointerBitmap);
476 	_useChampionIconOrdinalAsMousePointerBitmap = _vm->indexToOrdinal(kDMChampionNone);
477 	_mousePointerBitmapUpdated = true;
478 	bool useByteBoxCoordinatesBackup = displMan._useByteBoxCoordinates;
479 	displMan.blitToScreen(_mousePointerOriginalColorsChampionIcon, &_vm->_championMan->_boxChampionIcons[championIconIndex << 2], 16, kDMColorDarkestGray, 18);
480 	displMan._useByteBoxCoordinates = useByteBoxCoordinatesBackup;
481 	_preventBuildPointerScreenArea = false;
482 }
483 
buildpointerScreenArea(int16 mousePosX,int16 mousePosY)484 void EventManager::buildpointerScreenArea(int16 mousePosX, int16 mousePosY) {
485 	static unsigned char bitmapArrowPointer[288] = { // @ G0042_auc_Graphic562_Bitmap_ArrowPointer
486 		0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
487 		0x78, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
488 		0x7F, 0x80, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00,
489 		0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
490 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
491 		0x60, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00,
492 		0x7E, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00,
493 		0x6C, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
494 		0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
495 		0xC0, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
496 		0x84, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
497 		0x80, 0x40, 0x00, 0x00, 0x83, 0xC0, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0xA9, 0x00, 0x00, 0x00,
498 		0xC9, 0x00, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00,
499 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00,
500 		0xF0, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00,
501 		0xFF, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00,
502 		0xFE, 0x00, 0x00, 0x00, 0xEF, 0x00, 0x00, 0x00, 0xCF, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00,
503 		0x07, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
504 	};
505 	static unsigned char bitmapHanPointer[288] = { // @ G0043_auc_Graphic562_Bitmap_HandPointer
506 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
507 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
508 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
509 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
510 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x6A, 0x00, 0x00, 0x00,
511 		0x35, 0x40, 0x00, 0x00, 0x1A, 0xA0, 0x00, 0x00, 0x0D, 0x50, 0x00, 0x00, 0x0E, 0xA8, 0x00, 0x00,
512 		0x07, 0xF8, 0x00, 0x00, 0xC7, 0xFC, 0x00, 0x00, 0x67, 0xFC, 0x00, 0x00, 0x77, 0xFC, 0x00, 0x00,
513 		0x3F, 0xFC, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x1F, 0xFE, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00,
514 		0x01, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
515 		0x20, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x4A, 0xA0, 0x00, 0x00, 0x25, 0x50, 0x00, 0x00,
516 		0x12, 0xA8, 0x00, 0x00, 0x11, 0x54, 0x00, 0x00, 0xC8, 0x04, 0x00, 0x00, 0x28, 0x02, 0x00, 0x00,
517 		0x98, 0x02, 0x00, 0x00, 0x88, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00,
518 		0x20, 0x01, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
519 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
520 		0x7F, 0xE0, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x1F, 0xFC, 0x00, 0x00,
521 		0xCF, 0xFC, 0x00, 0x00, 0xEF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00,
522 		0x7F, 0xFE, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x00,
523 		0x07, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
524 	};
525 
526 	_preventBuildPointerScreenArea = true;
527 	if (_useChampionIconOrdinalAsMousePointerBitmap) {
528 		if ((mousePosY > 28) || (mousePosX < 274)) {
529 			_mousePointerType = k4_pointerTypeAutoselect;
530 			mouseDropChampionIcon();
531 		} else
532 			_mousePointerType = k2_pointerTypeChampionIcon;
533 	} else if (mousePosY >= 169)
534 		_mousePointerType = k0_pointerTypeArrow;
535 	else if (mousePosX >= 274)
536 		_mousePointerType = k0_pointerTypeArrow;
537 	else if (mousePosY <= 28) {
538 		uint16 championIdx = mousePosX / 69;
539 		uint16 xOverChampionStatusBox = mousePosX % 69;
540 		if (championIdx >= _vm->_championMan->_partyChampionCount)
541 			_mousePointerType = k4_pointerTypeAutoselect;
542 		else if (xOverChampionStatusBox > 42)
543 			_mousePointerType = k4_pointerTypeAutoselect;
544 		else {
545 			championIdx++;
546 			if (championIdx == _vm->_inventoryMan->_inventoryChampionOrdinal)
547 				_mousePointerType = k0_pointerTypeArrow;
548 			else if (mousePosY <= 6)
549 				_mousePointerType = k0_pointerTypeArrow;
550 			else
551 				_mousePointerType = k4_pointerTypeAutoselect;
552 		}
553 	} else if (mousePosX >= 224)
554 		_mousePointerType = k0_pointerTypeArrow;
555 	else
556 		_mousePointerType = k4_pointerTypeAutoselect;
557 
558 	if (_mousePointerType == k4_pointerTypeAutoselect)
559 		_mousePointerType = (_useObjectAsMousePointerBitmap) ? k1_pointerTypeObjectIcon : (_useHandAsMousePointerBitmap) ? k3_pointerTypeHand : k0_pointerTypeArrow;
560 
561 	if (_mousePointerBitmapUpdated || (_mousePointerType != _previousMousePointerType)) {
562 		_mousePointerBitmapUpdated = false;
563 		switch (_mousePointerType) {
564 		case k0_pointerTypeArrow:
565 			setMousePointerFromSpriteData(bitmapArrowPointer);
566 			break;
567 		case k1_pointerTypeObjectIcon:
568 			CursorMan.replaceCursor(_mousePointerOriginalColorsObject, 32, 18, 0, 0, 0);
569 			break;
570 		case k2_pointerTypeChampionIcon:
571 			CursorMan.replaceCursor(_mousePointerOriginalColorsChampionIcon, 32, 18, 0, 0, 0);
572 			break;
573 		case k3_pointerTypeHand:
574 			setMousePointerFromSpriteData(bitmapHanPointer);
575 			break;
576 		default:
577 			break;
578 		}
579 	}
580 	_previousMousePointerType = _mousePointerType;
581 	_preventBuildPointerScreenArea = false;
582 }
583 
setMousePointer()584 void EventManager::setMousePointer() {
585 	if (_vm->_championMan->_leaderEmptyHanded)
586 		setMousePointerToNormal((_vm->_championMan->_leaderIndex == kDMChampionNone) ? k0_pointerArrow : k1_pointerHand);
587 	else
588 		setPointerToObject(_vm->_objectMan->_objectIconForMousePointer);
589 }
590 
showMouse()591 void EventManager::showMouse() {
592 	if (_hideMousePointerRequestCount++ == 0)
593 		CursorMan.showMouse(true);
594 }
595 
hideMouse()596 void EventManager::hideMouse() {
597 	if (_hideMousePointerRequestCount-- == 1)
598 		CursorMan.showMouse(false);
599 }
600 
isMouseButtonDown(MouseButton button)601 bool EventManager::isMouseButtonDown(MouseButton button) {
602 	return (button != kDMMouseButtonNone) ? (_mouseButtonStatus & button) : (_mouseButtonStatus == 0);
603 }
604 
setMousePos(Common::Point pos)605 void EventManager::setMousePos(Common::Point pos) {
606 	g_system->warpMouse(pos.x, pos.y);
607 }
608 
processInput(Common::Event * grabKey,Common::Event * grabMouseClick)609 Common::EventType EventManager::processInput(Common::Event *grabKey, Common::Event *grabMouseClick) {
610 	Common::Event event;
611 	while (g_system->getEventManager()->pollEvent(event)) {
612 		switch (event.type) {
613 		case Common::EVENT_KEYDOWN: {
614 			if (event.kbdRepeat)
615 				break;
616 
617 			if (grabKey) {
618 				*grabKey = event;
619 				return event.type;
620 			}
621 
622 			if (_primaryKeyboardInput) {
623 				KeyboardInput *input = _primaryKeyboardInput;
624 				while (input->_commandToIssue != kDMCommandNone) {
625 					if ((input->_key == event.kbd.keycode) && (input->_modifiers == (event.kbd.flags & input->_modifiers))) {
626 						processPendingClick(); // possible fix to BUG0_73
627 						_commandQueue.push(Command(Common::Point(-1, -1), input->_commandToIssue));
628 						break;
629 					}
630 					input++;
631 				}
632 			}
633 
634 			if (_secondaryKeyboardInput) {
635 				KeyboardInput *input = _secondaryKeyboardInput;
636 				while (input->_commandToIssue != kDMCommandNone) {
637 					if ((input->_key == event.kbd.keycode) && (input->_modifiers == (event.kbd.flags & input->_modifiers))) {
638 						processPendingClick(); // possible fix to BUG0_73
639 						_commandQueue.push(Command(Common::Point(-1, -1), input->_commandToIssue));
640 						break;
641 					}
642 					input++;
643 				}
644 			}
645 			break;
646 		}
647 		case Common::EVENT_MOUSEMOVE:
648 			if (!_ignoreMouseMovements)
649 				_mousePos = event.mouse;
650 			break;
651 		case Common::EVENT_LBUTTONDOWN:
652 		case Common::EVENT_RBUTTONDOWN: {
653 			MouseButton button = (event.type == Common::EVENT_LBUTTONDOWN) ? kDMMouseButtonLeft : kDMMouseButtonRight;
654 			_mouseButtonStatus |= button;
655 			if (grabMouseClick) {
656 				*grabMouseClick = event;
657 				return event.type;
658 			}
659 			_pendingClickPresent = true;
660 			_pendingClickPos = _mousePos;
661 			_pendingClickButton = button;
662 			break;
663 		}
664 		case Common::EVENT_LBUTTONUP:
665 		case Common::EVENT_RBUTTONUP: {
666 			MouseButton button = (event.type == Common::EVENT_LBUTTONDOWN) ? kDMMouseButtonLeft : kDMMouseButtonRight;
667 			_mouseButtonStatus &= ~button;
668 			resetPressingEyeOrMouth();
669 			break;
670 		}
671 		case Common::EVENT_QUIT:
672 			_vm->_engineShouldQuit = true;
673 			break;
674 		default:
675 			break;
676 		}
677 	}
678 	if (_ignoreMouseMovements)
679 		setMousePos(_mousePos);
680 	return Common::EVENT_INVALID;
681 }
682 
683 
processPendingClick()684 void EventManager::processPendingClick() {
685 	if (_pendingClickPresent) {
686 		_pendingClickPresent = false;
687 		processClick(_pendingClickPos, _pendingClickButton);
688 	}
689 }
690 
processClick(Common::Point mousePos,MouseButton button)691 void EventManager::processClick(Common::Point mousePos, MouseButton button) {
692 	CommandType commandType;
693 
694 	commandType = getCommandTypeFromMouseInput(_primaryMouseInput, mousePos, button);
695 	if (commandType == kDMCommandNone)
696 		commandType = getCommandTypeFromMouseInput(_secondaryMouseInput, mousePos, button);
697 
698 	if (commandType != kDMCommandNone)
699 		_commandQueue.push(Command(mousePos, commandType));
700 
701 	_isCommandQueueLocked = false;
702 }
703 
getCommandTypeFromMouseInput(MouseInput * input,Common::Point mousePos,MouseButton button)704 CommandType EventManager::getCommandTypeFromMouseInput(MouseInput *input, Common::Point mousePos, MouseButton button) {
705 	if (!input)
706 		return kDMCommandNone;
707 
708 	CommandType commandType = kDMCommandNone;
709 	while ((commandType = input->_commandTypeToIssue) != kDMCommandNone) {
710 		if (input->_hitbox.isPointInside(mousePos) && input->_button == button)
711 			break;
712 		input++;
713 	}
714 	return commandType;
715 }
716 
processCommandQueue()717 void EventManager::processCommandQueue() {
718 	static KeyboardInput *primaryKeyboardInputBackup;
719 	static KeyboardInput *secondaryKeyboardInputBackup;
720 	static MouseInput *primaryMouseInputBackup;
721 	static MouseInput *secondaryMouseInputBackup;
722 
723 	DisplayMan &displMan = *_vm->_displayMan;
724 	TextMan &txtMan = *_vm->_textMan;
725 	InventoryMan &inventory = *_vm->_inventoryMan;
726 
727 	_isCommandQueueLocked = true;
728 	if (_commandQueue.empty()) { /* If the command queue is empty */
729 		_isCommandQueueLocked = false;
730 		processPendingClick();
731 		return;
732 	}
733 
734 	Command cmd = _commandQueue.pop();
735 	CommandType cmdType = cmd._type;
736 	if ((cmdType >= kDMCommandMoveForward) && (cmdType <= kDMCommandMoveLeft) && (_vm->_disabledMovementTicks || (_vm->_projectileDisableMovementTicks && (_vm->_lastProjectileDisabledMovementDirection == (_vm->normalizeModulo4(_vm->_dungeonMan->_partyDir + cmdType - kDMCommandMoveForward)))))) { /* If movement is disabled */
737 		_isCommandQueueLocked = false;
738 		processPendingClick();
739 		return;
740 	}
741 
742 	int16 commandX = cmd._pos.x;
743 	int16 commandY = cmd._pos.y;
744 	_isCommandQueueLocked = false;
745 	processPendingClick();
746 	if ((cmdType == kDMCommandTurnRight) || (cmdType == kDMCommandTurnLeft)) {
747 		commandTurnParty(cmdType);
748 		return;
749 	}
750 
751 	if ((cmdType >= kDMCommandMoveForward) && (cmdType <= kDMCommandMoveLeft)) {
752 		commandMoveParty(cmdType);
753 		return;
754 	}
755 
756 	if ((cmdType >= kDMCommandClickInChampion0StatusBox) && (cmdType <= kDMCommandClickInChampion3StatusBox)) {
757 		int16 championIdx = cmdType - kDMCommandClickInChampion0StatusBox;
758 		if ((championIdx < _vm->_championMan->_partyChampionCount) && !_vm->_championMan->_candidateChampionOrdinal)
759 			commandProcessTypes12to27_clickInChampionStatusBox(championIdx, commandX, commandY);
760 
761 		return;
762 	}
763 
764 	if ((cmdType >= kDMCommandClickOnChamptionIconTopLeft) && (cmdType <= kDMCommandClickOnChamptionIconLowerLeft)) {
765 		mouseProcessCommands125To128_clickOnChampionIcon(cmdType - kDMCommandClickOnChamptionIconTopLeft);
766 
767 		return;
768 	}
769 
770 	if ((cmdType >= kDMCommandClickOnSlotBoxInventoryReadyHand) && (cmdType < (kDMCommandClickOnSlotBoxChest8 + 1))) {
771 		if (_vm->_championMan->_leaderIndex != kDMChampionNone)
772 			_vm->_championMan->clickOnSlotBox(cmdType - kDMCommandClickOnSlotBoxChampion0StatusBoxReadyHand);
773 
774 		return;
775 	}
776 
777 	if ((cmdType >= kDMCommandToggleInventoryChampion0) && (cmdType <= kDMCommandCloseInventory)) {
778 		if (cmdType == kDMCommandCloseInventory) {
779 			delete _vm->_saveThumbnail;
780 			_vm->_saveThumbnail = nullptr;
781 		} else if (!_vm->_saveThumbnail) {
782 			_vm->_saveThumbnail = new Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES);
783 			Graphics::saveThumbnail(*_vm->_saveThumbnail);
784 		}
785 
786 		int16 championIndex = cmdType - kDMCommandToggleInventoryChampion0;
787 		if (((championIndex == kDMChampionCloseInventory) || (championIndex < _vm->_championMan->_partyChampionCount)) && !_vm->_championMan->_candidateChampionOrdinal)
788 			inventory.toggleInventory((ChampionIndex)championIndex);
789 
790 		return;
791 	}
792 
793 	if (cmdType == kDMCommandToggleInventoryLeader) {
794 		if (_vm->_championMan->_leaderIndex != kDMChampionNone)
795 			inventory.toggleInventory(_vm->_championMan->_leaderIndex);
796 
797 		return;
798 	}
799 
800 	if (cmdType == kDMCommandClickInSpellArea) {
801 		if ((!_vm->_championMan->_candidateChampionOrdinal) && (_vm->_championMan->_magicCasterChampionIndex != kDMChampionNone))
802 			commandProcessType100_clickInSpellArea(commandX, commandY);
803 
804 		return;
805 	}
806 
807 	if (cmdType == kDMCommandClickInActionArea) {
808 		if (!_vm->_championMan->_candidateChampionOrdinal)
809 			commandProcessType111To115_ClickInActionArea(commandX, commandY);
810 
811 		return;
812 	}
813 
814 	if (cmdType == kDMCommandClickOnMouth) {
815 		inventory.clickOnMouth();
816 		return;
817 	}
818 
819 	if (cmdType == kDMCommandClickOnEye) {
820 		inventory.clickOnEye();
821 		return;
822 	}
823 
824 	if (cmdType == kDMCommandClickInDungeonView) {
825 		commandProcessType80ClickInDungeonView(commandX, commandY);
826 		return;
827 	}
828 	if (cmdType == kDMCommandClickInPanel) {
829 		commandProcess81ClickInPanel(commandX, commandY);
830 		return;
831 	}
832 
833 	if (_vm->_pressingEye || _vm->_pressingMouth)
834 		return;
835 
836 	if (cmdType == kDMCommandSleep) {
837 		if (!_vm->_championMan->_candidateChampionOrdinal) {
838 			if (inventory._inventoryChampionOrdinal)
839 				inventory.toggleInventory(kDMChampionCloseInventory);
840 
841 			_vm->_menuMan->drawDisabledMenu();
842 			_vm->_championMan->_partyIsSleeping = true;
843 			drawSleepScreen();
844 			displMan.drawViewport(k2_viewportAsBeforeSleepOrFreezeGame);
845 			_vm->_waitForInputMaxVerticalBlankCount = 0;
846 			_primaryMouseInput = _primaryMouseInputPartySleeping;
847 			_secondaryMouseInput = 0;
848 			_primaryKeyboardInput = _primaryKeyboardInputPartySleeping;
849 			_secondaryKeyboardInput = nullptr;
850 			discardAllInput();
851 		}
852 		return;
853 	}
854 
855 	if (cmdType == kDMCommandWakeUp) {
856 		_vm->_championMan->wakeUp();
857 		return;
858 	}
859 
860 	if (cmdType == kDMCommandSaveGame) {
861 		if ((_vm->_championMan->_partyChampionCount > 0) && !_vm->_championMan->_candidateChampionOrdinal)
862 			_vm->saveGame();
863 
864 		return;
865 	}
866 
867 	if (cmdType == kDMCommandFreezeGame) {
868 		_vm->_gameTimeTicking = false;
869 		_vm->_menuMan->drawDisabledMenu();
870 		displMan.fillBitmap(displMan._bitmapViewport, kDMColorBlack, 112, 136);
871 
872 		switch (_vm->getGameLanguage()) { // localized
873 		default:
874 		case Common::EN_ANY:
875 			txtMan.printTextToBitmap(displMan._bitmapViewport, k112_byteWidthViewport, 81, 69, kDMColorCyan, kDMColorBlack,
876 												 "GAME FROZEN", k136_heightViewport);
877 			break;
878 		case Common::DE_DEU:
879 			txtMan.printTextToBitmap(displMan._bitmapViewport, k112_byteWidthViewport, 66, 69, kDMColorCyan, kDMColorBlack,
880 												 "SPIEL ANGEHALTEN", k136_heightViewport);
881 			break;
882 		case Common::FR_FRA:
883 			txtMan.printTextToBitmap(displMan._bitmapViewport, k112_byteWidthViewport, 84, 69, kDMColorCyan, kDMColorBlack,
884 												 "JEU BLOQUE", k136_heightViewport);
885 			break;
886 		}
887 		displMan.drawViewport(k2_viewportAsBeforeSleepOrFreezeGame);
888 		primaryMouseInputBackup = _primaryMouseInput;
889 		secondaryMouseInputBackup = _secondaryMouseInput;
890 		primaryKeyboardInputBackup = _primaryKeyboardInput;
891 		secondaryKeyboardInputBackup = _secondaryKeyboardInput;
892 		_primaryMouseInput = _primaryMouseInputFrozenGame;
893 		_secondaryMouseInput = 0;
894 		_primaryKeyboardInput = _primaryKeyboardInputFrozenGame;
895 		_secondaryKeyboardInput = nullptr;
896 		discardAllInput();
897 		return;
898 	}
899 
900 	if (cmdType == kDMCommandUnfreezeGame) {
901 		_vm->_gameTimeTicking = true;
902 		_vm->_menuMan->drawEnabledMenus();
903 		_primaryMouseInput = primaryMouseInputBackup;
904 		_secondaryMouseInput = secondaryMouseInputBackup;
905 		_primaryKeyboardInput = primaryKeyboardInputBackup;
906 		_secondaryKeyboardInput = secondaryKeyboardInputBackup;
907 		discardAllInput();
908 		return;
909 	}
910 
911 	if (cmdType == kDMCommandEntranceEnterDungeon) {
912 		_vm->_gameMode = kDMModeLoadDungeon;
913 		return;
914 	}
915 
916 	if (cmdType == kDMCommandEntranceResume) {
917 		_vm->_gameMode = kDMModeLoadSavedGame;
918 		return;
919 	}
920 
921 	if (cmdType == kDMCommandEntranceDrawCredits) {
922 		_vm->entranceDrawCredits();
923 		return;
924 	}
925 
926 	if ((cmdType >= kDMCommandClickOnDialogChoice1) && (cmdType <= kDMCommandClickOnDialogChoice4)) {
927 		_vm->_dialog->_selectedDialogChoice = cmdType - (kDMCommandClickOnDialogChoice1 - 1);
928 		return;
929 	}
930 
931 	if (cmdType == kDMCommandRestartGame)
932 		_vm->_restartGameRequest = true;
933 }
934 
commandTurnParty(CommandType cmdType)935 void EventManager::commandTurnParty(CommandType cmdType) {
936 	_vm->_stopWaitingForPlayerInput = true;
937 	if (cmdType == kDMCommandTurnLeft)
938 		commandHighlightBoxEnable(234, 261, 125, 145);
939 	else
940 		commandHighlightBoxEnable(291, 318, 125, 145);
941 
942 	uint16 partySquare = _vm->_dungeonMan->getSquare(_vm->_dungeonMan->_partyMapX, _vm->_dungeonMan->_partyMapY).toByte();
943 	if (Square(partySquare).getType() == kDMElementTypeStairs) {
944 		commandTakeStairs(getFlag(partySquare, kDMSquareMaskStairsUp));
945 		return;
946 	}
947 
948 	_vm->_moveSens->processThingAdditionOrRemoval(_vm->_dungeonMan->_partyMapX, _vm->_dungeonMan->_partyMapY, _vm->_thingParty, true, false);
949 	_vm->_championMan->setPartyDirection(_vm->normalizeModulo4(_vm->_dungeonMan->_partyDir + ((cmdType == kDMCommandTurnRight) ? 1 : 3)));
950 	_vm->_moveSens->processThingAdditionOrRemoval(_vm->_dungeonMan->_partyMapX, _vm->_dungeonMan->_partyMapY, _vm->_thingParty, true, true);
951 }
952 
commandMoveParty(CommandType cmdType)953 void EventManager::commandMoveParty(CommandType cmdType) {
954 	static Box boxMovementArrows[4] = { // @ G0463_as_Graphic561_Box_MovementArrows
955 		/* { X1, X2, Y1, Y2 } */
956 		Box(263, 289, 125, 145),   /* Forward */
957 		Box(291, 318, 147, 167),   /* Right */
958 		Box(263, 289, 147, 167),   /* Backward */
959 		Box(234, 261, 147, 167)    /* Left */
960 	};
961 
962 	static int16 movementArrowToStepForwardCount[4] = { // @ G0465_ai_Graphic561_MovementArrowToStepForwardCount
963 		1,   /* Forward */
964 		0,   /* Right */
965 		-1,  /* Backward */
966 		0    /* Left */
967 	};
968 
969 	static int16 movementArrowToSepRightCount[4] = { // @ G0466_ai_Graphic561_MovementArrowToStepRightCount
970 		0,    /* Forward */
971 		1,    /* Right */
972 		0,    /* Backward */
973 		-1    /* Left */
974 	};
975 
976 	_vm->_stopWaitingForPlayerInput = true;
977 	Champion *championsPtr = _vm->_championMan->_champions;
978 	for (uint16 idx = kDMChampionFirst; idx < _vm->_championMan->_partyChampionCount; idx++) {
979 		_vm->_championMan->decrementStamina(idx, ((championsPtr->_load * 3) / _vm->_championMan->getMaximumLoad(championsPtr)) + 1); /* BUG0_50 When a champion is brought back to life at a Vi Altar, his current stamina is lower than what it was before dying. Each time the party moves the current stamina of all champions is decreased, including for dead champions, by an amount that depends on the current load of the champion. For a dead champion the load before he died is used */
980 		championsPtr++;
981 	}
982 	uint16 movementArrowIdx = cmdType - kDMCommandMoveForward;
983 	Box *highlightBox = &boxMovementArrows[movementArrowIdx];
984 	commandHighlightBoxEnable(highlightBox->_rect.left, highlightBox->_rect.right, highlightBox->_rect.top, highlightBox->_rect.bottom);
985 	int16 partyMapX = _vm->_dungeonMan->_partyMapX;
986 	int16 partyMapY = _vm->_dungeonMan->_partyMapY;
987 
988 	Square curSquare = _vm->_dungeonMan->getSquare(partyMapX, partyMapY);
989 	bool isStairsSquare = (curSquare.getType() == kDMElementTypeStairs);
990 	if (isStairsSquare && (movementArrowIdx == 2)) { /* If moving backward while in stairs */
991 		commandTakeStairs(getFlag(curSquare.toByte(), kDMSquareMaskStairsUp));
992 		return;
993 	}
994 
995 	_vm->_dungeonMan->mapCoordsAfterRelMovement(_vm->_dungeonMan->_partyDir, movementArrowToStepForwardCount[movementArrowIdx], movementArrowToSepRightCount[movementArrowIdx], partyMapX, partyMapY);
996 	curSquare = _vm->_dungeonMan->getSquare(partyMapX, partyMapY);
997 
998 	bool isMovementBlocked = false;
999 	ElementType partySquareType = curSquare.getType();
1000 	switch (partySquareType){
1001 	case kDMElementTypeWall:
1002 		isMovementBlocked = true;
1003 		break;
1004 	case kDMElementTypeStairs: {
1005 		_vm->_moveSens->getMoveResult(_vm->_thingParty, _vm->_dungeonMan->_partyMapX, _vm->_dungeonMan->_partyMapY, kDMMapXNotOnASquare, 0);
1006 		_vm->_dungeonMan->_partyMapX = partyMapX;
1007 		_vm->_dungeonMan->_partyMapY = partyMapY;
1008 		byte stairState = curSquare.toByte();
1009 		commandTakeStairs(getFlag(stairState, kDMSquareMaskStairsUp));
1010 		return;
1011 		}
1012 	case kDMElementTypeDoor: {
1013 		byte doorState = curSquare.getDoorState();
1014 		isMovementBlocked = (doorState != kDMDoorStateOpen) && (doorState != kDMDoorStateOneFourth) && (doorState != kDMDoorStateDestroyed);
1015 		}
1016 		break;
1017 	case kDMElementTypeFakeWall: {
1018 		byte wallState = curSquare.toByte();
1019 		isMovementBlocked = (!getFlag(wallState, kDMSquareMaskFakeWallOpen) && !getFlag(wallState, kDMSquareMaskFakeWallImaginary));
1020 		}
1021 		break;
1022 	default:
1023 		break;
1024 	}
1025 
1026 	if (_vm->_championMan->_partyChampionCount) {
1027 		if (isMovementBlocked) {
1028 			movementArrowIdx += (_vm->_dungeonMan->_partyDir + 2);
1029 			int16 firstDamagedChampionIndex = _vm->_championMan->getTargetChampionIndex(partyMapX, partyMapY, _vm->normalizeModulo4(movementArrowIdx));
1030 			int16 secondDamagedChampionIndex = _vm->_championMan->getTargetChampionIndex(partyMapX, partyMapY, _vm->turnDirRight(movementArrowIdx));
1031 			int16 damage = _vm->_championMan->addPendingDamageAndWounds_getDamage(firstDamagedChampionIndex, 1, kDMWoundTorso | kDMWoundLegs, kDMAttackTypeSelf);
1032 			if (firstDamagedChampionIndex != secondDamagedChampionIndex)
1033 				damage |= _vm->_championMan->addPendingDamageAndWounds_getDamage(secondDamagedChampionIndex, 1, kDMWoundTorso | kDMWoundLegs, kDMAttackTypeSelf);
1034 
1035 			if (damage)
1036 				_vm->_sound->requestPlay(kDMSoundIndexPartyDamaged, partyMapX, partyMapY, kDMSoundModePlayImmediately);
1037 		} else {
1038 			isMovementBlocked = (_vm->_groupMan->groupGetThing(partyMapX, partyMapY) != _vm->_thingEndOfList);
1039 			if (isMovementBlocked)
1040 				_vm->_groupMan->processEvents29to41(partyMapX, partyMapY, kDMEventTypeCreateReactionPartyIsAdjacent, 0);
1041 		}
1042 	}
1043 
1044 	// DEBUG CODE: check for Console flag
1045 	if (isMovementBlocked && !_vm->_console->_debugNoclip) {
1046 		discardAllInput();
1047 		_vm->_stopWaitingForPlayerInput = false;
1048 		return;
1049 	}
1050 
1051 	if (isStairsSquare)
1052 		_vm->_moveSens->getMoveResult(_vm->_thingParty, kDMMapXNotOnASquare, 0, partyMapX, partyMapY);
1053 	else
1054 		_vm->_moveSens->getMoveResult(_vm->_thingParty, _vm->_dungeonMan->_partyMapX, _vm->_dungeonMan->_partyMapY, partyMapX, partyMapY);
1055 
1056 	uint16 disabledMovtTicks = 1;
1057 	championsPtr = _vm->_championMan->_champions;
1058 	for (uint16 idx = kDMChampionFirst; idx < _vm->_championMan->_partyChampionCount; idx++) {
1059 		if (championsPtr->_currHealth)
1060 			disabledMovtTicks = MAX((int32)disabledMovtTicks, (int32)_vm->_championMan->getMovementTicks(championsPtr));
1061 
1062 		championsPtr++;
1063 	}
1064 	_vm->_disabledMovementTicks = disabledMovtTicks;
1065 	_vm->_projectileDisableMovementTicks = 0;
1066 }
1067 
isLeaderHandObjThrown(int16 posX,int16 posY)1068 bool EventManager::isLeaderHandObjThrown(int16 posX, int16 posY) {
1069 #define k0_sideLeft 0 // @ C0_SIDE_LEFT
1070 #define k1_sideRight 1 // @ C0_SIDE_LEFT
1071 
1072 	if ((posY < 47) || (posY > 102))
1073 		return false;
1074 
1075 	bool objectThrownFl;
1076 	if (posX <= 111) {
1077 		if (_vm->_dungeonMan->_squareAheadElement == kDMElementTypeDoorFront) {
1078 			if (posX < 64)
1079 				return false;
1080 		} else if (posX < 32)
1081 			return false;
1082 
1083 		// Strangerke: Only present in CSB2.1... But it fixes a bug so we keep it
1084 		objectThrownFl = _vm->_championMan->isLeaderHandObjectThrown(k0_sideLeft);
1085 	} else {
1086 		if (_vm->_dungeonMan->_squareAheadElement == kDMElementTypeDoorFront) {
1087 			if (posX > 163)
1088 				return false;
1089 		} else if (posX > 191)
1090 			return false;
1091 
1092 		objectThrownFl = _vm->_championMan->isLeaderHandObjectThrown(k1_sideRight);
1093 	}
1094 
1095 	if (objectThrownFl)
1096 		_vm->_stopWaitingForPlayerInput = true;
1097 
1098 	return objectThrownFl;
1099 }
1100 
setMousePointerFromSpriteData(byte * mouseSprite)1101 void EventManager::setMousePointerFromSpriteData(byte *mouseSprite) {
1102 	byte bitmap[16 * 18];
1103 	memset(bitmap, 0, sizeof(bitmap));
1104 	for (int16 imgPart = 1; imgPart < 3; ++imgPart) {
1105 		for (byte *line = mouseSprite + 72 * imgPart, *pixel = bitmap;
1106 			 line < mouseSprite + 72 * (imgPart + 1);
1107 			 line += 4) {
1108 
1109 			uint16 words[2];
1110 			words[0] = READ_BE_UINT16(line);
1111 			words[1] = READ_BE_UINT16(line + 2);
1112 			for (int16 i = 15; i >= 0; --i, ++pixel) {
1113 				uint16 val = (((words[0] >> i) & 1) | (((words[1] >> i) & 1) << 1)) << (imgPart & 0x2);
1114 				if (val)
1115 					*pixel = val + 8;
1116 			}
1117 		}
1118 	}
1119 
1120 	CursorMan.replaceCursor(bitmap, 16, 18, 0, 0, 0);
1121 }
1122 
commandSetLeader(ChampionIndex champIndex)1123 void EventManager::commandSetLeader(ChampionIndex champIndex) {
1124 	ChampionMan &cm = *_vm->_championMan;
1125 	ChampionIndex leaderIndex;
1126 
1127 	if ((cm._leaderIndex == champIndex) || ((champIndex != kDMChampionNone) && !cm._champions[champIndex]._currHealth))
1128 		return;
1129 
1130 	if (cm._leaderIndex != kDMChampionNone) {
1131 		leaderIndex = cm._leaderIndex;
1132 		cm._champions[leaderIndex].setAttributeFlag(kDMAttributeLoad, true);
1133 		cm._champions[leaderIndex].setAttributeFlag(kDMAttributeNameTitle, true);
1134 		cm._champions[leaderIndex]._load -= _vm->_dungeonMan->getObjectWeight(cm._leaderHandObject);
1135 		cm._leaderIndex = kDMChampionNone;
1136 		cm.drawChampionState(leaderIndex);
1137 	}
1138 	if (champIndex == kDMChampionNone) {
1139 		cm._leaderIndex = kDMChampionNone;
1140 		return;
1141 	}
1142 	cm._leaderIndex = champIndex;
1143 	Champion *champion = &cm._champions[cm._leaderIndex];
1144 	champion->_dir = _vm->_dungeonMan->_partyDir;
1145 	cm._champions[champIndex]._load += _vm->_dungeonMan->getObjectWeight(cm._leaderHandObject);
1146 	if (_vm->indexToOrdinal(champIndex) != cm._candidateChampionOrdinal) {
1147 		champion->setAttributeFlag(kDMAttributeIcon, true);
1148 		champion->setAttributeFlag(kDMAttributeNameTitle, true);
1149 		cm.drawChampionState(champIndex);
1150 	}
1151 }
1152 
commandProcessType80ClickInDungeonViewTouchFrontWall()1153 void EventManager::commandProcessType80ClickInDungeonViewTouchFrontWall() {
1154 	int16 mapX = _vm->_dungeonMan->_partyMapX + _vm->_dirIntoStepCountEast[_vm->_dungeonMan->_partyDir];
1155 	int16 mapY = _vm->_dungeonMan->_partyMapY + _vm->_dirIntoStepCountNorth[_vm->_dungeonMan->_partyDir];
1156 
1157 	if ((mapX >= 0) && (mapX < _vm->_dungeonMan->_currMapWidth)
1158 		&& (mapY >= 0) && (mapY < _vm->_dungeonMan->_currMapHeight))
1159 		_vm->_stopWaitingForPlayerInput = _vm->_moveSens->sensorIsTriggeredByClickOnWall(mapX, mapY, _vm->returnOppositeDir(_vm->_dungeonMan->_partyDir));
1160 }
1161 
commandProcessType80ClickInDungeonView(int16 posX,int16 posY)1162 void EventManager::commandProcessType80ClickInDungeonView(int16 posX, int16 posY) {
1163 	Box boxObjectPiles[4] = { // @ G0462_as_Graphic561_Box_ObjectPiles
1164 		/* { X1, X2, Y1, Y2 } */
1165 		Box(24, 111, 148, 168),   /* Front left */
1166 		Box(112, 199, 148, 168),  /* Front right */
1167 		Box(112, 183, 122, 147),  /* Back right */
1168 		Box(40, 111, 122, 147)    /* Back left */
1169 	};
1170 
1171 	if (_vm->_dungeonMan->_squareAheadElement == kDMElementTypeDoorFront) {
1172 		if (_vm->_championMan->_leaderIndex == kDMChampionNone)
1173 			return;
1174 
1175 		int16 mapX = _vm->_dungeonMan->_partyMapX + _vm->_dirIntoStepCountEast[_vm->_dungeonMan->_partyDir];
1176 		int16 mapY = _vm->_dungeonMan->_partyMapY + _vm->_dirIntoStepCountNorth[_vm->_dungeonMan->_partyDir];
1177 
1178 		if (_vm->_championMan->_leaderEmptyHanded) {
1179 			Junk *junkPtr = (Junk*)_vm->_dungeonMan->getSquareFirstThingData(mapX, mapY);
1180 			if ((((Door*)junkPtr)->hasButton()) && _vm->_dungeonMan->_dungeonViewClickableBoxes[kDMViewCellDoorButtonOrWallOrn].isPointInside(posX, posY - 33)) {
1181 				_vm->_stopWaitingForPlayerInput = true;
1182 				_vm->_sound->requestPlay(kDMSoundIndexSwitch, _vm->_dungeonMan->_partyMapX, _vm->_dungeonMan->_partyMapY, kDMSoundModePlayIfPrioritized);
1183 				_vm->_moveSens->addEvent(kDMEventTypeDoor, mapX, mapY, kDMCellNorthWest, kDMSensorEffectToggle, _vm->_gameTime + 1);
1184 				return;
1185 			}
1186 		} else if (isLeaderHandObjThrown(posX, posY))
1187 			return;
1188 	}
1189 
1190 	if (_vm->_championMan->_leaderEmptyHanded) {
1191 		for (uint16 currViewCell = kDMViewCellFronLeft; currViewCell < kDMViewCellDoorButtonOrWallOrn + 1; currViewCell++) {
1192 			if (_vm->_dungeonMan->_dungeonViewClickableBoxes[currViewCell].isPointInside(posX, posY - 33)) {
1193 				if (currViewCell == kDMViewCellDoorButtonOrWallOrn) {
1194 					if (!_vm->_dungeonMan->_isFacingAlcove)
1195 						commandProcessType80ClickInDungeonViewTouchFrontWall();
1196 				} else
1197 					processType80_clickInDungeonView_grabLeaderHandObject(currViewCell);
1198 
1199 				return;
1200 			}
1201 		}
1202 	} else {
1203 		Thing thingHandObject = _vm->_championMan->_leaderHandObject;
1204 		Junk *junkPtr = (Junk*)_vm->_dungeonMan->getThingData(thingHandObject);
1205 		if (_vm->_dungeonMan->_squareAheadElement == kDMElementTypeWall) {
1206 			for (uint16 currViewCell = kDMViewCellFronLeft; currViewCell < kDMViewCellFrontRight + 1; currViewCell++) {
1207 				if (boxObjectPiles[currViewCell].isPointInside(posX, posY)) {
1208 					clickInDungeonViewDropLeaderHandObject(currViewCell);
1209 					return;
1210 				}
1211 			}
1212 			if (_vm->_dungeonMan->_dungeonViewClickableBoxes[kDMViewCellDoorButtonOrWallOrn].isPointInside(posX, posY - 33)) {
1213 				if (_vm->_dungeonMan->_isFacingAlcove)
1214 					clickInDungeonViewDropLeaderHandObject(kDMViewCellAlcove);
1215 				else {
1216 					if (_vm->_dungeonMan->_isFacingFountain) {
1217 						uint16 iconIdx = _vm->_objectMan->getIconIndex(thingHandObject);
1218 						uint16 weight = _vm->_dungeonMan->getObjectWeight(thingHandObject);
1219 						if ((iconIdx >= kDMIconIndiceJunkWater) && (iconIdx <= kDMIconIndiceJunkWaterSkin))
1220 							junkPtr->setChargeCount(3); /* Full */
1221 						else if (iconIdx == kDMIconIndicePotionEmptyFlask)
1222 							((Potion*)junkPtr)->setType(kDMPotionTypeWaterFlask);
1223 						else {
1224 							commandProcessType80ClickInDungeonViewTouchFrontWall();
1225 							return;
1226 						}
1227 						_vm->_championMan->drawChangedObjectIcons();
1228 						_vm->_championMan->_champions[_vm->_championMan->_leaderIndex]._load += _vm->_dungeonMan->getObjectWeight(thingHandObject) - weight;
1229 					}
1230 					commandProcessType80ClickInDungeonViewTouchFrontWall();
1231 				}
1232 			}
1233 		} else {
1234 			if (isLeaderHandObjThrown(posX, posY))
1235 				return;
1236 
1237 			for (uint16 currViewCell = kDMViewCellFronLeft; currViewCell < kDMViewCellBackLeft + 1; currViewCell++) {
1238 				if (boxObjectPiles[currViewCell].isPointInside(posX, posY)) {
1239 					clickInDungeonViewDropLeaderHandObject(currViewCell);
1240 					return;
1241 				}
1242 			}
1243 		}
1244 	}
1245 }
1246 
commandProcessCommands160To162ClickInResurrectReincarnatePanel(CommandType commandType)1247 void EventManager::commandProcessCommands160To162ClickInResurrectReincarnatePanel(CommandType commandType) {
1248 	ChampionMan &champMan = *_vm->_championMan;
1249 	InventoryMan &invMan = *_vm->_inventoryMan;
1250 	DisplayMan &dispMan = *_vm->_displayMan;
1251 	DungeonMan &dunMan = *_vm->_dungeonMan;
1252 	TextMan &txtMan = *_vm->_textMan;
1253 
1254 	uint16 championIndex = champMan._partyChampionCount - 1;
1255 	Champion *champ = &champMan._champions[championIndex];
1256 	if (commandType == kDMCommandClickInPanelCancel) {
1257 		invMan.toggleInventory(kDMChampionCloseInventory);
1258 		champMan._candidateChampionOrdinal = _vm->indexToOrdinal(kDMChampionNone);
1259 		if (champMan._partyChampionCount == 1) {
1260 			commandSetLeader(kDMChampionNone);
1261 		}
1262 		champMan._partyChampionCount--;
1263 		Box box;
1264 		box._rect.top = 0;
1265 		box._rect.bottom = 28;
1266 		box._rect.left = championIndex * kDMChampionStatusBoxSpacing;
1267 		box._rect.right = box._rect.left + 66;
1268 		dispMan._useByteBoxCoordinates = false;
1269 		dispMan.fillScreenBox(box, kDMColorBlack);
1270 		dispMan.fillScreenBox(_vm->_championMan->_boxChampionIcons[champMan.getChampionIconIndex(champ->_cell, dunMan._partyDir) * 2], kDMColorBlack);
1271 		_vm->_menuMan->drawEnabledMenus();
1272 		showMouse();
1273 		return;
1274 	}
1275 
1276 	champMan._candidateChampionOrdinal = _vm->indexToOrdinal(kDMChampionNone);
1277 	int16 mapX = dunMan._partyMapX + _vm->_dirIntoStepCountEast[dunMan._partyDir];
1278 	int16 mapY = dunMan._partyMapY + _vm->_dirIntoStepCountNorth[dunMan._partyDir];
1279 
1280 	for (uint16 slotIndex = kDMSlotReadyHand; slotIndex < kDMSlotChest1; slotIndex++) {
1281 		Thing thing = champ->getSlot((ChampionSlot)slotIndex);
1282 		if (thing != _vm->_thingNone) {
1283 			_vm->_dungeonMan->unlinkThingFromList(thing, Thing(0), mapX, mapY);
1284 		}
1285 	}
1286 	Thing thing = dunMan.getSquareFirstThing(mapX, mapY);
1287 	for (;;) { // infinite
1288 		if (thing.getType() == kDMThingTypeSensor) {
1289 			((Sensor*)dunMan.getThingData(thing))->setTypeDisabled();
1290 			break;
1291 		}
1292 		thing = dunMan.getNextThing(thing);
1293 	}
1294 
1295 	if (commandType == kDMCommandClickInPanelReincarnate) {
1296 		champMan.renameChampion(champ);
1297 		if (_vm->_engineShouldQuit)
1298 			return;
1299 		champ->resetSkillsToZero();
1300 
1301 		for (uint16 i = 0; i < 12; i++) {
1302 			uint16 statIndex = _vm->getRandomNumber(7);
1303 			champ->getStatistic((ChampionStatType)statIndex, kDMStatCurrent)++; // returns reference
1304 			champ->getStatistic((ChampionStatType)statIndex, kDMStatMaximum)++; // returns reference
1305 		}
1306 	}
1307 
1308 	if (champMan._partyChampionCount == 1) {
1309 		_vm->_projexpl->_lastPartyMovementTime = _vm->_gameTime;
1310 		commandSetLeader(kDMChampionFirst);
1311 		_vm->_menuMan->setMagicCasterAndDrawSpellArea(kDMChampionFirst);
1312 	} else
1313 		_vm->_menuMan->drawSpellAreaControls(champMan._magicCasterChampionIndex);
1314 
1315 	txtMan.printLineFeed();
1316 	Color champColor = _vm->_championMan->_championColor[championIndex];
1317 	txtMan.printMessage(champColor, champ->_name);
1318 
1319 	switch (_vm->getGameLanguage()) { // localized
1320 	default:
1321 	case Common::EN_ANY:
1322 		txtMan.printMessage(champColor, (commandType == kDMCommandClickInPanelResurrect) ? " RESURRECTED." : " REINCARNATED.");
1323 		break;
1324 	case Common::DE_DEU:
1325 		txtMan.printMessage(champColor, (commandType == kDMCommandClickInPanelResurrect) ? " VOM TODE ERWECKT." : " REINKARNIERT.");
1326 		break;
1327 	case Common::FR_FRA:
1328 		txtMan.printMessage(champColor, (commandType == kDMCommandClickInPanelResurrect) ? " RESSUSCITE." : " REINCARNE.");
1329 		break;
1330 	}
1331 
1332 	invMan.toggleInventory(kDMChampionCloseInventory);
1333 	_vm->_menuMan->drawEnabledMenus();
1334 	setMousePointerToNormal((_vm->_championMan->_leaderIndex == kDMChampionNone) ? k0_pointerArrow : k1_pointerHand);
1335 }
1336 
commandProcess81ClickInPanel(int16 x,int16 y)1337 void EventManager::commandProcess81ClickInPanel(int16 x, int16 y) {
1338 	ChampionMan &champMan = *_vm->_championMan;
1339 	InventoryMan &invMan = *_vm->_inventoryMan;
1340 
1341 	CommandType commandType;
1342 	switch (invMan._panelContent) {
1343 	case kDMPanelContentChest:
1344 		if (champMan._leaderIndex == kDMChampionNone) // if no leader
1345 			return;
1346 		commandType = getCommandTypeFromMouseInput(_mouseInputPanelChest, Common::Point(x, y), kDMMouseButtonLeft);
1347 		if (commandType != kDMCommandNone)
1348 			champMan.clickOnSlotBox(commandType - kDMCommandClickOnSlotBoxChampion0StatusBoxReadyHand);
1349 		break;
1350 	case kDMPanelContentResurrectReincarnate:
1351 		if (!champMan._leaderEmptyHanded)
1352 			break;
1353 		commandType = getCommandTypeFromMouseInput(_mouseInputPanelResurrectReincarnateCancel, Common::Point(x, y), kDMMouseButtonLeft);
1354 		if (commandType != kDMCommandNone)
1355 			commandProcessCommands160To162ClickInResurrectReincarnatePanel(commandType);
1356 		break;
1357 	default:
1358 		break;
1359 	}
1360 }
1361 
processType80_clickInDungeonView_grabLeaderHandObject(uint16 viewCell)1362 void EventManager::processType80_clickInDungeonView_grabLeaderHandObject(uint16 viewCell) {
1363 	if (_vm->_championMan->_leaderIndex == kDMChampionNone)
1364 		return;
1365 
1366 	int16 mapX = _vm->_dungeonMan->_partyMapX;
1367 	int16 mapY = _vm->_dungeonMan->_partyMapY;
1368 	if (viewCell >= kDMViewCellBackRight) {
1369 		mapX += _vm->_dirIntoStepCountEast[_vm->_dungeonMan->_partyDir];
1370 		mapY += _vm->_dirIntoStepCountNorth[_vm->_dungeonMan->_partyDir];
1371 		Thing groupThing = _vm->_groupMan->groupGetThing(mapX, mapY);
1372 		if ((groupThing != _vm->_thingEndOfList) &&
1373 			!_vm->_moveSens->isLevitating(groupThing) &&
1374 			_vm->_groupMan->getCreatureOrdinalInCell((Group*)_vm->_dungeonMan->getThingData(groupThing), _vm->normalizeModulo4(viewCell + _vm->_dungeonMan->_partyDir))) {
1375 			return; /* It is not possible to grab an object on floor if there is a non levitating creature on its cell */
1376 		}
1377 	}
1378 
1379 	Thing topPileThing = _vm->_dungeonMan->_pileTopObject[viewCell];
1380 	if (_vm->_objectMan->getIconIndex(topPileThing) != kDMIconIndiceNone) {
1381 		_vm->_moveSens->getMoveResult(topPileThing, mapX, mapY, kDMMapXNotOnASquare, 0);
1382 		_vm->_championMan->putObjectInLeaderHand(topPileThing, true);
1383 	}
1384 
1385 	_vm->_stopWaitingForPlayerInput = true;
1386 }
1387 
clickInDungeonViewDropLeaderHandObject(uint16 viewCell)1388 void EventManager::clickInDungeonViewDropLeaderHandObject(uint16 viewCell) {
1389 	if (_vm->_championMan->_leaderIndex == kDMChampionNone)
1390 		return;
1391 
1392 	int16 mapX = _vm->_dungeonMan->_partyMapX;
1393 	int16 mapY = _vm->_dungeonMan->_partyMapY;
1394 	bool droppingIntoAnAlcove = (viewCell == kDMViewCellAlcove);
1395 	if (droppingIntoAnAlcove)
1396 		viewCell = kDMViewCellBackRight;
1397 
1398 	if (viewCell > kDMViewCellFrontRight) {
1399 		mapX += _vm->_dirIntoStepCountEast[_vm->_dungeonMan->_partyDir];
1400 		mapY += _vm->_dirIntoStepCountNorth[_vm->_dungeonMan->_partyDir];
1401 	}
1402 
1403 	uint16 currCell = _vm->normalizeModulo4(_vm->_dungeonMan->_partyDir + viewCell);
1404 	Thing removedThing = _vm->_championMan->getObjectRemovedFromLeaderHand();
1405 	_vm->_moveSens->getMoveResult(_vm->thingWithNewCell(removedThing, currCell), kDMMapXNotOnASquare, 0, mapX, mapY);
1406 	if (droppingIntoAnAlcove && _vm->_dungeonMan->_isFacingViAltar && (_vm->_objectMan->getIconIndex(removedThing) == kDMIconIndiceJunkChampionBones)) {
1407 		Junk *removedJunk = (Junk*)_vm->_dungeonMan->getThingData(removedThing);
1408 		TimelineEvent newEvent;
1409 		newEvent._mapTime = _vm->setMapAndTime(_vm->_dungeonMan->_partyMapIndex, _vm->_gameTime + 1);
1410 		newEvent._type = kDMEventTypeViAltarRebirth;
1411 		newEvent._priority = removedJunk->getChargeCount();
1412 		newEvent._Bu._location._mapX = mapX;
1413 		newEvent._Bu._location._mapY = mapY;
1414 		newEvent._Cu.A._cell = currCell;
1415 		newEvent._Cu.A._effect = kDMSensorEffectToggle;
1416 		_vm->_timeline->addEventGetEventIndex(&newEvent);
1417 	}
1418 	_vm->_stopWaitingForPlayerInput = true;
1419 }
1420 
hasPendingClick(Common::Point & point,MouseButton button)1421 bool EventManager::hasPendingClick(Common::Point& point, MouseButton button) {
1422 	if (_pendingClickButton && button == _pendingClickButton)
1423 		point = _pendingClickPos;
1424 
1425 	return _pendingClickPresent;
1426 }
1427 
drawSleepScreen()1428 void EventManager::drawSleepScreen() {
1429 	DisplayMan &displMan = *_vm->_displayMan;
1430 	TextMan &txtMan = *_vm->_textMan;
1431 
1432 	displMan.fillBitmap(displMan._bitmapViewport, kDMColorBlack, 112, 136);
1433 	switch (_vm->getGameLanguage()) { // localized
1434 	default:
1435 	case Common::EN_ANY:
1436 		txtMan.printTextToBitmap(displMan._bitmapViewport, k112_byteWidthViewport, 93, 69, kDMColorCyan, kDMColorBlack, "WAKE UP", k136_heightViewport);
1437 		break;
1438 	case Common::DE_DEU:
1439 		txtMan.printTextToBitmap(displMan._bitmapViewport, k112_byteWidthViewport, 96, 69, kDMColorCyan, kDMColorBlack, "WECKEN", k136_heightViewport);
1440 		break;
1441 	case Common::FR_FRA:
1442 		txtMan.printTextToBitmap(displMan._bitmapViewport, k112_byteWidthViewport, 72, 69, kDMColorCyan, kDMColorBlack, "REVEILLEZ-VOUS", k136_heightViewport);
1443 		break;
1444 	}
1445 }
1446 
discardAllInput()1447 void EventManager::discardAllInput() {
1448 	Common::Event event;
1449 	while (g_system->getEventManager()->pollEvent(event) && !_vm->_engineShouldQuit) {
1450 		if (event.type == Common::EVENT_QUIT)
1451 			_vm->_engineShouldQuit = true;
1452 	}
1453 	_commandQueue.clear();
1454 }
1455 
commandTakeStairs(bool stairsGoDown)1456 void EventManager::commandTakeStairs(bool stairsGoDown) {
1457 	_vm->_moveSens->getMoveResult(_vm->_thingParty, _vm->_dungeonMan->_partyMapX, _vm->_dungeonMan->_partyMapY, kDMMapXNotOnASquare, 0);
1458 	_vm->_newPartyMapIndex = _vm->_dungeonMan->getLocationAfterLevelChange(_vm->_dungeonMan->_partyMapIndex, stairsGoDown ? -1 : 1, &_vm->_dungeonMan->_partyMapX, &_vm->_dungeonMan->_partyMapY);
1459 	_vm->_dungeonMan->setCurrentMap(_vm->_newPartyMapIndex);
1460 	_vm->_championMan->setPartyDirection(_vm->_dungeonMan->getStairsExitDirection(_vm->_dungeonMan->_partyMapX, _vm->_dungeonMan->_partyMapY));
1461 	_vm->_dungeonMan->setCurrentMap(_vm->_dungeonMan->_partyMapIndex);
1462 }
1463 
commandProcessTypes12to27_clickInChampionStatusBox(uint16 champIndex,int16 posX,int16 posY)1464 void EventManager::commandProcessTypes12to27_clickInChampionStatusBox(uint16 champIndex, int16 posX, int16 posY) {
1465 	if (_vm->indexToOrdinal(champIndex) == _vm->_inventoryMan->_inventoryChampionOrdinal) {
1466 		commandSetLeader((ChampionIndex)champIndex);
1467 	} else {
1468 		uint16 commandType = getCommandTypeFromMouseInput(_mouseInputChampionNamesHands, Common::Point(posX, posY), kDMMouseButtonLeft);
1469 		if ((commandType >= kDMCommandSetLeaderChampion0) && (commandType <= kDMCommandSetLeaderChampion3))
1470 			commandSetLeader((ChampionIndex)(commandType - kDMCommandSetLeaderChampion0));
1471 		else if ((commandType >= kDMCommandClickOnSlotBoxChampion0StatusBoxReadyHand) && (commandType <= kDMCommandClickOnSlotBoxChampion3StatusBoxActionHand))
1472 			_vm->_championMan->clickOnSlotBox(commandType - kDMCommandClickOnSlotBoxChampion0StatusBoxReadyHand);
1473 	}
1474 }
1475 
mouseProcessCommands125To128_clickOnChampionIcon(uint16 champIconIndex)1476 void EventManager::mouseProcessCommands125To128_clickOnChampionIcon(uint16 champIconIndex) {
1477 	static Box championIconShadowBox = Box(2, 20, 2, 15);
1478 	static Box championIconBox = Box(0, 18, 0, 13);
1479 	static byte mousePointerIconShadowBox[16] = {0, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 0, 120, 120, 120};
1480 
1481 	DisplayMan &displMan = *_vm->_displayMan;
1482 
1483 	_preventBuildPointerScreenArea = true;
1484 	if (!_useChampionIconOrdinalAsMousePointerBitmap) {
1485 		if (_vm->_championMan->getIndexInCell(_vm->normalizeModulo4(champIconIndex + _vm->_dungeonMan->_partyDir)) == kDMChampionNone) {
1486 			_preventBuildPointerScreenArea = false;
1487 			return;
1488 		}
1489 		_mousePointerBitmapUpdated = true;
1490 		_useChampionIconOrdinalAsMousePointerBitmap = true;
1491 		displMan._useByteBoxCoordinates = false;
1492 		byte *tmpBitmap = _mousePointerTempBuffer;
1493 		memset(tmpBitmap, 0, 32 * 18);
1494 		Box *curChampionIconBox = &_vm->_championMan->_boxChampionIcons[champIconIndex];
1495 
1496 		displMan.blitToBitmap(displMan._bitmapScreen, tmpBitmap, championIconShadowBox, curChampionIconBox->_rect.left, curChampionIconBox->_rect.top, k160_byteWidthScreen, k16_byteWidth, kDMColorBlack, 200, 18);
1497 		displMan.blitToBitmapShrinkWithPalChange(tmpBitmap, _mousePointerOriginalColorsChampionIcon, 32, 18, 32, 18, mousePointerIconShadowBox);
1498 		displMan.blitToBitmap(displMan._bitmapScreen, _mousePointerOriginalColorsChampionIcon, championIconBox, curChampionIconBox->_rect.left, curChampionIconBox->_rect.top, k160_byteWidthScreen, k16_byteWidth, kDMColorBlack, 200, 18);
1499 		displMan.fillScreenBox(*curChampionIconBox, kDMColorBlack);
1500 		_useChampionIconOrdinalAsMousePointerBitmap = _vm->indexToOrdinal(champIconIndex);
1501 	} else {
1502 		_mousePointerBitmapUpdated = true;
1503 		uint16 championIconIndex = _vm->ordinalToIndex(_useChampionIconOrdinalAsMousePointerBitmap);
1504 		_useChampionIconOrdinalAsMousePointerBitmap = _vm->indexToOrdinal(kDMChampionNone);
1505 		int16 championCellIndex = _vm->_championMan->getIndexInCell(_vm->normalizeModulo4(championIconIndex + _vm->_dungeonMan->_partyDir));
1506 		if (championIconIndex == champIconIndex) {
1507 			setFlag(_vm->_championMan->_champions[championCellIndex]._attributes, kDMAttributeIcon);
1508 			_vm->_championMan->drawChampionState((ChampionIndex)championCellIndex);
1509 		} else {
1510 			int16 championIndex = _vm->_championMan->getIndexInCell(_vm->normalizeModulo4(champIconIndex + _vm->_dungeonMan->_partyDir));
1511 			if (championIndex >= 0) {
1512 				_vm->_championMan->_champions[championIndex]._cell = (ViewCell)_vm->normalizeModulo4(championIconIndex + _vm->_dungeonMan->_partyDir);
1513 				setFlag(_vm->_championMan->_champions[championIndex]._attributes, kDMAttributeIcon);
1514 				_vm->_championMan->drawChampionState((ChampionIndex)championIndex);
1515 			} else
1516 				displMan.fillScreenBox(_vm->_championMan->_boxChampionIcons[championIconIndex], kDMColorBlack);
1517 
1518 			_vm->_championMan->_champions[championCellIndex]._cell = (ViewCell)_vm->normalizeModulo4(champIconIndex + _vm->_dungeonMan->_partyDir);
1519 			setFlag(_vm->_championMan->_champions[championCellIndex]._attributes, kDMAttributeIcon);
1520 			_vm->_championMan->drawChampionState((ChampionIndex)championCellIndex);
1521 		}
1522 	}
1523 	_preventBuildPointerScreenArea = false;
1524 	buildpointerScreenArea(_mousePos.x, _mousePos.y);
1525 }
1526 
commandProcessType100_clickInSpellArea(uint16 posX,uint16 posY)1527 void EventManager::commandProcessType100_clickInSpellArea(uint16 posX, uint16 posY) {
1528 	ChampionIndex championIndex = kDMChampionNone;
1529 	if (posY <= 48) {
1530 		switch (_vm->_championMan->_magicCasterChampionIndex) {
1531 		case 0:
1532 			if ((posX >= 280) && (posX <= 291))
1533 				championIndex = kDMChampionSecond;
1534 			else if ((posX >= 294) && (posX <= 305))
1535 				championIndex = kDMChampionThird;
1536 			else if (posX >= 308)
1537 				championIndex = kDMChampionFourth;
1538 
1539 			break;
1540 		case 1:
1541 			if ((posX >= 233) && (posX <= 244))
1542 				championIndex = kDMChampionFirst;
1543 			else if ((posX >= 294) && (posX <= 305))
1544 				championIndex = kDMChampionThird;
1545 			else if (posX >= 308)
1546 				championIndex = kDMChampionFourth;
1547 
1548 			break;
1549 		case 2:
1550 			if ((posX >= 233) && (posX <= 244))
1551 				championIndex = kDMChampionFirst;
1552 			else if ((posX >= 247) && (posX <= 258))
1553 				championIndex = kDMChampionSecond;
1554 			else if (posX >= 308)
1555 				championIndex = kDMChampionFourth;
1556 
1557 			break;
1558 		case 3:
1559 			if ((posX >= 247) && (posX <= 258))
1560 				championIndex = kDMChampionSecond;
1561 			else if ((posX >= 261) && (posX <= 272))
1562 				championIndex = kDMChampionThird;
1563 			else if (posX <= 244)
1564 				championIndex = kDMChampionFirst;
1565 			break;
1566 		default:
1567 			break;
1568 		}
1569 
1570 		if ((championIndex != kDMChampionNone) && (championIndex < _vm->_championMan->_partyChampionCount))
1571 			_vm->_menuMan->setMagicCasterAndDrawSpellArea(championIndex);
1572 
1573 		return;
1574 	}
1575 
1576 	CommandType newCommand = getCommandTypeFromMouseInput(_mouseInputSpellArea, Common::Point(posX, posY), kDMMouseButtonLeft);
1577 	if (newCommand != kDMCommandNone)
1578 		commandProcessTypes101To108_clickInSpellSymbolsArea(newCommand);
1579 }
1580 
commandProcessTypes101To108_clickInSpellSymbolsArea(CommandType cmdType)1581 void EventManager::commandProcessTypes101To108_clickInSpellSymbolsArea(CommandType cmdType) {
1582 	static Box spellSymbolsAndDelete[7] = {
1583 		/* { X1, X2, Y1, Y2 } */
1584 		Box(235, 247, 51, 61),   /* Symbol 1 */
1585 		Box(249, 261, 51, 61),   /* Symbol 2 */
1586 		Box(263, 275, 51, 61),   /* Symbol 3 */
1587 		Box(277, 289, 51, 61),   /* Symbol 4 */
1588 		Box(291, 303, 51, 61),   /* Symbol 5 */
1589 		Box(305, 317, 51, 61),   /* Symbol 6 */
1590 		Box(305, 318, 63, 73)    /* Delete */
1591 	};
1592 
1593 	if (cmdType == kDMCommandClickInSpeallAreaCastSpell) {
1594 		if (_vm->_championMan->_champions[_vm->_championMan->_magicCasterChampionIndex]._symbols[0] == '\0')
1595 			return;
1596 
1597 		commandHighlightBoxEnable(234, 303, 63, 73);
1598 		_vm->_stopWaitingForPlayerInput = _vm->_menuMan->getClickOnSpellCastResult();
1599 		return;
1600 	}
1601 
1602 	uint16 symbolIndex = cmdType - kDMCommandClickInSpellAreaSymbol1;
1603 	Box *highlightBox = &spellSymbolsAndDelete[symbolIndex];
1604 	commandHighlightBoxEnable(highlightBox->_rect.left, highlightBox->_rect.right, highlightBox->_rect.top, highlightBox->_rect.bottom);
1605 	_vm->delay(1);
1606 	highlightBoxDisable();
1607 
1608 	if (symbolIndex < 6)
1609 		_vm->_menuMan->addChampionSymbol(symbolIndex);
1610 	else
1611 		_vm->_menuMan->deleteChampionSymbol();
1612 }
1613 
commandProcessType111To115_ClickInActionArea(int16 posX,int16 posY)1614 void EventManager::commandProcessType111To115_ClickInActionArea(int16 posX, int16 posY) {
1615 	if (_vm->_championMan->_actingChampionOrdinal) {
1616 		uint16 mouseCommand = getCommandTypeFromMouseInput(_mouseInputActionAreaNames, Common::Point(posX, posY), kDMMouseButtonLeft);
1617 		if (mouseCommand != kDMCommandNone) {
1618 			if (mouseCommand == kDMCommandClickInActionAreaPass) {
1619 				commandHighlightBoxEnable(285, 319, 77, 83);
1620 				_vm->_menuMan->didClickTriggerAction(-1);
1621 			} else if ((mouseCommand - kDMCommandClickInActionAreaPass) <= _vm->_menuMan->_actionCount) {
1622 				if (mouseCommand == kDMCommandClickInActionAreaAction0)
1623 					commandHighlightBoxEnable(234, 318, 86, 96);
1624 				else if (mouseCommand == kDMCommandClickInActionAreaAction1)
1625 					commandHighlightBoxEnable(234, 318, 98, 108);
1626 				else
1627 					commandHighlightBoxEnable(234, 318, 110, 120);
1628 
1629 				_vm->_stopWaitingForPlayerInput = _vm->_menuMan->didClickTriggerAction(mouseCommand - kDMCommandClickInActionAreaAction0);
1630 			}
1631 		}
1632 	} else if (_vm->_menuMan->_actionAreaContainsIcons) {
1633 		uint16 mouseCommand = getCommandTypeFromMouseInput(_mouseInputActionAreaIcons, Common::Point(posX, posY), kDMMouseButtonLeft);
1634 		if (mouseCommand != kDMCommandNone) {
1635 			mouseCommand -= kDMCommandClickInActionAreaChampion0Action;
1636 			if (mouseCommand < _vm->_championMan->_partyChampionCount)
1637 				_vm->_menuMan->processCommands116To119_setActingChampion(mouseCommand);
1638 		}
1639 	}
1640 }
1641 
resetPressingEyeOrMouth()1642 void EventManager::resetPressingEyeOrMouth() {
1643 	if (_vm->_pressingEye) {
1644 		_ignoreMouseMovements = false;
1645 		_vm->_stopPressingEye = true;
1646 	}
1647 	if (_vm->_pressingMouth) {
1648 		_ignoreMouseMovements = false;
1649 		_vm->_stopPressingMouth = true;
1650 	}
1651 }
1652 
waitForMouseOrKeyActivity()1653 void EventManager::waitForMouseOrKeyActivity() {
1654 	discardAllInput();
1655 	Common::Event event;
1656 	DisplayMan &displMan = *_vm->_displayMan;
1657 	while (true) {
1658 		if (g_system->getEventManager()->pollEvent(event)) {
1659 			switch (event.type) {
1660 			case Common::EVENT_QUIT:
1661 				_vm->_engineShouldQuit = true;
1662 			case Common::EVENT_KEYDOWN: // Intentional fall through
1663 			case Common::EVENT_LBUTTONDOWN:
1664 			case Common::EVENT_RBUTTONDOWN:
1665 				return;
1666 			default:
1667 				break;
1668 			}
1669 		}
1670 		_vm->delay(1);
1671 		displMan.updateScreen();
1672 	}
1673 }
1674 
commandHighlightBoxEnable(int16 x1,int16 x2,int16 y1,int16 y2)1675 void EventManager::commandHighlightBoxEnable(int16 x1, int16 x2, int16 y1, int16 y2) {
1676 	_highlightScreenBox = Box(x1, x2, y1, y2);
1677 	highlightScreenBox(x1, x2, y1, y2);
1678 	_highlightBoxEnabled = true;
1679 }
1680 
highlightBoxDisable()1681 void EventManager::highlightBoxDisable() {
1682 	if (_highlightBoxEnabled == true) {
1683 		highlightScreenBox(_highlightScreenBox._rect.left, _highlightScreenBox._rect.right, _highlightScreenBox._rect.top, _highlightScreenBox._rect.bottom);
1684 		_highlightBoxEnabled = false;
1685 	}
1686 }
1687 
1688 } // end of namespace DM
1689