1 /*
2  *  Copyright (C) 2001-2013 The Exult Team
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18 
19 #ifdef HAVE_CONFIG_H
20 #  include <config.h>
21 #endif
22 
23 #include "keyactions.h"
24 #include "keys.h"
25 #include "gump_utils.h"
26 #include "gamewin.h"
27 #include "gamemap.h"
28 #include "mouse.h"
29 #include "actors.h"
30 #include "game.h"
31 #include "exult.h"
32 #include "common_types.h"
33 #include "exult_constants.h"
34 #include "File_gump.h"
35 #include "Scroll_gump.h"
36 #include "cheat.h"
37 #include "combat_opts.h"
38 #include "ucmachine.h"
39 #include "party.h"
40 #include "Audio.h"
41 #include "Gamemenu_gump.h"
42 #include "Newfile_gump.h"
43 #include "Face_stats.h"
44 #include "Notebook_gump.h"
45 #include "Gump_manager.h"
46 #include "effects.h"
47 #include "palette.h"
48 #include "Yesno_gump.h"
49 #include "ShortcutBar_gump.h"
50 #include "ignore_unused_variable_warning.h"
51 
52 /*
53  *  Get the i'th party member, with the 0'th being the Avatar.
54  */
55 
Get_party_member(int num)56 static Actor *Get_party_member(
57     int num             // 0=avatar.
58 ) {
59 	int npc_num = 0;        // Default to Avatar
60 	if (num > 0)
61 		npc_num = Game_window::get_instance()->get_party_man()->get_member(num - 1);
62 	return Game_window::get_instance()->get_npc(npc_num);
63 }
64 
65 
66 //  { ActionQuit, 0, "Quit", normal_keys, NONE },
ActionQuit(int const * params)67 void ActionQuit(int const *params) {
68 	ignore_unused_variable_warning(params);
69 	Game_window::get_instance()->get_gump_man()->okay_to_quit();
70 }
71 
72 // { ActionOldFileGump, 0, "Save/restore", normal_keys, NONE },
ActionOldFileGump(int const * params)73 void ActionOldFileGump(int const *params) {
74 	ignore_unused_variable_warning(params);
75 	auto *fileio = new File_gump();
76 	Game_window::get_instance()->get_gump_man()->do_modal_gump(fileio,
77 	        Mouse::hand);
78 	delete fileio;
79 }
80 
81 // { ActionMenuGump, 0, "GameMenu", normal_keys, NONE },
ActionMenuGump(int const * params)82 void ActionMenuGump(int const *params) {
83 	ignore_unused_variable_warning(params);
84 	auto *gmenu = new Gamemenu_gump();
85 	Game_window::get_instance()->get_gump_man()->do_modal_gump(gmenu,
86 	        Mouse::hand);
87 	delete gmenu;
88 }
89 
90 // { ActionFileGump, 0, "Save/restore", normal_keys, NONE },
ActionFileGump(int const * params)91 void ActionFileGump(int const *params) {
92 	ignore_unused_variable_warning(params);
93 	auto *fileio = new Newfile_gump();
94 	Game_window::get_instance()->get_gump_man()->do_modal_gump(fileio,
95 	        Mouse::hand);
96 	delete fileio;
97 }
98 //  { ActionQuicksave, 0, "Quick-save", normal_keys, NONE },
ActionQuicksave(int const * params)99 void ActionQuicksave(int const *params) {
100 	ignore_unused_variable_warning(params);
101 	Game_window *gwin = Game_window::get_instance();
102 	try {
103 		gwin->write();
104 	} catch (exult_exception &/*e*/) {
105 		gwin->get_effects()->center_text("Saving game failed!");
106 		return;
107 	}
108 	gwin->get_effects()->center_text("Game saved");
109 	gwin->got_bad_feeling(8);
110 }
111 
112 //  { ActionQuickrestore, 0, "Quick-restore", normal_keys, NONE },
ActionQuickrestore(int const * params)113 void ActionQuickrestore(int const *params) {
114 	ignore_unused_variable_warning(params);
115 	Game_window *gwin = Game_window::get_instance();
116 	try {
117 		gwin->read();
118 	} catch (exult_exception &/*e*/) {
119 		gwin->get_effects()->center_text("Restoring game failed!");
120 		return;
121 	}
122 	gwin->get_effects()->center_text("Game restored");
123 	gwin->paint();
124 }
125 
126 //  { ActionAbout, 0, "About Exult", normal_keys, NONE },
ActionAbout(int const * params)127 void ActionAbout(int const *params) {
128 	ignore_unused_variable_warning(params);
129 	Game_window *gwin = Game_window::get_instance();
130 	Scroll_gump *scroll;
131 	scroll = new Scroll_gump();
132 
133 	scroll->add_text("Exult V" VERSION "\n");
134 	scroll->add_text("(C) 1998-2020 Exult Team\n\n");
135 	scroll->add_text("Available under the terms of the ");
136 	scroll->add_text("GNU General Public License\n\n");
137 	scroll->add_text("http://exult.sourceforge.net\n");
138 
139 	scroll->paint();
140 	do {
141 		int x;
142 		int y;
143 		Get_click(x, y, Mouse::hand);
144 	} while (scroll->show_next_page());
145 	gwin->paint();
146 	delete scroll;
147 }
148 
149 //  { ActionHelp, 0, "List keys", normal_keys, NONE },
ActionHelp(int const * params)150 void ActionHelp(int const *params) {
151 	ignore_unused_variable_warning(params);
152 	keybinder->ShowHelp();
153 }
154 
155 //  { ActionCloseGumps, 0, "Close gumps", dont_show, NONE },
ActionCloseGumps(int const * params)156 void ActionCloseGumps(int const *params) {
157 	ignore_unused_variable_warning(params);
158 	Game_window::get_instance()->get_gump_man()->close_all_gumps();
159 }
160 
161 //  { ActionCloseOrMenu, "Game menu", normal_keys, NONE },
ActionCloseOrMenu(int const * params)162 void ActionCloseOrMenu(int const *params) {
163 	ignore_unused_variable_warning(params);
164 	Game_window *gwin = Game_window::get_instance();
165 	if (gwin->get_gump_man()->showing_gumps(true))
166 		gwin->get_gump_man()->close_all_gumps();
167 	else
168 		ActionMenuGump(nullptr);
169 }
170 
171 //  { ActionScreenshot, 0, "Take screenshot", normal_keys, NONE },
ActionScreenshot(int const * params)172 void ActionScreenshot(int const *params) {
173 	ignore_unused_variable_warning(params);
174 	make_screenshot();
175 }
176 
177 //  { ActionRepaint, 0, "Repaint screen", dont_show, NONE },
ActionRepaint(int const * params)178 void ActionRepaint(int const *params) {
179 	ignore_unused_variable_warning(params);
180 	Game_window::get_instance()->paint();
181 }
182 
183 //  { ActionScalevalIncrease, 0, "Increase scaleval", cheat_keys, NONE },
ActionScalevalIncrease(int const * params)184 void ActionScalevalIncrease(int const *params) {
185 	ignore_unused_variable_warning(params);
186 	increase_scaleval();
187 }
188 
189 //  { ActionScalevalDecrease, 0, "Decrease scaleval", cheat_keys, NONE },
ActionScalevalDecrease(int const * params)190 void ActionScalevalDecrease(int const *params) {
191 	ignore_unused_variable_warning(params);
192 	decrease_scaleval();
193 }
194 
195 //  { ActionBrighter, 0, "Increase brightness", normal_keys, NONE },
ActionBrighter(int const * params)196 void ActionBrighter(int const *params) {
197 	ignore_unused_variable_warning(params);
198 	change_gamma(true);
199 }
200 
201 //  { ActionDarker, 0, "Decrease brightness", normal_keys, NONE },
ActionDarker(int const * params)202 void ActionDarker(int const *params) {
203 	ignore_unused_variable_warning(params);
204 	change_gamma(false);
205 }
206 
207 //  { ActionFullscreen, 0, "Toggle fullscreen", normal_keys, NONE },
ActionFullscreen(int const * params)208 void ActionFullscreen(int const *params) {
209 	ignore_unused_variable_warning(params);
210 	Game_window *gwin = Game_window::get_instance();
211 	setup_video(!gwin->get_win()->is_fullscreen(), TOGGLE_FULLSCREEN);
212 	const char *msg;
213 	if (gwin->get_win()->is_fullscreen())
214 		msg = "Fullscreen applied.\nKeep?";
215 	else
216 		msg = "Windowed mode.\nKeep?";
217 	if (Countdown_gump::ask(msg, 20))
218 		config->set("config/video/fullscreen",
219 		            gwin->get_win()->is_fullscreen() ? "yes" : "no",
220 		            true);
221 	else
222 		setup_video(!gwin->get_win()->is_fullscreen(), TOGGLE_FULLSCREEN);
223 }
224 
225 //  { ActionUseItem, 3, "Use item", dont_show, NONE },
226 // params[0] = shape nr.
227 // params[1] = frame nr.
228 // params[2] = quality
ActionUseItem(int const * params)229 void ActionUseItem(int const *params) {
230 	int framenum = params[1] == -1 ? c_any_framenum : params[1];
231 	int qual     = params[2] == -1 ? c_any_qual     : params[2];
232 	Game_window::get_instance()->activate_item(params[0], framenum, qual);
233 
234 	Mouse::mouse->set_speed_cursor();
235 }
236 
237 //  { ActionUseItem, 3, "Use food", dont_show, NONE },
ActionUseFood(int const * params)238 void ActionUseFood(int const *params) {
239 	ignore_unused_variable_warning(params);
240 	Game_window *gwin = Game_window::get_instance();
241 	if (gwin->activate_item(377) || // Food
242 	        (GAME_SI && gwin->activate_item(404)) ||  // Special SI food
243 	         gwin->activate_item(616))  // Drinks
244 		Mouse::mouse->set_speed_cursor();
245 }
246 
247 //  { ActionCallUsecode, 2, "Call usecode", dont_show, NONE },
248 // params[0] = usecode function.
249 // params[1] = event id.
ActionCallUsecode(int const * params)250 void ActionCallUsecode(int const *params) {
251 	Usecode_machine *usecode = Game_window::get_instance()->get_usecode();
252 	usecode->call_usecode(params[0], nullptr,
253 	                      static_cast<Usecode_machine::Usecode_events>(params[1]));
254 
255 	Mouse::mouse->set_speed_cursor();
256 }
257 
258 //  { ActionCombat, 0, "Toggle combat", normal_keys, NONE },
ActionCombat(int const * params)259 void ActionCombat(int const *params) {
260 	ignore_unused_variable_warning(params);
261 	Game_window *gwin = Game_window::get_instance();
262 	gwin->toggle_combat();
263 	gwin->paint();
264 	Mouse::mouse->set_speed_cursor();
265 }
266 
267 //  { ActionCombatPause, 0, "Pause combat", normal_keys, NONE },
ActionCombatPause(int const * params)268 void ActionCombatPause(int const *params) {
269 	ignore_unused_variable_warning(params);
270 	Combat::toggle_pause();
271 	Mouse::mouse->set_speed_cursor();
272 }
273 
274 //  { ActionTarget, 0, "Target mode", normal_keys, NONE },
ActionTarget(int const * params)275 void ActionTarget(int const *params) {
276 	ignore_unused_variable_warning(params);
277 	int x;
278 	int y;
279 	if (!Get_click(x, y, Mouse::greenselect))
280 		return;
281 	Game_window::get_instance()->double_clicked(x, y);
282 	Mouse::mouse->set_speed_cursor();
283 }
284 
285 //  { ActionInventory, 1, "Show inventory", normal_keys, NONE },
286 // params[0] = party member (0-7), or -1 for 'next'
ActionInventory(int const * params)287 void ActionInventory(int const *params) {
288 	Game_window *gwin = Game_window::get_instance();
289 	static int inventory_page = -1;
290 	Actor *actor;
291 
292 	if (params[0] == -1) {
293 		Gump_manager *gump_man = gwin->get_gump_man();
294 		int party_count = gwin->get_party_man()->get_count();
295 		int shapenum;
296 
297 		for (int i = 0; i <= party_count; ++i) {
298 			actor = Get_party_member(i);
299 			if (!actor)
300 				continue;
301 
302 			shapenum = actor->inventory_shapenum();
303 			// Check if this actor's inventory page is open or not
304 			if (!gump_man->find_gump(actor, shapenum) && actor->can_act_charmed()) {
305 				gump_man->add_gump(actor, shapenum, true); //force showing inv.
306 				inventory_page = i;
307 				return;
308 			}
309 		}
310 		inventory_page = (inventory_page + 1) % (party_count + 1);
311 	} else {
312 		inventory_page = params[0];
313 		if (inventory_page < 0 ||
314 		        inventory_page > gwin->get_party_man()->get_count())
315 			return;
316 	}
317 
318 	actor = Get_party_member(inventory_page);
319 	if (actor && actor->can_act_charmed()) {
320 		actor->show_inventory(); //force showing inv.
321 	}
322 
323 	Mouse::mouse->set_speed_cursor();
324 }
325 
326 //  { ActionTryKeys, 0, "Try keys", normal_keys, NONE },
ActionTryKeys(int const * params)327 void ActionTryKeys(int const *params) {
328 	ignore_unused_variable_warning(params);
329 	Game_window *gwin = Game_window::get_instance();
330 	int x;
331 	int y;           // Allow dragging.
332 	if (!Get_click(x, y, Mouse::greenselect, nullptr, true))
333 		return;
334 	// Look for obj. in open gump.
335 	Gump *gump = gwin->get_gump_man()->find_gump(x, y);
336 	Game_object *obj;
337 	if (gump)
338 		obj = gump->find_object(x, y);
339 	else                // Search rest of world.
340 		obj = gwin->find_object(x, y);
341 	if (!obj)
342 		return;
343 	int qual = obj->get_quality();  // Key quality should match.
344 	Actor *party[10];       // Get ->party members.
345 	int party_cnt = gwin->get_party(&party[0], 1);
346 	for (int i = 0; i < party_cnt; i++) {
347 		Actor *act = party[i];
348 		Game_object_vector keys;        // Get keys.
349 		if (act->get_objects(keys, 641, qual, c_any_framenum)) {
350 			for (size_t i = 0; i < keys.size(); i++)
351 				if (!keys[i]->inside_locked()) {
352 					// intercept the click_on_item call made by the key-usecode
353 					Usecode_machine *ucmachine = gwin->get_usecode();
354 					Game_object *oldtarg;
355 					Tile_coord *oldtile;
356 					ucmachine->save_intercept(oldtarg, oldtile);
357 					ucmachine->intercept_click_on_item(obj);
358 					keys[0]->activate();
359 					ucmachine->restore_intercept(oldtarg, oldtile);
360 					return;
361 				}
362 		}
363 	}
364 	Mouse::mouse->flash_shape(Mouse::redx); // Nothing matched.
365 }
366 
367 //  { ActionStats, 1, "Show stats", normal_keys, NONE },
368 // params[0] = party member (0-7), or -1 for 'next'
ActionStats(int const * params)369 void ActionStats(int const *params) {
370 	Game_window *gwin = Game_window::get_instance();
371 	static int stats_page = -1;
372 	Actor *actor;
373 
374 	if (params[0] == -1) {
375 		Gump_manager *gump_man = gwin->get_gump_man();
376 		int party_count = gwin->get_party_man()->get_count();
377 		int shapenum = game->get_shape("gumps/statsdisplay");
378 
379 		for (int i = 0; i <= party_count; ++i) {
380 			actor = Get_party_member(i);
381 			if (!actor)
382 				continue;
383 
384 			// Check if this actor's stats page is open or not
385 			if (!gump_man->find_gump(actor, shapenum)) {
386 				gump_man->add_gump(actor, shapenum); //force showing stats.
387 				stats_page = i;
388 				return;
389 			}
390 		}
391 		stats_page = (stats_page + 1) % (party_count + 1);
392 	} else {
393 		stats_page = params[0];
394 		if (stats_page < 0 ||
395 		        stats_page >= gwin->get_party_man()->get_count())
396 			stats_page = 0;
397 	}
398 
399 	actor = Get_party_member(stats_page);
400 	if (actor) gwin->get_gump_man()->add_gump(actor, game->get_shape("gumps/statsdisplay"));
401 
402 	Mouse::mouse->set_speed_cursor();
403 }
404 
405 //  { ActionCombatStats, 0, "Show Combat stats", normal_keys, SERPENT_ISLE }
ActionCombatStats(int const * params)406 void ActionCombatStats(int const *params) {
407 	ignore_unused_variable_warning(params);
408 	Game_window *gwin = Game_window::get_instance();
409 	int cnt = gwin->get_party_man()->get_count();
410 	gwin->get_gump_man()->add_gump(nullptr, game->get_shape("gumps/cstats/1") + cnt);
411 }
412 
413 //  { ActionFaceStats, 0, "Change Face Stats State", normal_keys, NONE }
ActionFaceStats(int const * params)414 void ActionFaceStats(int const *params) {
415 	ignore_unused_variable_warning(params);
416 	Face_stats::AdvanceState();
417 	Face_stats::save_config(config);
418 }
419 
ActionUseHealingItems(int const * params)420 void ActionUseHealingItems(int const *params) {
421 	ignore_unused_variable_warning(params);
422 	Game_window *gwin = Game_window::get_instance();
423 	if (gwin->activate_item(827)) // bandage
424 		return;
425 
426 	// Potions are wasted if at full health so we will check for that
427 	int x;
428 	int y;
429 	if (!is_party_item(340, 1) || !Get_click(x, y, Mouse::greenselect))
430 		return;
431 	Game_object *obj = gwin->find_object(x, y);
432 	if(obj) {
433 		Actor *target = obj->as_actor();
434 		if(target && target->get_property(Actor::health) < target->get_property(Actor::strength)) {
435 			Game_object *oldtarg;
436 			Tile_coord *oldtile;
437 			Usecode_machine *ucmachine = gwin->get_usecode();
438 
439 			ucmachine->save_intercept(oldtarg, oldtile);
440 			ucmachine->intercept_click_on_item(obj);
441 			gwin->activate_item(340, 1); // healing potion
442 			ucmachine->restore_intercept(oldtarg, oldtile);
443 			return;
444 		}
445 	}
446 }
447 
448 //  { ActionSIIntro, 0,  "Show SI intro", cheat_keys, SERPENT_ISLE },
ActionSIIntro(int const * params)449 void ActionSIIntro(int const *params) {
450 	ignore_unused_variable_warning(params);
451 	Game_window *gwin = Game_window::get_instance();
452 	game->set_jive();
453 	game->play_intro();
454 	game->clear_jive();
455 	gwin->clear_screen(true);
456 	gwin->get_pal()->set(0);
457 	gwin->paint();
458 	gwin->get_pal()->fade(50, 1, 0);
459 }
460 
461 //  { ActionEndgame, 1, "Show endgame", cheat_keys, BLACK_GATE },
462 // params[0] = -1,0 = won, 1 = lost
ActionEndgame(int const * params)463 void ActionEndgame(int const *params) {
464 	Game_window *gwin = Game_window::get_instance();
465 	game->end_game(params[0] != 1);
466 	gwin->clear_screen(true);
467 	gwin->get_pal()->set(0);
468 	gwin->paint();
469 	gwin->get_pal()->fade(50, 1, 0);
470 }
471 
472 //  { ActionScrollLeft, 0, "Scroll left", cheat_keys, NONE },
ActionScrollLeft(int const * params)473 void ActionScrollLeft(int const *params) {
474 	ignore_unused_variable_warning(params);
475 	Game_window *gwin = Game_window::get_instance();
476 	for (int i = 16; i; i--)
477 		gwin->view_left();
478 }
479 
480 //  { ActionScrollRight, 0, "Scroll right", cheat_keys, NONE },
ActionScrollRight(int const * params)481 void ActionScrollRight(int const *params) {
482 	ignore_unused_variable_warning(params);
483 	Game_window *gwin = Game_window::get_instance();
484 	for (int i = 16; i; i--)
485 		gwin->view_right();
486 }
487 
488 //  { ActionScrollUp, 0, "Scroll up", cheat_keys, NONE },
ActionScrollUp(int const * params)489 void ActionScrollUp(int const *params) {
490 	ignore_unused_variable_warning(params);
491 	Game_window *gwin = Game_window::get_instance();
492 	for (int i = 16; i; i--)
493 		gwin->view_up();
494 }
495 
496 //  { ActionScrollDown, 0, "Scroll down", cheat_keys, NONE },
ActionScrollDown(int const * params)497 void ActionScrollDown(int const *params) {
498 	ignore_unused_variable_warning(params);
499 	Game_window *gwin = Game_window::get_instance();
500 	for (int i = 16; i; i--)
501 		gwin->view_down();
502 }
503 
get_walking_speed(int const * params)504 int get_walking_speed(int const *params) {
505 	Game_window *gwin = Game_window::get_instance();
506 	int parm = params ? params[0] : 0;
507 	int speed;
508 	if (parm == 2)
509 		speed = Mouse::slow_speed_factor;
510 	else if (gwin->in_combat() || gwin->is_hostile_nearby())
511 		speed = Mouse::medium_combat_speed_factor;
512 	else
513 		speed = parm == 1 ? Mouse::medium_speed_factor : Mouse::fast_speed_factor;
514 	return 200 * gwin->get_std_delay() / speed;
515 }
516 
517 //  { ActionWalkWest, 0, "Walk west", normal_keys, NONE },
ActionWalkWest(int const * params)518 void ActionWalkWest(int const *params) {
519 	Game_window *gwin = Game_window::get_instance();
520 	int speed = get_walking_speed(params);
521 	gwin->start_actor(gwin->get_width() / 2 - 50, gwin->get_height() / 2, speed);
522 }
523 
524 //  { ActionWalkEast, 0, "Walk east", normal_keys, NONE },
ActionWalkEast(int const * params)525 void ActionWalkEast(int const *params) {
526 	Game_window *gwin = Game_window::get_instance();
527 	int speed = get_walking_speed(params);
528 	gwin->start_actor(gwin->get_width() / 2 + 50, gwin->get_height() / 2, speed);
529 }
530 
531 //  { ActionWalkNorth, 0, "Walk north", normal_keys, NONE },
ActionWalkNorth(int const * params)532 void ActionWalkNorth(int const *params) {
533 	Game_window *gwin = Game_window::get_instance();
534 	int speed = get_walking_speed(params);
535 	gwin->start_actor(gwin->get_width() / 2, gwin->get_height() / 2 - 50, speed);
536 }
537 
538 //  { ActionWalkSouth, 0, "Walk south", normal_keys, NONE },
ActionWalkSouth(int const * params)539 void ActionWalkSouth(int const *params) {
540 	Game_window *gwin = Game_window::get_instance();
541 	int speed = get_walking_speed(params);
542 	gwin->start_actor(gwin->get_width() / 2, gwin->get_height() / 2 + 50, speed);
543 }
544 
545 //  { ActionWalkNorthEast, 0, "Walk north-east", normal_keys, NONE },
ActionWalkNorthEast(int const * params)546 void ActionWalkNorthEast(int const *params) {
547 	Game_window *gwin = Game_window::get_instance();
548 	int speed = get_walking_speed(params);
549 	gwin->start_actor(gwin->get_width() / 2 + 50, gwin->get_height() / 2 - 50, speed);
550 }
551 
552 //  { ActionWalkSouthEast, 0, "Walk south-east", normal_keys, NONE },
ActionWalkSouthEast(int const * params)553 void ActionWalkSouthEast(int const *params) {
554 	Game_window *gwin = Game_window::get_instance();
555 	int speed = get_walking_speed(params);
556 	gwin->start_actor(gwin->get_width() / 2 + 50, gwin->get_height() / 2 + 50, speed);
557 }
558 
559 //  { ActionWalkNorthWest, 0, "Walk north-west", normal_keys, NONE },
ActionWalkNorthWest(int const * params)560 void ActionWalkNorthWest(int const *params) {
561 	Game_window *gwin = Game_window::get_instance();
562 	int speed = get_walking_speed(params);
563 	gwin->start_actor(gwin->get_width() / 2 - 50, gwin->get_height() / 2 - 50, speed);
564 }
565 
566 //  { ActionWalkSouthWest, 0, "Walk south-west", normal_keys, NONE },
ActionWalkSouthWest(int const * params)567 void ActionWalkSouthWest(int const *params) {
568 	Game_window *gwin = Game_window::get_instance();
569 	int speed = get_walking_speed(params);
570 	gwin->start_actor(gwin->get_width() / 2 - 50, gwin->get_height() / 2 + 50, speed);
571 }
572 
573 //  { ActionStopWalking, 0, "Stop Walking", cheat_keys, NONE },
ActionStopWalking(int const * params)574 void ActionStopWalking(int const *params) {
575 	ignore_unused_variable_warning(params);
576 	Game_window *gwin = Game_window::get_instance();
577 	gwin->stop_actor();
578 }
579 
580 //  { ActionCenter, 0, "Center screen", cheat_keys, NONE },
ActionCenter(int const * params)581 void ActionCenter(int const *params) {
582 	ignore_unused_variable_warning(params);
583 	Game_window *gwin = Game_window::get_instance();
584 	gwin->center_view(gwin->get_camera_actor()->get_tile());
585 	gwin->paint();
586 }
587 
588 //  { ActionShapeBrowser, 0, "Shape browser", cheat_keys, NONE },
ActionShapeBrowser(int const * params)589 void ActionShapeBrowser(int const *params) {
590 	ignore_unused_variable_warning(params);
591 	cheat.shape_browser();
592 }
593 
ActionShapeBrowserHelp(int const * params)594 void ActionShapeBrowserHelp(int const *params) {
595 	ignore_unused_variable_warning(params);
596 	keybinder->ShowBrowserKeys();
597 }
598 
599 //  { ActionCreateShape, 3, "Create last shape", cheat_keys, NONE },
600 // params[0] = shape nr., or -1 for 'last selected shape in browser'
601 // params[1] = frame nr.
602 // params[2] = quantity
603 // params[3] = quality
ActionCreateShape(int const * params)604 void ActionCreateShape(int const *params) {
605 	if (params[0] == -1) {
606 		cheat.create_last_shape();
607 	} else {
608 		Game_window *gwin = Game_window::get_instance();
609 		int delta    = params[2] == -1 ? 1 : params[2];
610 		int shapenum = params[0];
611 		int qual     = params[2] == -1 ? c_any_qual : params[2];
612 		int framenum = params[1] == -1 ? 0 : params[1];
613 		gwin->get_main_actor()->add_quantity(delta, shapenum, qual, framenum);
614 		gwin->get_effects()->center_text("Object created");
615 	}
616 }
617 
618 //  { ActionDeleteObject, 0, "Delete object", cheat_keys, NONE },
ActionDeleteObject(int const * params)619 void ActionDeleteObject(int const *params) {
620 	ignore_unused_variable_warning(params);
621 	cheat.delete_object();
622 }
623 
624 //  { ActionDeleteSelected, "Delete selected", true, ture, NONE, false },
ActionDeleteSelected(int const * params)625 void ActionDeleteSelected(int const *params) {
626 	ignore_unused_variable_warning(params);
627 	cheat.delete_selected();
628 }
629 
630 //  { ActionMoveSelected, 3, "Move selected", cheat_keys, NONE },
631 // params[0] = deltax (tiles)
632 // params[1] = deltay
633 // params[2] = deltaz
ActionMoveSelected(int const * params)634 void ActionMoveSelected(int const *params) {
635 	cheat.move_selected(params[0], params[1], params[2]);
636 }
637 
638 //  { ActionToggleEggs, 0, "Toggle egg display", cheat_keys, NONE },
ActionToggleEggs(int const * params)639 void ActionToggleEggs(int const *params) {
640 	ignore_unused_variable_warning(params);
641 	cheat.toggle_eggs();
642 }
643 
644 //  { ActionGodMode, 1, "Toggle god mode", cheat_keys, NONE },
645 // params[0] = -1 for toggle, 0 for off, 1 for on
ActionGodMode(int const * params)646 void ActionGodMode(int const *params) {
647 	if (params[0] == -1)
648 		cheat.toggle_god();
649 	else
650 		cheat.set_god(params[0] != 0);
651 }
652 
653 //  { ActionGender, 0, "Change gender", cheat_keys, NONE },
ActionGender(int const * params)654 void ActionGender(int const *params) {
655 	ignore_unused_variable_warning(params);
656 	cheat.change_gender();
657 }
658 
659 //  { ActionCheatHelp, 0, "List cheat keys", cheat_keys, NONE },
ActionCheatHelp(int const * params)660 void ActionCheatHelp(int const *params) {
661 	ignore_unused_variable_warning(params);
662 	keybinder->ShowCheatHelp();
663 }
664 
665 //  { ActionMapeditHelp, 0, "List mapedit keys", mapedit_keys, NONE },
ActionMapeditHelp(int const * params)666 void ActionMapeditHelp(int const *params) {
667 	ignore_unused_variable_warning(params);
668 	keybinder->ShowMapeditHelp();
669 }
670 
671 //  { ActionInfravision, 1, "Toggle infravision", cheat_keys, NONE },
672 // params[0] = -1 for toggle, 0 for off, 1 for on
ActionInfravision(int const * params)673 void ActionInfravision(int const *params) {
674 	if (params[0] == -1)
675 		cheat.toggle_infravision();
676 	else
677 		cheat.set_infravision(params[0] != 0);
678 }
679 
680 //  { ActionSkipLift, 1, "Change skiplift", cheat_keys, NONE },
681 // params[0] = level, or -1 to decrease one
ActionSkipLift(int const * params)682 void ActionSkipLift(int const *params) {
683 	if (params[0] == -1)
684 		cheat.dec_skip_lift();
685 	else
686 		cheat.set_skip_lift(params[0]);
687 }
688 
689 //  { ActionLevelup, 1, "Level-up party", cheat_keys, NONE },
690 // params[0] = nr. of levels (or -1 for one)
ActionLevelup(int const * params)691 void ActionLevelup(int const *params) {
692 	int cnt = params[0] == -1 ? 1 : params[0];
693 	for (int i = 0; i < cnt; i++)
694 		cheat.levelup_party();
695 }
696 
697 //  { ActionMapEditor, 1, "Toggle map-editor mode", cheat_keys, NONE },
698 // params[0] = -1 for toggle, 0 for off, 1 for on
ActionMapEditor(int const * params)699 void ActionMapEditor(int const *params) {
700 	if (params[0] == -1)
701 		cheat.toggle_map_editor();
702 	else
703 		cheat.set_map_editor(params[0] != 0);
704 }
705 
706 // { ActionHackMover, "Toggle hack-mover mode", cheat_keys, NONE },
707 // params[0] = -1 for toggle, 0 for off, 1 for on
ActionHackMover(int const * params)708 void ActionHackMover(int const *params) {
709 	if (params[0] == -1)
710 		cheat.toggle_hack_mover();
711 	else
712 		cheat.set_hack_mover(params[0] != 0);
713 }
714 
715 //  { ActionMapTeleport, 0, "Map teleport", cheat_keys, NONE },
ActionMapTeleport(int const * params)716 void ActionMapTeleport(int const *params) {
717 	ignore_unused_variable_warning(params);
718 	cheat.map_teleport();
719 }
720 
721 //  { ActionWriteMiniMap, 0, "Write minimap", cheat_keys, NONE },
ActionWriteMiniMap(int const * params)722 void ActionWriteMiniMap(int const *params) {
723 	ignore_unused_variable_warning(params);
724 	Game_map::write_minimap();
725 }
726 
727 //  { ActionTeleport, 0, "Teleport to cursor", cheat_keys, NONE },
ActionTeleport(int const * params)728 void ActionTeleport(int const *params) {
729 	ignore_unused_variable_warning(params);
730 	cheat.cursor_teleport();
731 }
732 
ActionTeleportTargetMode(int const * params)733 void ActionTeleportTargetMode(int const *params) {
734 	ignore_unused_variable_warning(params);
735 	int x;
736 	int y;
737 	if (!Get_click(x, y, Mouse::redx))
738 		return;
739 	cheat.cursor_teleport();
740 }
741 
742 //  { ActionNextMapTeleport, 0, "Teleport to next map", cheat_keys, NONE },
ActionNextMapTeleport(int const * params)743 void ActionNextMapTeleport(int const *params) {
744 	ignore_unused_variable_warning(params);
745 	cheat.next_map_teleport();
746 }
747 
748 //  { ActionTime, 0, "Next time period", cheat_keys, NONE },
ActionTime(int const * params)749 void ActionTime(int const *params) {
750 	ignore_unused_variable_warning(params);
751 	cheat.fake_time_period();
752 }
753 
754 //  { ActionWizard, 1, "Toggle archwizard mode", cheat_keys, NONE },
755 // params[0] = -1 for toggle, 0 for off, 1 for on
ActionWizard(int const * params)756 void ActionWizard(int const *params) {
757 	if (params[0] == -1)
758 		cheat.toggle_wizard();
759 	else
760 		cheat.set_wizard(params[0] != 0);
761 }
762 
763 //  { ActionHeal, 0, "Heal party", cheat_keys, NONE },
ActionHeal(int const * params)764 void ActionHeal(int const *params) {
765 	ignore_unused_variable_warning(params);
766 	cheat.heal_party();
767 }
768 
769 //  { ActionCheatScreen, 0, "Cheat Screen", cheat_keys, NONE },
ActionCheatScreen(int const * params)770 void ActionCheatScreen(int const *params) {
771 	ignore_unused_variable_warning(params);
772 	cheat.cheat_screen();
773 }
774 
775 //  { ActionPickPocket, 1, "Toggle Pickpocket", cheat_keys, NONE },
776 // params[0] = -1 for toggle, 0 for off, 1 for on
ActionPickPocket(int const * params)777 void ActionPickPocket(int const *params) {
778 	if (params[0] == -1)
779 		cheat.toggle_pickpocket();
780 	else
781 		cheat.set_pickpocket(params[0] != 0);
782 }
783 
784 //  { ActionPickPocket, 1, "Toggle Pickpocket", cheat_keys, NONE },
785 // params[0] = -1 for toggle, 0 for off, 1 for on
ActionNPCNumbers(int const * params)786 void ActionNPCNumbers(int const *params) {
787 	if (params[0] == -1)
788 		cheat.toggle_number_npcs();
789 	else
790 		cheat.set_number_npcs(params[0] != 0);
791 }
792 
793 //  { ActionGrabActor, 1, "Grab Actor for Cheatscreen", cheat_keys, NONE },
794 // params[0] = -1 for toggle, 0 for off, 1 for on
ActionGrabActor(int const * params)795 void ActionGrabActor(int const *params) {
796 	if (params[0] == -1)
797 		cheat.toggle_grab_actor();
798 	else
799 		cheat.set_grab_actor(params[0] != 0);
800 }
801 
802 //  { ActionCut, "Cut Selected Objects", normal_keys, NONE, true},
ActionCut(int const * params)803 void ActionCut(int const *params) {
804 	ignore_unused_variable_warning(params);
805 	cheat.cut(false);
806 }
807 
808 //  { ActionCopy, "Copy Selected Objects", normal_keys, NONE, true},
ActionCopy(int const * params)809 void ActionCopy(int const *params) {
810 	ignore_unused_variable_warning(params);
811 	cheat.cut(true);
812 }
813 
814 //  { ActionPaste, "Paste Selected Objects", normal_keys, NONE, true},
ActionPaste(int const * params)815 void ActionPaste(int const *params) {
816 	ignore_unused_variable_warning(params);
817 	cheat.paste();
818 }
819 
820 //  { ActionPlayMusic, 1, "Play song", cheat_keys, NONE },
821 // params[0] = song nr., or -1 for next, -2 for previous
ActionPlayMusic(int const * params)822 void ActionPlayMusic(int const *params) {
823 	static int mnum = 0;
824 
825 	if (params[0] == -1) {
826 		Audio::get_ptr()->start_music(mnum++, false);
827 	} else if (params[0] == -2) {
828 		if (mnum > 0)
829 			Audio::get_ptr()->start_music(--mnum, false);
830 	} else {
831 		mnum = params[0];
832 		Audio::get_ptr()->start_music(mnum, false);
833 	}
834 }
835 
836 //  { ActionNaked, 0, "Toggle naked mode", cheat_keys, SERPENT_ISLE },
ActionNaked(int const * params)837 void ActionNaked(int const *params) {
838 	ignore_unused_variable_warning(params);
839 	cheat.toggle_naked();
840 }
841 
842 //  { ActionPetra, 0, "Toggle Petra mode", cheat_keys, SERPENT_ISLE },
ActionPetra(int const * params)843 void ActionPetra(int const *params) {
844 	ignore_unused_variable_warning(params);
845 	cheat.toggle_Petra();
846 }
847 
848 //  { ActionSkinColour, 0 "Change skin colour", cheat_keys, NONE },
ActionSkinColour(int const * params)849 void ActionSkinColour(int const *params) {
850 	ignore_unused_variable_warning(params);
851 	cheat.change_skin();
852 }
853 
854 //   { ActionNotebook, 0, "Show notebook", normal_keys, NONE, false },
ActionNotebook(int const * params)855 void ActionNotebook(int const *params) {
856 	ignore_unused_variable_warning(params);
857 	Game_window *gwin = Game_window::get_instance();
858 	Gump_manager *gman = gwin->get_gump_man();
859 	Notebook_gump *notes = Notebook_gump::get_instance();
860 	if (notes)
861 		gman->remove_gump(notes);   // Want to raise to top.
862 	else
863 		notes = Notebook_gump::create();
864 	gman->add_gump(notes);
865 	gwin->paint();
866 }
867 
868 //  { ActionSoundTester, 0, "Sound tester", cheat_keys, NONE }
ActionSoundTester(int const * params)869 void ActionSoundTester(int const *params) {
870 	ignore_unused_variable_warning(params);
871 	cheat.sound_tester();
872 }
873 
ActionTest(int const * params)874 void ActionTest(int const *params) {
875 	ignore_unused_variable_warning(params);
876 }
877 
878