1 /*
2 * Copyright (C) 2000-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 <cstring>
24
25 #include "SDL_events.h"
26 #include "files/U7file.h"
27 #include "chunks.h"
28 #include "gamemap.h"
29 #include "gamewin.h"
30 #include "game.h"
31 #include "cheat_screen.h"
32 #include "font.h"
33 #include "actors.h"
34 #include "cheat.h"
35 #include "exult.h"
36 #include "imagewin.h"
37 #include "vgafile.h"
38 #include "gameclk.h"
39 #include "schedule.h"
40 #include "ucmachine.h"
41 #include "Configuration.h"
42 #include "SDL.h"
43 #include "party.h"
44 #include "miscinf.h"
45 #include "gump_utils.h"
46 #include "ignore_unused_variable_warning.h"
47 #include "touchui.h"
48 #include "Gump_manager.h"
49
50 const char *CheatScreen::schedules[33] = {
51 "Combat",
52 "Hor. Pace",
53 "Ver. Pace",
54 "Talk",
55 "Dance",
56 "Eat",
57 "Farm",
58 "Tend Shop",
59 "Miner",
60 "Hound",
61 "Stand",
62 "Loiter",
63 "Wander",
64 "Blacksmith",
65 "Sleep",
66 "Wait",
67 "Major Sit",
68 "Graze",
69 "Bake",
70 "Sew",
71 "Shy",
72 "Lab",
73 "Thief",
74 "Waiter",
75 "Special",
76 "Kid Games",
77 "Eat at Inn",
78 "Duel",
79 "Preach",
80 "Patrol",
81 "Desk Work",
82 "Follow Avt",
83 "Move2Sched"
84 };
85
86 const char *CheatScreen::flag_names[64] = {
87 "invisible", // 0x00
88 "asleep", // 0x01
89 "charmed", // 0x02
90 "cursed", // 0x03
91 "dead", // 0x04
92 nullptr, // 0x05
93 "in_party", // 0x06
94 "paralyzed", // 0x07
95
96 "poisoned", // 0x08
97 "protection", // 0x09
98 "on_moving_barge", // 0x0A
99 "okay_to_take", // 0x0B
100 "might", // 0x0C
101 "immunities", //0x0D
102 "cant_die", // 0x0E
103 "dancing", // 0x0F
104
105 "dont_move/bg_dont_render", // 0x10
106 "si_on_moving_barge", // 0x11
107 "is_temporary", // 0x12
108 nullptr, // 0x13
109 "sailor", // 0x14
110 "okay_to_land", // 0x15
111 "dont_render/bg_dont_move", // 0x16
112 "in_dungeon", // 0x17
113
114 nullptr, // 0x18
115 "confused", // 0x19
116 "in_motion", // 0x1A
117 nullptr, // 0x1B
118 "met", // 0x1C
119 "tournament", // 0x1D
120 "si_zombie", // 0x1E
121 "no_spell_casting", // 0x1F
122
123 "polymorph", // 0x20
124 "tattooed", // 0x21
125 "read", // 0x22
126 "petra", // 0x23
127 "si_lizard_king", // 0x24
128 "freeze", // 0x25
129 "naked", // 0x26
130 nullptr, // 0x27
131
132 nullptr, // 0x28
133 nullptr, // 0x29
134 nullptr, // 0x2A
135 nullptr, // 0x2B
136 nullptr, // 0x2C
137 nullptr, // 0x2D
138 nullptr, // 0x2E
139 nullptr, // 0x2F
140
141 nullptr, // 0x30
142 nullptr, // 0x31
143 nullptr, // 0x32
144 nullptr, // 0x33
145 nullptr, // 0x34
146 nullptr, // 0x35
147 nullptr, // 0x36
148 nullptr, // 0x37
149
150 nullptr, // 0x38
151 nullptr, // 0x39
152 nullptr, // 0x3A
153 nullptr, // 0x3B
154 nullptr, // 0x3C
155 nullptr, // 0x3D
156 nullptr, // 0x3E
157 nullptr, // 0x3F
158 };
159
160 const char *CheatScreen::alignments[4] = {
161 "Neutral",
162 "Good",
163 "Evil",
164 "Chaotic"
165 };
166
Find_highest_map()167 static int Find_highest_map(
168 ) {
169 int n = 0;
170 int next;
171 while ((next = Find_next_map(n + 1, 10)) != -1)
172 n = next;
173 return n;
174 }
175
show_screen()176 void CheatScreen::show_screen() {
177 gwin = Game_window::get_instance();
178 ibuf = gwin->get_win()->get_ib8();
179 font = fontManager.get_font("MENU_FONT");
180 clock = gwin->get_clock();
181 maxx = gwin->get_width();
182 #ifdef __IPHONEOS__
183 maxy = 200;
184 #else
185 maxy = gwin->get_height();
186 #endif
187 centerx = maxx / 2;
188 centery = maxy / 2;
189 if (touchui != nullptr) {
190 touchui->hideGameControls();
191 SDL_StartTextInput();
192 }
193
194 // Pause the game
195 gwin->get_tqueue()->pause(SDL_GetTicks());
196
197 const str_int_pair &pal_tuple_static = game->get_resource("palettes/0");
198 const str_int_pair &pal_tuple_patch = game->get_resource("palettes/patch/0");
199 pal.load(pal_tuple_static.str, pal_tuple_patch.str, pal_tuple_static.num);
200 pal.apply();
201
202 // Start the loop
203 NormalLoop();
204
205 // Resume the game clock
206 gwin->get_tqueue()->resume(SDL_GetTicks());
207
208 // Reset the palette
209 clock->reset_palette();
210 if (touchui != nullptr) {
211 Gump_manager *gumpman = gwin->get_gump_man();
212 if (!gumpman->gump_mode()) {
213 touchui->showGameControls();
214 }
215 if (SDL_IsTextInputActive()) {
216 SDL_StopTextInput();
217 }
218 }
219 }
220
221
222 //
223 // DISPLAYS
224 //
225
226 //
227 // Shared
228 //
229
SharedPrompt(char * input,const Cheat_Prompt & mode)230 void CheatScreen::SharedPrompt(char *input, const Cheat_Prompt &mode) {
231 char buf[512];
232
233 #ifdef __IPHONEOS__
234 const int prompt = 81;
235 const int promptmes = 90;
236 const int offsetx = 15;
237 #else
238 const int prompt = maxy - 18;
239 const int promptmes = maxy - 9;
240 const int offsetx = 0;
241 #endif
242 font->paint_text_fixedwidth(ibuf, "Select->", offsetx, prompt, 8);
243
244 if (input && std::strlen(input)) {
245 font->paint_text_fixedwidth(ibuf, input, 64 + offsetx , prompt, 8);
246 font->paint_text_fixedwidth(ibuf, "_", 64 + offsetx + std::strlen(input) * 8, prompt, 8);
247 } else
248 font->paint_text_fixedwidth(ibuf, "_", 64 + offsetx, prompt, 8);
249
250 // ...and Prompt Message
251 switch (mode) {
252 default:
253 case CP_Command:
254 font->paint_text_fixedwidth(ibuf, "Enter Command.", offsetx, promptmes, 8);
255 break;
256
257 case CP_HitKey:
258 font->paint_text_fixedwidth(ibuf, "Hit a key.", offsetx, promptmes, 8);
259 break;
260
261 case CP_NotAvail:
262 font->paint_text_fixedwidth(ibuf, "Not yet available. Hit a key.", offsetx, promptmes, 8);
263 break;
264
265 case CP_InvalidNPC:
266 font->paint_text_fixedwidth(ibuf, "Invalid NPC. Hit a key", offsetx, promptmes, 8);
267 break;
268
269 case CP_InvalidCom:
270 font->paint_text_fixedwidth(ibuf, "Invalid Command. Hit a key.", offsetx, promptmes, 8);
271 break;
272
273 case CP_Canceled:
274 font->paint_text_fixedwidth(ibuf, "Canceled. Hit a key.", offsetx, promptmes, 8);
275 break;
276
277 case CP_ClockSet:
278 font->paint_text_fixedwidth(ibuf, "Clock Set. Hit a key.", offsetx, promptmes, 8);
279 break;
280
281 case CP_InvalidTime:
282 font->paint_text_fixedwidth(ibuf, "Invalid Time. Hit a key.", offsetx, promptmes, 8);
283 break;
284
285 case CP_InvalidShape:
286 font->paint_text_fixedwidth(ibuf, "Invalid Shape. Hit a key.", offsetx, promptmes, 8);
287 break;
288
289 case CP_InvalidValue:
290 font->paint_text_fixedwidth(ibuf, "Invalid Value. Hit a key.", offsetx, promptmes, 8);
291 break;
292
293 case CP_Created:
294 font->paint_text_fixedwidth(ibuf, "Item Created. Hit a key.", offsetx, promptmes, 8);
295 break;
296
297 case CP_ShapeSet:
298 font->paint_text_fixedwidth(ibuf, "Shape Set. Hit a key.", offsetx, promptmes, 8);
299 break;
300
301 case CP_ValueSet:
302 font->paint_text_fixedwidth(ibuf, "Clock Set. Hit a key.", offsetx, promptmes, 8);
303 break;
304
305 case CP_NameSet:
306 font->paint_text_fixedwidth(ibuf, "Name Changed. Hit a key.", offsetx, promptmes, 8);
307 break;
308
309 case CP_WrongShapeFile:
310 font->paint_text_fixedwidth(ibuf, "Wrong shape file. Must be SHAPES.VGA.", offsetx, promptmes, 8);
311 break;
312
313
314 case CP_ChooseNPC:
315 font->paint_text_fixedwidth(ibuf, "Which NPC? (-1 to cancel.)", offsetx, promptmes, 8);
316 break;
317
318 case CP_EnterValue:
319 font->paint_text_fixedwidth(ibuf, "Enter Value. (-1 to cancel.)", offsetx, promptmes, 8);
320 break;
321
322 case CP_EnterValueNoCancel:
323 font->paint_text_fixedwidth(ibuf, "Enter Value.", offsetx, promptmes, 8);
324 break;
325
326 case CP_Minute:
327 font->paint_text_fixedwidth(ibuf, "Enter Minute. (-1 to cancel.)", offsetx, promptmes, 8);
328 break;
329
330 case CP_Hour:
331 font->paint_text_fixedwidth(ibuf, "Enter Hour. (-1 to cancel.)", offsetx, promptmes, 8);
332 break;
333
334 case CP_Day:
335 font->paint_text_fixedwidth(ibuf, "Enter Day. (-1 to cancel.)", offsetx, promptmes, 8);
336 break;
337
338 case CP_Shape:
339 font->paint_text_fixedwidth(ibuf, "Enter Shape (B=Browse or -1=Cancel)", offsetx, promptmes, 8);
340 break;
341
342 case CP_Activity:
343 font->paint_text_fixedwidth(ibuf, "Enter Activity 0-31. (-1 to cancel.)", offsetx, promptmes, 8);
344 break;
345
346 case CP_XCoord:
347 snprintf(buf, 512, "Enter X Coord. Max %i (-1 to cancel)", c_num_tiles);
348 font->paint_text_fixedwidth(ibuf, buf, offsetx, promptmes, 8);
349 break;
350
351 case CP_YCoord:
352 snprintf(buf, 512, "Enter Y Coord. Max %i (-1 to cancel)", c_num_tiles);
353 font->paint_text_fixedwidth(ibuf, buf, offsetx, promptmes, 8);
354 break;
355
356 case CP_Lift:
357 font->paint_text_fixedwidth(ibuf, "Enter Lift. (-1 to cancel)", offsetx, promptmes, 8);
358 break;
359
360 case CP_GFlagNum: {
361 char buf[50];
362 snprintf(buf, 50, "Enter Global Flag 0-%d. (-1 to cancel)", c_last_gflag);
363 font->paint_text_fixedwidth(ibuf, buf, offsetx, promptmes, 8);
364 break;
365 }
366
367 case CP_NFlagNum:
368 font->paint_text_fixedwidth(ibuf, "Enter NPC Flag 0-63. (-1 to cancel)", offsetx, promptmes, 8);
369 break;
370
371 case CP_TempNum:
372 font->paint_text_fixedwidth(ibuf, "Enter Temperature 0-63. (-1 to cancel)", offsetx, promptmes, 8);
373 break;
374
375 case CP_NLatitude:
376 font->paint_text_fixedwidth(ibuf, "Enter Latitude. Max 113 (-1 to cancel)", offsetx, promptmes, 8);
377 break;
378
379 case CP_SLatitude:
380 font->paint_text_fixedwidth(ibuf, "Enter Latitude. Max 193 (-1 to cancel)", offsetx, promptmes, 8);
381 break;
382
383 case CP_WLongitude:
384 font->paint_text_fixedwidth(ibuf, "Enter Longitude. Max 93 (-1 to cancel)", offsetx, promptmes, 8);
385 break;
386
387 case CP_ELongitude:
388 font->paint_text_fixedwidth(ibuf, "Enter Longitude. Max 213 (-1 to cancel)", offsetx, promptmes, 8);
389 break;
390
391 case CP_Name:
392 font->paint_text_fixedwidth(ibuf, "Enter a new Name...", offsetx, promptmes, 8);
393 break;
394
395 case CP_NorthSouth:
396 font->paint_text_fixedwidth(ibuf, "Latitude [N]orth or [S]outh?", offsetx, promptmes, 8);
397 break;
398
399 case CP_WestEast:
400 font->paint_text_fixedwidth(ibuf, "Longitude [W]est or [E]ast?", offsetx, promptmes, 8);
401 break;
402
403 case CP_HexXCoord:
404 snprintf(buf, 512, "Enter X Coord. Max %04x (-1 to cancel)", c_num_tiles);
405 font->paint_text_fixedwidth(ibuf, buf, offsetx, promptmes, 8);
406 break;
407
408 case CP_HexYCoord:
409 snprintf(buf, 512, "Enter Y Coord. Max %04x (-1 to cancel)", c_num_tiles);
410 font->paint_text_fixedwidth(ibuf, buf, offsetx, promptmes, 8);
411 break;
412
413 }
414 }
415
SDLScanCodeToInt(SDL_Keycode sym)416 static int SDLScanCodeToInt(SDL_Keycode sym) {
417 switch (sym) {
418 case SDLK_KP_0:
419 return '0';
420 case SDLK_KP_1:
421 return '1';
422 case SDLK_KP_2:
423 return '2';
424 case SDLK_KP_3:
425 return '3';
426 case SDLK_KP_4:
427 return '4';
428 case SDLK_KP_5:
429 return '5';
430 case SDLK_KP_6:
431 return '6';
432 case SDLK_KP_7:
433 return '7';
434 case SDLK_KP_8:
435 return '8';
436 case SDLK_KP_9:
437 return '9';
438 default:
439 return -1;
440 }
441 }
442
SharedInput(char * input,int len,int & command,Cheat_Prompt & mode,bool & activate)443 bool CheatScreen::SharedInput(char *input, int len, int &command, Cheat_Prompt &mode, bool &activate) {
444 SDL_Event event;
445
446 while (true) {
447 Delay();
448 while (SDL_PollEvent(&event)) {
449 // Touch on the cheat screen will bring up the keyboard
450 if (event.type == SDL_MOUSEBUTTONDOWN) {
451 if (SDL_IsTextInputActive())
452 SDL_StopTextInput();
453 else
454 SDL_StartTextInput();
455 }
456
457 if (event.type != SDL_KEYDOWN)
458 continue;
459 SDL_Keysym &key = event.key.keysym;
460
461 if ((key.sym == SDLK_s) && (key.mod & KMOD_ALT) && (key.mod & KMOD_CTRL)) {
462 make_screenshot(true);
463 return false;
464 }
465
466 if (mode == CP_NorthSouth) {
467 if (!input[0] && (key.sym == 'n' || key.sym == 's')) {
468 input[0] = key.sym;
469 activate = true;
470 }
471 } else if (mode == CP_WestEast) {
472 if (!input[0] && (key.sym == 'w' || key.sym == 'e')) {
473 input[0] = key.sym;
474 activate = true;
475 }
476 } else if (mode >= CP_HexXCoord) { // Want hex input
477 // Activate (if possible)
478 if (key.sym == SDLK_RETURN || key.sym == SDLK_KP_ENTER) {
479 activate = true;
480 } else if ((key.sym == '-' || key.sym == SDLK_KP_MINUS) && !input[0]) {
481 input[0] = '-';
482 } else if (std::isxdigit(key.sym)) {
483 int curlen = std::strlen(input);
484 if (curlen < (len - 1)) {
485 input[curlen] = std::tolower(key.sym);
486 input[curlen + 1] = 0;
487 }
488 } else if ((key.sym >= SDLK_KP_1 && key.sym <= SDLK_KP_9) || key.sym == SDLK_KP_0) {
489 int curlen = std::strlen(input);
490 if (curlen < (len - 1)) {
491 int sym = SDLScanCodeToInt(key.sym);
492 input[curlen] = sym;
493 input[curlen + 1] = 0;
494 }
495 } else if (key.sym == SDLK_BACKSPACE) {
496 int curlen = std::strlen(input);
497 if (curlen) input[curlen - 1] = 0;
498 }
499 } else if (mode >= CP_Name) { // Want Text input (len chars)
500 if (key.sym == SDLK_RETURN || key.sym == SDLK_KP_ENTER) {
501 activate = true;
502 } else if (std::isalnum(key.sym) || key.sym == ' ') {
503 int curlen = std::strlen(input);
504 char chr = key.sym;
505 if (key.mod & KMOD_SHIFT) {
506 chr = static_cast<char>(std::toupper(static_cast<unsigned char>(chr)));
507 }
508 if (curlen < (len - 1)) {
509 input[curlen] = chr;
510 input[curlen + 1] = 0;
511 }
512 } else if (key.sym == SDLK_BACKSPACE) {
513 int curlen = std::strlen(input);
514 if (curlen) input[curlen - 1] = 0;
515 }
516 } else if (mode >= CP_ChooseNPC) { // Need to grab numerical input
517 // Browse shape
518 if (mode == CP_Shape && !input[0] && key.sym == 'b') {
519 cheat.shape_browser();
520 input[0] = 'b';
521 activate = true;
522 }
523
524 // Activate (if possible)
525 if (key.sym == SDLK_RETURN || key.sym == SDLK_KP_ENTER) {
526 activate = true;
527 } else if ((key.sym == '-' || key.sym == SDLK_KP_MINUS) && !input[0]) {
528 input[0] = '-';
529 } else if (std::isdigit(key.sym)) {
530 int curlen = std::strlen(input);
531 if (curlen < (len - 1)) {
532 input[curlen] = key.sym;
533 input[curlen + 1] = 0;
534 }
535 } else if ((key.sym >= SDLK_KP_1 && key.sym <= SDLK_KP_9) || key.sym == SDLK_KP_0) {
536 int curlen = std::strlen(input);
537 if (curlen < (len - 1)) {
538 int sym = SDLScanCodeToInt(key.sym);
539 input[curlen] = sym;
540 input[curlen + 1] = 0;
541 }
542 } else if (key.sym == SDLK_BACKSPACE) {
543 int curlen = std::strlen(input);
544 if (curlen) input[curlen - 1] = 0;
545 }
546 } else if (mode) { // Just want a key pressed
547 mode = CP_Command;
548 for (int i = 0; i < len; i++) input[i] = 0;
549 command = 0;
550 } else { // Need the key pressed
551 command = key.sym;
552 return true;
553 }
554 return false;
555 }
556 gwin->paint_dirty();
557 }
558 return false;
559 }
560
561
562 //
563 // Normal
564 //
565
NormalLoop()566 void CheatScreen::NormalLoop() {
567 bool looping = true;
568
569 // This is for the prompt message
570 Cheat_Prompt mode = CP_Command;
571
572 // This is the command
573 char input[5] = { 0, 0, 0, 0, 0 };
574 int command;
575 bool activate = false;
576
577 while (looping) {
578 gwin->clear_screen();
579
580 // First the display
581 NormalDisplay();
582
583 // Now the Menu Column
584 NormalMenu();
585
586 // Finally the Prompt...
587 SharedPrompt(input, mode);
588
589 // Draw it!
590 gwin->get_win()->show();
591
592 // Check to see if we need to change menus
593 if (activate) {
594 NormalActivate(input, command, mode);
595 activate = false;
596 continue;
597 }
598
599 if (SharedInput(input, 5, command, mode, activate))
600 looping = NormalCheck(input, command, mode, activate);
601 }
602 }
603
NormalDisplay()604 void CheatScreen::NormalDisplay() {
605 char buf[512];
606 #ifdef __IPHONEOS__
607 const int offsetx = 15;
608 const int offsety1 = 108;
609 const int offsety2 = 54;
610 const int offsety3 = 0;
611 #else
612 const int offsetx = 0;
613 const int offsety1 = 0;
614 const int offsety2 = 0;
615 const int offsety3 = 45;
616 #endif
617 int curmap = gwin->get_map()->get_num();
618 Tile_coord t = gwin->get_main_actor()->get_tile();
619
620 font->paint_text_fixedwidth(ibuf, "Colourless' Advanced Option Cheat Screen", 0, offsety1, 8);
621
622 if (Game::get_game_type() == BLACK_GATE)
623 snprintf(buf, 512, "Running \"Ultima 7: The Black Gate\"");
624 else if (Game::get_game_type() == SERPENT_ISLE)
625 snprintf(buf, 512, "Running \"Ultima 7: Part 2: Serpent Isle\"");
626 else
627 snprintf(buf, 512, "Running Unknown Game Type %i", Game::get_game_type());
628
629 font->paint_text_fixedwidth(ibuf, buf, offsetx, offsety1 + 18, 8);
630
631 snprintf(buf, 512, "Exult Version %s", VERSION);
632 font->paint_text_fixedwidth(ibuf, buf, offsetx, offsety1 + 27, 8);
633
634
635 snprintf(buf, 512, "Current time: %i:%02i %s Day: %i",
636 ((clock->get_hour() + 11) % 12) + 1,
637 clock->get_minute(),
638 clock->get_hour() < 12 ? "AM" : "PM",
639 clock->get_day());
640 font->paint_text_fixedwidth(ibuf, buf, offsetx, offsety3, 8);
641
642 int longi = ((t.tx - 0x3A5) / 10);
643 int lati = ((t.ty - 0x46E) / 10);
644 snprintf(buf, 512, "Coordinates %d %s %d %s, Map #%d",
645 abs(lati), (lati < 0 ? "North" : "South"),
646 abs(longi), (longi < 0 ? "West" : "East"), curmap);
647 font->paint_text_fixedwidth(ibuf, buf, offsetx, 63 - offsety2, 8);
648
649 snprintf(buf, 512, "Coords in hex (%04x, %04x, %02x)",
650 t.tx, t.ty, t.tz);
651 font->paint_text_fixedwidth(ibuf, buf, offsetx, 72 - offsety2, 8);
652
653 snprintf(buf, 512, "Coords in dec (%04i, %04i, %02i)",
654 t.tx, t.ty, t.tz);
655 font->paint_text_fixedwidth(ibuf, buf, offsetx, 81 - offsety2, 8);
656 }
657
NormalMenu()658 void CheatScreen::NormalMenu() {
659 char buf[512];
660 #ifdef __IPHONEOS__
661 const int offsetx = 15;
662 const int offsety1 = 73;
663 const int offsety2 = 55;
664 const int offsetx1 = 160;
665 const int offsety4 = 36;
666 const int offsety5 = 72;
667 #else
668 const int offsetx = 0;
669 const int offsety1 = 0;
670 const int offsety2 = 0;
671 const int offsetx1 = 0;
672 const int offsety4 = maxy - 45;
673 const int offsety5 = maxy - 36;
674 #endif
675
676 // Left Column
677
678 // Use
679 #ifndef __IPHONEOS__
680 // Paperdolls can be toggled in the gumps, no need here for iOS
681 Shape_manager *sman = Shape_manager::get_instance();
682 if (sman->can_use_paperdolls() && sman->are_paperdolls_enabled())
683 snprintf(buf, 512, "[P]aperdolls..: Yes");
684 else
685 snprintf(buf, 512, "[P]aperdolls..: No");
686 font->paint_text_fixedwidth(ibuf, buf, 0, maxy - 99, 8);
687 #endif
688
689 // GodMode
690 snprintf(buf, 512, "[G]od Mode....: %3s", cheat.in_god_mode() ? "On" : "Off");
691 font->paint_text_fixedwidth(ibuf, buf, offsetx, maxy - offsety1 - 90, 8);
692
693 // Archwizzard Mode
694 snprintf(buf, 512, "[W]izard Mode.: %3s", cheat.in_wizard_mode() ? "On" : "Off");
695 font->paint_text_fixedwidth(ibuf, buf, offsetx, maxy - offsety1 - 81, 8);
696
697 // Infravision
698 snprintf(buf, 512, "[I]nfravision.: %3s", cheat.in_infravision() ? "On" : "Off");
699 font->paint_text_fixedwidth(ibuf, buf, offsetx, maxy - offsety1 - 72, 8);
700
701 // Hackmover
702 snprintf(buf, 512, "[H]ack Mover..: %3s", cheat.in_hack_mover() ? "Yes" : "No");
703 font->paint_text_fixedwidth(ibuf, buf, offsetx, maxy - offsety1 - 63, 8);
704
705 // Eggs
706 snprintf(buf, 512, "[E]ggs Visible: %3s", gwin->paint_eggs ? "Yes" : "No");
707 font->paint_text_fixedwidth(ibuf, buf, offsetx, maxy - offsety1 - 54, 8);
708
709 // Set Time
710 font->paint_text_fixedwidth(ibuf, "[S]et Time", offsetx + offsetx1, offsety4, 8);
711
712 #ifndef __IPHONEOS__
713 // for iOS taking the liberty of leaving that out
714 // Time Rate
715 snprintf(buf, 512, "[+-] Time Rate: %3i", clock->get_time_rate());
716 font->paint_text_fixedwidth(ibuf, buf, 0, maxy - 36, 8);
717 #endif
718
719
720 // Right Column
721
722 // NPC Tool
723 font->paint_text_fixedwidth(ibuf, "[N]PC Tool", offsetx + 160, maxy - offsety2 - 99, 8);
724
725 // Global Flag Modify
726 font->paint_text_fixedwidth(ibuf, "[F]lag Modifier", offsetx + 160, maxy - offsety2 - 90, 8);
727
728 // Teleport
729 font->paint_text_fixedwidth(ibuf, "[T]eleport", offsetx + 160, maxy - offsety2 - 81, 8);
730
731 // eXit
732 font->paint_text_fixedwidth(ibuf, "[X]it", offsetx + 160, offsety5, 8);
733 }
734
NormalActivate(char * input,int & command,Cheat_Prompt & mode)735 void CheatScreen::NormalActivate(char *input, int &command, Cheat_Prompt &mode) {
736 int npc = std::atoi(input);
737 Shape_manager *sman = Shape_manager::get_instance();
738
739 mode = CP_Command;
740
741 switch (command) {
742 // God Mode
743 case 'g':
744 cheat.toggle_god();
745 break;
746
747 // Wizard Mode
748 case 'w':
749 cheat.toggle_wizard();
750 break;
751
752 // Infravision
753 case 'i':
754 cheat.toggle_infravision();
755 pal.apply();
756 break;
757
758 // Eggs
759 case 'e':
760 cheat.toggle_eggs();
761 break;
762
763 // Hack mover
764 case 'h':
765 cheat.toggle_hack_mover();
766 break;
767
768 // Set Time
769 case 's':
770 mode = TimeSetLoop();
771 break;
772
773 // - Time Rate
774 case '-':
775 if (clock->get_time_rate() > 0)
776 clock->set_time_rate(clock->get_time_rate() - 1);
777 break;
778
779 // + Time Rate
780 case '+':
781 if (clock->get_time_rate() < 20)
782 clock->set_time_rate(clock->get_time_rate() + 1);
783 break;
784
785 // Teleport
786 case 't':
787 TeleportLoop();
788 break;
789
790 // NPC Tool
791 case 'n':
792 if (npc < -1 || (npc >= 356 && npc <= 359)) mode = CP_InvalidNPC;
793 else if (npc == -1) mode = CP_Canceled;
794 else if (!input[0]) NPCLoop(-1);
795 else mode = NPCLoop(npc);
796 break;
797
798 // Global Flag Editor
799 case 'f':
800 if (npc < -1) mode = CP_InvalidValue;
801 else if (npc > c_last_gflag) mode = CP_InvalidValue;
802 else if (npc == -1 || !input[0]) mode = CP_Canceled;
803 else mode = GlobalFlagLoop(npc);
804 break;
805
806 // Paperdolls
807 case 'p':
808 if ((Game::get_game_type() == BLACK_GATE
809 || Game::get_game_type() == EXULT_DEVEL_GAME)
810 && sman->can_use_paperdolls()) {
811 sman->set_paperdoll_status(!sman->are_paperdolls_enabled());
812 config->set("config/gameplay/bg_paperdolls",
813 sman->are_paperdolls_enabled() ? "yes" : "no", true);
814 }
815 break;
816
817 default:
818 break;
819 }
820
821 input[0] = 0;
822 input[1] = 0;
823 input[2] = 0;
824 input[3] = 0;
825 command = 0;
826 }
827
828 // Checks the input
NormalCheck(char * input,int & command,Cheat_Prompt & mode,bool & activate)829 bool CheatScreen::NormalCheck(char *input, int &command, Cheat_Prompt &mode, bool &activate) {
830 switch (command) {
831 // Simple commands
832 case 't': // Teleport
833 case 'g': // God Mode
834 case 'w': // Wizard
835 case 'i': // iNfravision
836 case 's': // Set Time
837 case 'e': // Eggs
838 case 'h': // Hack Mover
839 case 'c': // Create Item
840 case 'p': // Paperdolls
841 input[0] = command;
842 activate = true;
843 break;
844
845 // - Time
846 case SDLK_KP_MINUS:
847 case '-':
848 command = '-';
849 input[0] = command;
850 activate = true;
851 break;
852
853 // + Time
854 case SDLK_KP_PLUS:
855 case '=':
856 command = '+';
857 input[0] = command;
858 activate = true;
859 break;
860
861 // NPC Tool
862 case 'n':
863 mode = CP_ChooseNPC;
864 break;
865
866 // Global Flag Editor
867 case 'f':
868 mode = CP_GFlagNum;
869 break;
870
871 // X and Escape leave
872 case SDLK_ESCAPE:
873 case 'x':
874 input[0] = command;
875 return false;
876
877 default:
878 mode = CP_InvalidCom;
879 input[0] = command;
880 command = 0;
881 break;
882 }
883
884 return true;
885 }
886
887 //
888 // Activity Display
889 //
890
ActivityDisplay()891 void CheatScreen::ActivityDisplay() {
892 char buf[512];
893 #ifdef __IPHONEOS__
894 const int offsety1 = 99;
895 #else
896 const int offsety1 = 0;
897 #endif
898
899 for (int i = 0; i < 11; i++) {
900 snprintf(buf, 512, "%2i %s", i, schedules[i]);
901 font->paint_text_fixedwidth(ibuf, buf, 0, i * 9 + offsety1, 8);
902
903 snprintf(buf, 512, "%2i %s", i + 11, schedules[i + 11]);
904 font->paint_text_fixedwidth(ibuf, buf, 112, i * 9 + offsety1, 8);
905
906 if (i != 10) {
907 snprintf(buf, 512, "%2i %s", i + 22, schedules[i + 22]);
908 font->paint_text_fixedwidth(ibuf, buf, 224, i * 9 + offsety1, 8);
909 }
910 }
911
912 }
913
914
915 //
916 // TimeSet
917 //
918
TimeSetLoop()919 CheatScreen::Cheat_Prompt CheatScreen::TimeSetLoop() {
920 // This is for the prompt message
921 Cheat_Prompt mode = CP_Day;
922
923 // This is the command
924 char input[5] = { 0, 0, 0, 0, 0 };
925 int command;
926 bool activate = false;
927
928 int day = 0;
929 int hour = 0;
930
931 while (true) {
932 gwin->clear_screen();
933
934 // First the display
935 NormalDisplay();
936
937 // Now the Menu Column
938 NormalMenu();
939
940 // Finally the Prompt...
941 SharedPrompt(input, mode);
942
943 // Draw it!
944 gwin->get_win()->show();
945
946 // Check to see if we need to change menus
947 if (activate) {
948 int val = std::atoi(input);
949
950 if (val == -1) {
951 return CP_Canceled;
952 } else if (val < -1) {
953 return CP_InvalidTime;
954 } else if (mode == CP_Day) {
955 day = val;
956 mode = CP_Hour;
957 } else if (val > 59) {
958 return CP_InvalidTime;
959 } else if (mode == CP_Minute) {
960 clock->reset();
961 clock->set_day(day);
962 clock->set_hour(hour);
963 clock->set_minute(val);
964 break;
965 } else if (val > 23) {
966 return CP_InvalidTime;
967 } else if (mode == CP_Hour) {
968 hour = val;
969 mode = CP_Minute;
970 }
971
972 activate = false;
973 input[0] = 0;
974 input[1] = 0;
975 input[2] = 0;
976 input[3] = 0;
977 command = 0;
978 continue;
979 }
980
981 SharedInput(input, 5, command, mode, activate);
982 }
983
984 return CP_ClockSet;
985 }
986
987
988 //
989 // Global Flags
990 //
991
GlobalFlagLoop(int num)992 CheatScreen::Cheat_Prompt CheatScreen::GlobalFlagLoop(int num) {
993 bool looping = true;
994 #ifdef __IPHONEOS__
995 const int offsetx = 15;
996 const int offsety1 = 83;
997 const int offsety2 = 72;
998 #else
999 const int offsetx = 0;
1000 const int offsety1 = 0;
1001 const int offsety2 = maxy - 36;
1002 #endif
1003
1004 // This is for the prompt message
1005 Cheat_Prompt mode = CP_Command;
1006
1007 // This is the command
1008 char input[17];
1009 int i;
1010 int command;
1011 bool activate = false;
1012 char buf[512];
1013
1014 for (i = 0; i < 17; i++) input[i] = 0;
1015
1016 Usecode_machine *usecode = Game_window::get_instance()->get_usecode();
1017
1018 while (looping) {
1019 gwin->clear_screen();
1020
1021 #ifdef __IPHONEOS__
1022 // on iOS we want lean and mean, so begone NormalDisplay
1023 font->paint_text_fixedwidth(ibuf, "Global Flags", 15, 0, 8);
1024 #else
1025 NormalDisplay();
1026 #endif
1027
1028 // First the info
1029 snprintf(buf, 512, "Global Flag %i", num);
1030 font->paint_text_fixedwidth(ibuf, buf, offsetx, maxy - offsety1 - 99, 8);
1031
1032 snprintf(buf, 512, "Flag is %s", usecode->get_global_flag(num) ? "SET" : "UNSET");
1033 font->paint_text_fixedwidth(ibuf, buf, offsetx, maxy - offsety1 - 90, 8);
1034
1035 // Now the Menu Column
1036 if (!usecode->get_global_flag(num)) font->paint_text_fixedwidth(ibuf, "[S]et Flag", offsetx + 160, maxy - offsety1 - 99, 8);
1037 else font->paint_text_fixedwidth(ibuf, "[U]nset Flag", offsetx + 160, maxy - offsety1 - 99, 8);
1038
1039 // Change Flag
1040
1041 font->paint_text_fixedwidth(ibuf, "[*] Change Flag", offsetx, maxy - offsety1 - 72, 8);
1042 if (num > 0 && num < c_last_gflag) font->paint_text_fixedwidth(ibuf, "[+-] Scroll Flags", offsetx, maxy - offsety1 - 63, 8);
1043 else if (num == 0) font->paint_text_fixedwidth(ibuf, "[+] Scroll Flags", offsetx, maxy - offsety1 - 63, 8);
1044 else font->paint_text_fixedwidth(ibuf, "[-] Scroll Flags", offsetx, maxy - offsety1 - 63, 8);
1045 font->paint_text_fixedwidth(ibuf, "[X]it", offsetx, offsety2, 8);
1046
1047 // Finally the Prompt...
1048 SharedPrompt(input, mode);
1049
1050 // Draw it!
1051 gwin->get_win()->show();
1052
1053 // Check to see if we need to change menus
1054 if (activate) {
1055 mode = CP_Command;
1056 if (command == '-') { // Decrement
1057 num--;
1058 if (num < 0) {
1059 num = 0;
1060 }
1061 } else if (command == '+') { // Increment
1062 num++;
1063 if (num > c_last_gflag) {
1064 num = c_last_gflag;
1065 }
1066 } else if (command == '*') { // Change Flag
1067 i = std::atoi(input);
1068 if (i < -1 || i > c_last_gflag) {
1069 mode = CP_InvalidValue;
1070 } else if (i == -1) {
1071 mode = CP_Canceled;
1072 } else if (input[0]) {
1073 num = i;
1074 }
1075 } else if (command == 's') { // Set
1076 usecode->set_global_flag(num, 1);
1077 } else if (command == 'u') { // Unset
1078 usecode->set_global_flag(num, 0);
1079 }
1080
1081 for (i = 0; i < 17; i++) {
1082 input[i] = 0;
1083 }
1084 command = 0;
1085 activate = false;
1086 continue;
1087 }
1088
1089 if (SharedInput(input, 17, command, mode, activate)) {
1090 switch (command) {
1091 // Simple commands
1092 case 's': // Set Flag
1093 case 'u': // Unset flag
1094 input[0] = command;
1095 activate = true;
1096 break;
1097
1098 // Decrement
1099 case SDLK_KP_MINUS:
1100 case '-':
1101 command = '-';
1102 input[0] = command;
1103 activate = true;
1104 break;
1105
1106 // Increment
1107 case SDLK_KP_PLUS:
1108 case '=':
1109 command = '+';
1110 input[0] = command;
1111 activate = true;
1112 break;
1113
1114 // * Change Flag
1115 case SDLK_KP_MULTIPLY:
1116 case '8':
1117 command = '*';
1118 input[0] = 0;
1119 mode = CP_GFlagNum;
1120 break;
1121
1122 // X and Escape leave
1123 case SDLK_ESCAPE:
1124 case 'x':
1125 input[0] = command;
1126 looping = false;
1127 break;
1128
1129 default:
1130 mode = CP_InvalidCom;
1131 input[0] = command;
1132 command = 0;
1133 break;
1134 }
1135 }
1136 }
1137 return CP_Command;
1138 }
1139
1140 //
1141 // NPCs
1142 //
1143
NPCLoop(int num)1144 CheatScreen::Cheat_Prompt CheatScreen::NPCLoop(int num) {
1145 Actor *actor;
1146
1147 bool looping = true;
1148
1149 // This is for the prompt message
1150 Cheat_Prompt mode = CP_Command;
1151
1152 // This is the command
1153 char input[17];
1154 int i;
1155 int command;
1156 bool activate = false;
1157
1158 for (i = 0; i < 17; i++) input[i] = 0;
1159
1160 while (looping) {
1161 if (num == -1) actor = grabbed;
1162 else actor = gwin->get_npc(num);
1163 grabbed = actor;
1164 if (actor) num = actor->get_npc_num();
1165
1166 gwin->clear_screen();
1167
1168 // First the display
1169 NPCDisplay(actor, num);
1170
1171 // Now the Menu Column
1172 NPCMenu(actor, num);
1173
1174 // Finally the Prompt...
1175 SharedPrompt(input, mode);
1176
1177 // Draw it!
1178 gwin->get_win()->show();
1179
1180 // Check to see if we need to change menus
1181 if (activate) {
1182 NPCActivate(input, command, mode, actor, num);
1183 activate = false;
1184 continue;
1185 }
1186
1187 if (SharedInput(input, 17, command, mode, activate))
1188 looping = NPCCheck(input, command, mode, activate, actor, num);
1189 }
1190 return CP_Command;
1191 }
1192
NPCDisplay(Actor * actor,int & num)1193 void CheatScreen::NPCDisplay(Actor *actor, int &num) {
1194 char buf[512];
1195 #ifdef __IPHONEOS__
1196 const int offsetx = 15;
1197 const int offsety1 = 73;
1198 #else
1199 const int offsetx = 0;
1200 const int offsety1 = 0;
1201 #endif
1202 if (actor) {
1203 Tile_coord t = actor->get_tile();
1204
1205 // Paint the actors shape
1206 Shape_frame *shape = actor->get_shape();
1207 if (shape) actor->paint_shape(shape->get_xright() + 240, shape->get_yabove());
1208
1209 // Now the info
1210 std::string namestr = actor->get_npc_name();
1211 snprintf(buf, 512, "NPC %i - %s", num, namestr.c_str());
1212 font->paint_text_fixedwidth(ibuf, buf, offsetx, 0, 8);
1213
1214 snprintf(buf, 512, "Loc (%04i, %04i, %02i)",
1215 t.tx, t.ty, t.tz);
1216 font->paint_text_fixedwidth(ibuf, buf, offsetx, 9, 8);
1217
1218 snprintf(buf, 512, "Shape %04i:%02i %s", actor->get_shapenum(), actor->get_framenum(), actor->get_flag(Obj_flags::met) ? "Met" : "Not Met");
1219 font->paint_text_fixedwidth(ibuf, buf, offsetx, 18, 8);
1220
1221 snprintf(buf, 512, "Current Activity: %2i - %s", actor->get_schedule_type(), schedules[actor->get_schedule_type()]);
1222 font->paint_text_fixedwidth(ibuf, buf, offsetx, offsety1 + 36, 8);
1223
1224 snprintf(buf, 512, "Experience: %i", actor->get_property(Actor::exp));
1225 font->paint_text_fixedwidth(ibuf, buf, offsetx, offsety1 + 45, 8);
1226
1227 snprintf(buf, 512, "Level: %i", actor->get_level());
1228 font->paint_text_fixedwidth(ibuf, buf, offsetx + 144, offsety1 + 45, 8);
1229
1230 snprintf(buf, 512, "Training: %2i Health: %2i", actor->get_property(Actor::training), actor->get_property(Actor::health));
1231 font->paint_text_fixedwidth(ibuf, buf, offsetx, offsety1 + 54, 8);
1232
1233 if (num != -1) {
1234 int ucitemnum = 0x10000 - num;
1235 if (!num) ucitemnum = 0xfe9c;
1236 snprintf(buf, 512, "Usecode item %4x function %x", ucitemnum, actor->get_usecode());
1237 font->paint_text_fixedwidth(ibuf, buf, offsetx, offsety1 + 63, 8);
1238 } else {
1239 snprintf(buf, 512, "Usecode function %x", actor->get_usecode());
1240 font->paint_text_fixedwidth(ibuf, buf, offsetx, offsety1 + 63, 8);
1241 }
1242
1243 if (actor->get_flag(Obj_flags::charmed))
1244 snprintf(buf, 512, "Alignment: %s (orig: %s)", alignments[actor->get_effective_alignment()], alignments[actor->get_alignment()]);
1245 else
1246 snprintf(buf, 512, "Alignment: %s", alignments[actor->get_alignment()]);
1247 font->paint_text_fixedwidth(ibuf, buf, offsetx, offsety1 + 72, 8);
1248
1249 if (actor->get_polymorph() != -1) {
1250 snprintf(buf, 512, "Polymorphed from %04i", actor->get_polymorph());
1251 font->paint_text_fixedwidth(ibuf, buf, offsetx, offsety1 + 81, 8);
1252 }
1253 } else {
1254 snprintf(buf, 512, "NPC %i - Invalid NPC!", num);
1255 font->paint_text_fixedwidth(ibuf, buf, offsetx, 0, 8);
1256 }
1257 }
1258
NPCMenu(Actor * actor,int & num)1259 void CheatScreen::NPCMenu(Actor *actor, int &num) {
1260 ignore_unused_variable_warning(num);
1261 #ifdef __IPHONEOS__
1262 const int offsetx = 15;
1263 const int offsety1 = 74;
1264 const int offsetx2 = 15;
1265 const int offsety2 = 72;
1266 const int offsetx3 = 175;
1267 const int offsety3 = 63;
1268 const int offsety4 = 72;
1269 #else
1270 const int offsetx = 0;
1271 const int offsety1 = 0;
1272 const int offsetx2 = 0;
1273 const int offsety2 = maxy - 36;
1274 const int offsetx3 = offsetx + 160;
1275 const int offsety3 = maxy - 45;
1276 const int offsety4 = maxy - 36;
1277 #endif
1278 // Left Column
1279
1280 if (actor) {
1281 // Business Activity
1282 font->paint_text_fixedwidth(ibuf, "[B]usiness Activity", offsetx, maxy - offsety1 - 99, 8);
1283
1284 // Change Shape
1285 font->paint_text_fixedwidth(ibuf, "[C]hange Shape", offsetx, maxy - offsety1 - 90, 8);
1286
1287 // XP
1288 font->paint_text_fixedwidth(ibuf, "[E]xperience", offsetx, maxy - offsety1 - 81, 8);
1289
1290 // NPC Flags
1291 font->paint_text_fixedwidth(ibuf, "[N]pc Flags", offsetx, maxy - offsety1 - 72, 8);
1292
1293 // Name
1294 font->paint_text_fixedwidth(ibuf, "[1] Name", offsetx, maxy - offsety1 - 63, 8);
1295 }
1296
1297 // eXit
1298 font->paint_text_fixedwidth(ibuf, "[X]it", offsetx2, offsety2, 8);
1299
1300 // Right Column
1301
1302 if (actor) {
1303 // Stats
1304 font->paint_text_fixedwidth(ibuf, "[S]tats", offsetx + 160, maxy - offsety1 - 99, 8);
1305
1306 // Training Points
1307 font->paint_text_fixedwidth(ibuf, "[2] Training Points", offsetx + 160, maxy - offsety1 - 90, 8);
1308
1309 // Teleport
1310 font->paint_text_fixedwidth(ibuf, "[T]eleport", offsetx + 160, maxy - offsety1 - 81, 8);
1311
1312 // Change NPC
1313 font->paint_text_fixedwidth(ibuf, "[*] Change NPC", offsetx3, offsety3, 8);
1314 }
1315
1316 // Change NPC
1317 font->paint_text_fixedwidth(ibuf, "[+-] Scroll NPCs", offsetx3, offsety4, 8);
1318 }
1319
NPCActivate(char * input,int & command,Cheat_Prompt & mode,Actor * actor,int & num)1320 void CheatScreen::NPCActivate(char *input, int &command, Cheat_Prompt &mode, Actor *actor, int &num) {
1321 int i = std::atoi(input);
1322 int nshapes =
1323 Shape_manager::get_instance()->get_shapes().get_num_shapes();
1324
1325 mode = CP_Command;
1326
1327 if (command == '-') {
1328 num--;
1329 if (num < 0)
1330 num = 0;
1331 else if (num >= 356 && num <= 359)
1332 num = 355;
1333 } else if (command == '+') {
1334 num++;
1335 if (num >= 356 && num <= 359)
1336 num = 360;
1337 } else if (command == '*') { // Change NPC
1338 if (i < -1 || (i >= 356 && i <= 359)) mode = CP_InvalidNPC;
1339 else if (i == -1) mode = CP_Canceled;
1340 else if (input[0]) num = i;
1341 } else if (actor) switch (command) {
1342 case 'b': // Business
1343 BusinessLoop(actor);
1344 break;
1345
1346 case 'n': // Npc flags
1347 FlagLoop(actor);
1348 break;
1349
1350 case 's': // stats
1351 StatLoop(actor);
1352 break;
1353
1354 case 't': // Teleport
1355 Game_window::get_instance()->teleport_party(actor->get_tile(),
1356 false, actor->get_map_num());
1357 break;
1358
1359 case 'e': // Experience
1360 if (i < 0) mode = CP_Canceled;
1361 else actor->set_property(Actor::exp, i);
1362 break;
1363
1364 case '2': // Training Points
1365 if (i < 0) mode = CP_Canceled;
1366 else actor->set_property(Actor::training, i);
1367 break;
1368
1369 case 'c': // Change shape
1370 if (input[0] == 'b') { // Browser
1371 int n;
1372 if (!cheat.get_browser_shape(i, n)) {
1373 mode = CP_WrongShapeFile;
1374 break;
1375 }
1376 }
1377
1378 if (i == -1) mode = CP_Canceled;
1379 else if (i < 0) mode = CP_InvalidShape;
1380 else if (i >= nshapes) mode = CP_InvalidShape;
1381 else if (input[0] && (input[0] != '-' || input[1])) {
1382 if (actor->get_npc_num() != 0)
1383 actor->set_shape(i);
1384 else
1385 actor->set_polymorph(i);
1386 mode = CP_ShapeSet;
1387 }
1388 break;
1389
1390 case '1': // Name
1391 if (!std::strlen(input)) mode = CP_Canceled;
1392 else {
1393 actor->set_npc_name(input);
1394 mode = CP_NameSet;
1395 }
1396 break;
1397
1398 default:
1399 break;
1400 }
1401 for (i = 0; i < 17; i++) input[i] = 0;
1402 command = 0;
1403 }
1404
1405 // Checks the input
NPCCheck(char * input,int & command,Cheat_Prompt & mode,bool & activate,Actor * actor,int & num)1406 bool CheatScreen::NPCCheck(char *input, int &command, Cheat_Prompt &mode, bool &activate, Actor *actor, int &num) {
1407 ignore_unused_variable_warning(num);
1408 switch (command) {
1409 // Simple commands
1410 case 'a': // Attack mode
1411 case 'b': // BUsiness
1412 case 'n': // Npc flags
1413 case 'd': // pop weapon
1414 case 's': // stats
1415 case 'z': // Target
1416 case 't': // Teleport
1417 input[0] = command;
1418 if (!actor) mode = CP_InvalidCom;
1419 else activate = true;
1420 break;
1421
1422 // Value entries
1423 case 'e': // Experience
1424 case '2': // Training Points
1425 if (!actor) mode = CP_InvalidCom;
1426 else mode = CP_EnterValue;
1427 break;
1428
1429 // Change shape
1430 case 'c':
1431 if (!actor) mode = CP_InvalidCom;
1432 else mode = CP_Shape;
1433 break;
1434
1435 // Name
1436 case '1':
1437 if (!actor) mode = CP_InvalidCom;
1438 else mode = CP_Name;
1439 break;
1440
1441 // - NPC
1442 case SDLK_KP_MINUS:
1443 case '-':
1444 command = '-';
1445 input[0] = command;
1446 activate = true;
1447 break;
1448
1449 // + NPC
1450 case SDLK_KP_PLUS:
1451 case '=':
1452 command = '+';
1453 input[0] = command;
1454 activate = true;
1455 break;
1456
1457 // * Change NPC
1458 case SDLK_KP_MULTIPLY:
1459 case '8':
1460 command = '*';
1461 input[0] = 0;
1462 mode = CP_ChooseNPC;
1463 break;
1464
1465 // X and Escape leave
1466 case SDLK_ESCAPE:
1467 case 'x':
1468 input[0] = command;
1469 return false;
1470
1471 default:
1472 mode = CP_InvalidCom;
1473 input[0] = command;
1474 command = 0;
1475 break;
1476 }
1477
1478 return true;
1479 }
1480
1481 //
1482 // NPC Flags
1483 //
1484
FlagLoop(Actor * actor)1485 void CheatScreen::FlagLoop(Actor *actor) {
1486 #ifndef __IPHONEOS__
1487 int num = actor->get_npc_num();
1488 #endif
1489 bool looping = true;
1490
1491 // This is for the prompt message
1492 Cheat_Prompt mode = CP_Command;
1493
1494 // This is the command
1495 char input[17];
1496 int i;
1497 int command;
1498 bool activate = false;
1499
1500 for (i = 0; i < 17; i++) input[i] = 0;
1501
1502 while (looping) {
1503 gwin->clear_screen();
1504
1505 #ifndef __IPHONEOS__
1506 // First the display
1507 NPCDisplay(actor, num);
1508 #endif
1509
1510 // Now the Menu Column
1511 FlagMenu(actor);
1512
1513 // Finally the Prompt...
1514 SharedPrompt(input, mode);
1515
1516 // Draw it!
1517 gwin->get_win()->show();
1518
1519 // Check to see if we need to change menus
1520 if (activate) {
1521 FlagActivate(input, command, mode, actor);
1522 activate = false;
1523 continue;
1524 }
1525
1526 if (SharedInput(input, 17, command, mode, activate))
1527 looping = FlagCheck(input, command, mode, activate, actor);
1528 }
1529 }
1530
FlagMenu(Actor * actor)1531 void CheatScreen::FlagMenu(Actor *actor) {
1532 char buf[512];
1533 #ifdef __IPHONEOS__
1534 const int offsetx = 10;
1535 const int offsetx1 = 6;
1536 const int offsety1 = 92;
1537 #else
1538 const int offsetx = 0;
1539 const int offsetx1 = 0;
1540 const int offsety1 = 0;
1541 #endif
1542
1543 // Left Column
1544
1545 // Asleep
1546 snprintf(buf, 512, "[A] Asleep.%c", actor->get_flag(Obj_flags::asleep) ? 'Y' : 'N');
1547 font->paint_text_fixedwidth(ibuf, buf, offsetx, maxy - offsety1 - 108, 8);
1548
1549 // Charmed
1550 snprintf(buf, 512, "[B] Charmd.%c", actor->get_flag(Obj_flags::charmed) ? 'Y' : 'N');
1551 font->paint_text_fixedwidth(ibuf, buf, offsetx, maxy - offsety1 - 99, 8);
1552
1553 // Cursed
1554 snprintf(buf, 512, "[C] Cursed.%c", actor->get_flag(Obj_flags::cursed) ? 'Y' : 'N');
1555 font->paint_text_fixedwidth(ibuf, buf, offsetx, maxy - offsety1 - 90, 8);
1556
1557 // Paralyzed
1558 snprintf(buf, 512, "[D] Prlyzd.%c", actor->get_flag(Obj_flags::paralyzed) ? 'Y' : 'N');
1559 font->paint_text_fixedwidth(ibuf, buf, offsetx, maxy - offsety1 - 81, 8);
1560
1561 // Poisoned
1562 snprintf(buf, 512, "[E] Poisnd.%c", actor->get_flag(Obj_flags::poisoned) ? 'Y' : 'N');
1563 font->paint_text_fixedwidth(ibuf, buf, offsetx, maxy - offsety1 - 72, 8);
1564
1565 // Protected
1566 snprintf(buf, 512, "[F] Prtctd.%c", actor->get_flag(Obj_flags::protection) ? 'Y' : 'N');
1567 font->paint_text_fixedwidth(ibuf, buf, offsetx, maxy - offsety1 - 63, 8);
1568
1569 // Advanced Editor
1570 font->paint_text_fixedwidth(ibuf, "[*] Advanced", offsetx, maxy - offsety1 - 45, 8);
1571
1572 // Exit
1573 font->paint_text_fixedwidth(ibuf, "[X]it", offsetx, maxy - offsety1 - 36, 8);
1574
1575
1576 // Center Column
1577
1578 // Party
1579 snprintf(buf, 512, "[I] Party..%c", actor->get_flag(Obj_flags::in_party) ? 'Y' : 'N');
1580 font->paint_text_fixedwidth(ibuf, buf, offsetx1 + 104, maxy - offsety1 - 108, 8);
1581
1582 // Invisible
1583 snprintf(buf, 512, "[J] Invsbl.%c", actor->get_flag(Obj_flags::invisible) ? 'Y' : 'N');
1584 font->paint_text_fixedwidth(ibuf, buf, offsetx1 + 104, maxy - offsety1 - 99, 8);
1585
1586 // Fly
1587 snprintf(buf, 512, "[K] Fly....%c", actor->get_type_flag(Actor::tf_fly) ? 'Y' : 'N');
1588 font->paint_text_fixedwidth(ibuf, buf, offsetx1 + 104, maxy - offsety1 - 90, 8);
1589
1590 // Walk
1591 snprintf(buf, 512, "[L] Walk...%c", actor->get_type_flag(Actor::tf_walk) ? 'Y' : 'N');
1592 font->paint_text_fixedwidth(ibuf, buf, offsetx1 + 104, maxy - offsety1 - 81, 8);
1593
1594 // Swim
1595 snprintf(buf, 512, "[M] Swim...%c", actor->get_type_flag(Actor::tf_swim) ? 'Y' : 'N');
1596 font->paint_text_fixedwidth(ibuf, buf, offsetx1 + 104, maxy - offsety1 - 72, 8);
1597
1598 // Ethereal
1599 snprintf(buf, 512, "[N] Ethrel.%c", actor->get_type_flag(Actor::tf_ethereal) ? 'Y' : 'N');
1600 font->paint_text_fixedwidth(ibuf, buf, offsetx1 + 104, maxy - offsety1 - 63, 8);
1601
1602 // Protectee
1603 snprintf(buf, 512, "[O] Prtcee.%c", '?');
1604 font->paint_text_fixedwidth(ibuf, buf, offsetx1 + 104, maxy - offsety1 - 54, 8);
1605
1606 // Conjured
1607 snprintf(buf, 512, "[P] Conjrd.%c", actor->get_type_flag(Actor::tf_conjured) ? 'Y' : 'N');
1608 font->paint_text_fixedwidth(ibuf, buf, offsetx1 + 104, maxy - offsety1 - 45, 8);
1609
1610 // Tournament (Original is SI only -- allowing for BG in Exult)
1611 snprintf(buf, 512, "[3] Tourna.%c", actor->get_flag(
1612 Obj_flags::tournament) ? 'Y' : 'N');
1613 font->paint_text_fixedwidth(ibuf, buf, offsetx1 + 104, maxy - offsety1 - 36, 8);
1614
1615 // Naked (AV ONLY)
1616 if (!actor->get_npc_num()) {
1617 snprintf(buf, 512, "[7] Naked..%c", actor->get_flag(Obj_flags::naked) ? 'Y' : 'N');
1618 font->paint_text_fixedwidth(ibuf, buf, offsetx1 + 104, maxy - offsety1 - 27, 8);
1619 }
1620
1621
1622 // Right Column
1623
1624 // Summoned
1625 snprintf(buf, 512, "[Q] Summnd.%c", actor->get_type_flag(Actor::tf_summonned) ? 'Y' : 'N');
1626 font->paint_text_fixedwidth(ibuf, buf, offsetx1 + 208, maxy - offsety1 - 108, 8);
1627
1628 // Bleeding
1629 snprintf(buf, 512, "[R] Bleedn.%c", actor->get_type_flag(Actor::tf_bleeding) ? 'Y' : 'N');
1630 font->paint_text_fixedwidth(ibuf, buf, offsetx1 + 208, maxy - offsety1 - 99, 8);
1631
1632 if (!actor->get_npc_num()) { // Avatar
1633 // Sex
1634 snprintf(buf, 512, "[S] Sex....%c", actor->get_type_flag(Actor::tf_sex) ? 'F' : 'M');
1635 font->paint_text_fixedwidth(ibuf, buf, offsetx1 + 208, maxy - offsety1 - 90, 8);
1636
1637 // Skin
1638 snprintf(buf, 512, "[1] Skin...%d", actor->get_skin_color());
1639 font->paint_text_fixedwidth(ibuf, buf, offsetx1 + 208, maxy - offsety1 - 81, 8);
1640
1641 // Read
1642 snprintf(buf, 512, "[4] Read...%c", actor->get_flag(Obj_flags::read) ? 'Y' : 'N');
1643 font->paint_text_fixedwidth(ibuf, buf, offsetx1 + 208, maxy - offsety1 - 72, 8);
1644 } else { // Not Avatar
1645 // Met
1646 snprintf(buf, 512, "[T] Met....%c", actor->get_flag(Obj_flags::met) ? 'Y' : 'N');
1647 font->paint_text_fixedwidth(ibuf, buf, offsetx1 + 208, maxy - offsety1 - 90, 8);
1648
1649 // NoCast
1650 snprintf(buf, 512, "[U] NoCast.%c", actor->get_flag(
1651 Obj_flags::no_spell_casting) ? 'Y' : 'N');
1652 font->paint_text_fixedwidth(ibuf, buf, offsetx1 + 208, maxy - offsety1 - 81, 8);
1653
1654 // ID
1655 snprintf(buf, 512, "[V] ID#:%02i", actor->get_ident());
1656 font->paint_text_fixedwidth(ibuf, buf, offsetx1 + 208, maxy - offsety1 - 72, 8);
1657 }
1658
1659 // Freeze
1660 snprintf(buf, 512, "[W] Freeze.%c", actor->get_flag(
1661 Obj_flags::freeze) ? 'Y' : 'N');
1662 font->paint_text_fixedwidth(ibuf, buf, offsetx1 + 208, maxy - offsety1 - 63, 8);
1663
1664 // Party
1665 if (actor->is_in_party()) {
1666 // Temp
1667 snprintf(buf, 512, "[Y] Temp: %02i",
1668 actor->get_temperature());
1669 font->paint_text_fixedwidth(ibuf, buf, offsetx1 + 208, maxy - offsety1 - 54, 8);
1670
1671 // Conjured
1672 snprintf(buf, 512, "Warmth: %04i",
1673 actor->figure_warmth());
1674 font->paint_text_fixedwidth(ibuf, buf, offsetx1 + 208, maxy - offsety1 - 45, 8);
1675 }
1676
1677 // Polymorph
1678 snprintf(buf, 512, "[2] Polymo.%c", actor->get_flag(Obj_flags::polymorph) ? 'Y' : 'N');
1679 font->paint_text_fixedwidth(ibuf, buf, offsetx1 + 208, maxy - offsety1 - 36, 8);
1680
1681 // Patra (AV SI ONLY)
1682 if (!actor->get_npc_num()) {
1683 snprintf(buf, 512, "[5] Petra..%c", actor->get_flag(Obj_flags::petra) ? 'Y' : 'N');
1684 font->paint_text_fixedwidth(ibuf, buf, offsetx1 + 208, maxy - offsety1 - 27, 8);
1685 }
1686
1687 }
1688
FlagActivate(char * input,int & command,Cheat_Prompt & mode,Actor * actor)1689 void CheatScreen::FlagActivate(char *input, int &command, Cheat_Prompt &mode, Actor *actor) {
1690 int i = std::atoi(input);
1691 int nshapes =
1692 Shape_manager::get_instance()->get_shapes().get_num_shapes();
1693
1694 mode = CP_Command;
1695 switch (command) {
1696 // Everyone
1697
1698 // Toggles
1699 case 'a': // Asleep
1700 if (actor->get_flag(Obj_flags::asleep))
1701 actor->clear_flag(Obj_flags::asleep);
1702 else
1703 actor->set_flag(Obj_flags::asleep);
1704 break;
1705
1706 case 'b': // Charmed
1707 if (actor->get_flag(Obj_flags::charmed))
1708 actor->clear_flag(Obj_flags::charmed);
1709 else
1710 actor->set_flag(Obj_flags::charmed);
1711 break;
1712
1713 case 'c': // Cursed
1714 if (actor->get_flag(Obj_flags::cursed))
1715 actor->clear_flag(Obj_flags::cursed);
1716 else
1717 actor->set_flag(Obj_flags::cursed);
1718 break;
1719
1720 case 'd': // Paralyzed
1721 if (actor->get_flag(Obj_flags::paralyzed))
1722 actor->clear_flag(Obj_flags::paralyzed);
1723 else
1724 actor->set_flag(Obj_flags::paralyzed);
1725 break;
1726
1727 case 'e': // Poisoned
1728 if (actor->get_flag(Obj_flags::poisoned))
1729 actor->clear_flag(Obj_flags::poisoned);
1730 else
1731 actor->set_flag(Obj_flags::poisoned);
1732 break;
1733
1734 case 'f': // Protected
1735 if (actor->get_flag(Obj_flags::protection))
1736 actor->clear_flag(Obj_flags::protection);
1737 else
1738 actor->set_flag(Obj_flags::protection);
1739 break;
1740
1741 case 'j': // Invisible
1742 if (actor->get_flag(Obj_flags::invisible))
1743 actor->clear_flag(Obj_flags::invisible);
1744 else
1745 actor->set_flag(Obj_flags::invisible);
1746 pal.apply();
1747 break;
1748
1749 case 'k': // Fly
1750 if (actor->get_type_flag(Actor::tf_fly))
1751 actor->clear_type_flag(Actor::tf_fly);
1752 else
1753 actor->set_type_flag(Actor::tf_fly);
1754 break;
1755
1756 case 'l': // Walk
1757 if (actor->get_type_flag(Actor::tf_walk))
1758 actor->clear_type_flag(Actor::tf_walk);
1759 else
1760 actor->set_type_flag(Actor::tf_walk);
1761 break;
1762
1763 case 'm': // Swim
1764 if (actor->get_type_flag(Actor::tf_swim))
1765 actor->clear_type_flag(Actor::tf_swim);
1766 else
1767 actor->set_type_flag(Actor::tf_swim);
1768 break;
1769
1770 case 'n': // Ethrel
1771 if (actor->get_type_flag(Actor::tf_ethereal))
1772 actor->clear_type_flag(Actor::tf_ethereal);
1773 else
1774 actor->set_type_flag(Actor::tf_ethereal);
1775 break;
1776
1777 case 'p': // Conjured
1778 if (actor->get_type_flag(Actor::tf_conjured))
1779 actor->clear_type_flag(Actor::tf_conjured);
1780 else
1781 actor->set_type_flag(Actor::tf_conjured);
1782 break;
1783
1784 case 'q': // Summoned
1785 if (actor->get_type_flag(Actor::tf_summonned))
1786 actor->clear_type_flag(Actor::tf_summonned);
1787 else
1788 actor->set_type_flag(Actor::tf_summonned);
1789 break;
1790
1791 case 'r': // Bleeding
1792 if (actor->get_type_flag(Actor::tf_bleeding))
1793 actor->clear_type_flag(Actor::tf_bleeding);
1794 else
1795 actor->set_type_flag(Actor::tf_bleeding);
1796 break;
1797
1798 case 's': // Sex
1799 if (actor->get_type_flag(Actor::tf_sex))
1800 actor->clear_type_flag(Actor::tf_sex);
1801 else
1802 actor->set_type_flag(Actor::tf_sex);
1803 break;
1804
1805 case '4': // Read
1806 if (actor->get_flag(Obj_flags::read))
1807 actor->clear_flag(Obj_flags::read);
1808 else
1809 actor->set_flag(Obj_flags::read);
1810 break;
1811
1812 case '5': // Petra
1813 if (actor->get_flag(Obj_flags::petra))
1814 actor->clear_flag(Obj_flags::petra);
1815 else
1816 actor->set_flag(Obj_flags::petra);
1817 break;
1818
1819 case '7': // Naked
1820 if (actor->get_flag(Obj_flags::naked))
1821 actor->clear_flag(Obj_flags::naked);
1822 else
1823 actor->set_flag(Obj_flags::naked);
1824 break;
1825
1826 case 't': // Met
1827 if (actor->get_flag(Obj_flags::met))
1828 actor->clear_flag(Obj_flags::met);
1829 else
1830 actor->set_flag(Obj_flags::met);
1831 break;
1832
1833 case 'u': // No Cast
1834 if (actor->get_flag(Obj_flags::no_spell_casting))
1835 actor->clear_flag(Obj_flags::no_spell_casting);
1836 else
1837 actor->set_flag(Obj_flags::no_spell_casting);
1838 break;
1839
1840 case 'z': // Zombie
1841 if (actor->get_flag(Obj_flags::si_zombie))
1842 actor->clear_flag(Obj_flags::si_zombie);
1843 else
1844 actor->set_flag(Obj_flags::si_zombie);
1845 break;
1846
1847 case 'w': // Freeze
1848 if (actor->get_flag(Obj_flags::freeze))
1849 actor->clear_flag(Obj_flags::freeze);
1850 else
1851 actor->set_flag(Obj_flags::freeze);
1852 break;
1853
1854 case 'i': // Party
1855 if (actor->get_flag(Obj_flags::in_party)) {
1856 gwin->get_party_man()->remove_from_party(actor);
1857 gwin->revert_schedules(actor);
1858 // Just to be sure.
1859 actor->clear_flag(Obj_flags::in_party);
1860 } else if (gwin->get_party_man()->add_to_party(actor))
1861 actor->set_schedule_type(Schedule::follow_avatar);
1862 break;
1863
1864 case 'o': // Protectee
1865 break;
1866
1867 // Value
1868 case 'v': // ID
1869 if (i < -1) mode = CP_InvalidValue;
1870 else if (i > 63) mode = CP_InvalidValue;
1871 else if (i == -1 || !input[0]) mode = CP_Canceled;
1872 else actor->set_ident(i);
1873 break;
1874
1875 case '1': // Skin color
1876 actor->set_skin_color(
1877 Shapeinfo_lookup::GetNextSkin(
1878 actor->get_skin_color(), actor->get_type_flag(Actor::tf_sex),
1879 Shape_manager::get_instance()->have_si_shapes()));
1880 break;
1881
1882 case '3': // Tournament
1883 if (actor->get_flag(Obj_flags::tournament))
1884 actor->clear_flag(Obj_flags::tournament);
1885 else
1886 actor->set_flag(Obj_flags::tournament);
1887 break;
1888
1889 case 'y': // Warmth
1890 if (i < -1) mode = CP_InvalidValue;
1891 else if (i > 63) mode = CP_InvalidValue;
1892 else if (i == -1 || !input[0]) mode = CP_Canceled;
1893 else actor->set_temperature(i);
1894 break;
1895
1896 case '2': // Polymorph
1897
1898 // Clear polymorph
1899 if (actor->get_polymorph() != -1) {
1900 actor->set_polymorph(actor->get_polymorph());
1901 break;
1902 }
1903
1904 if (input[0] == 'b') { // Browser
1905 int n;
1906 if (!cheat.get_browser_shape(i, n)) {
1907 mode = CP_WrongShapeFile;
1908 break;
1909 }
1910 }
1911
1912 if (i == -1) mode = CP_Canceled;
1913 else if (i < 0) mode = CP_InvalidShape;
1914 else if (i >= nshapes) mode = CP_InvalidShape;
1915 else if (input[0] && (input[0] != '-' || input[1])) {
1916 actor->set_polymorph(i);
1917 mode = CP_ShapeSet;
1918 }
1919
1920 break;
1921
1922 // Advanced Numeric Flag Editor
1923 case '*':
1924 if (i < -1) mode = CP_InvalidValue;
1925 else if (i > 63) mode = CP_InvalidValue;
1926 else if (i == -1 || !input[0]) mode = CP_Canceled;
1927 else mode = AdvancedFlagLoop(i, actor);
1928 break;
1929
1930 default:
1931 break;
1932 }
1933 for (i = 0; i < 17; i++) input[i] = 0;
1934 command = 0;
1935 }
1936
1937 // Checks the input
FlagCheck(char * input,int & command,Cheat_Prompt & mode,bool & activate,Actor * actor)1938 bool CheatScreen::FlagCheck(char *input, int &command, Cheat_Prompt &mode, bool &activate, Actor *actor) {
1939 switch (command) {
1940 // Everyone
1941
1942 // Toggles
1943 case 'a': // Asleep
1944 case 'b': // Charmed
1945 case 'c': // Cursed
1946 case 'd': // Paralyzed
1947 case 'e': // Poisoned
1948 case 'f': // Protected
1949 case 'i': // Party
1950 case 'j': // Invisible
1951 case 'k': // Fly
1952 case 'l': // Walk
1953 case 'm': // Swim
1954 case 'n': // Ethrel
1955 case 'o': // Protectee
1956 case 'p': // Conjured
1957 case 'q': // Summoned
1958 case 'r': // Bleedin
1959 case 'w': // Freeze
1960 case '3': // Tournament
1961 activate = true;
1962 input[0] = command;
1963 break;
1964
1965 // Value
1966 case '2': // Polymorph
1967 if (actor->get_polymorph() == -1) {
1968 mode = CP_Shape;
1969 input[0] = 0;
1970 } else {
1971 activate = true;
1972 input[0] = command;
1973 }
1974 break;
1975
1976
1977 // Party Only
1978
1979 // Value
1980 case 'y': // Temp
1981 if (!actor->is_in_party()) command = 0;
1982 else mode = CP_TempNum;
1983 input[0] = 0;
1984 break;
1985
1986
1987 // Avatar Only
1988
1989 // Toggles
1990 case 's': // Sex
1991 case '4': // Read
1992 if (actor->get_npc_num()) command = 0;
1993 else activate = true;
1994 input[0] = command;
1995 break;
1996
1997 // Toggles SI
1998 case '5': // Petra
1999 case '7': // Naked
2000 if (actor->get_npc_num()) command = 0;
2001 else activate = true;
2002 input[0] = command;
2003 break;
2004
2005 // Value SI
2006 case '1': // Skin
2007 if (actor->get_npc_num()) command = 0;
2008 else activate = true;
2009 input[0] = command;
2010 break;
2011
2012
2013 // Everyone but avatar
2014
2015 // Toggles
2016 case 't': // Met
2017 case 'u': // No Cast
2018 case 'z': // Zombie
2019 if (!actor->get_npc_num()) command = 0;
2020 else activate = true;
2021 input[0] = command;
2022 break;
2023
2024 // Value
2025 case 'v': // ID
2026 if (!actor->get_npc_num()) command = 0;
2027 else mode = CP_EnterValue;
2028 input[0] = 0;
2029 break;
2030
2031 // NPC Flag Editor
2032
2033 case SDLK_KP_MULTIPLY:
2034 case '8':
2035 command = '*';
2036 input[0] = 0;
2037 mode = CP_NFlagNum;
2038 break;
2039
2040
2041 // X and Escape leave
2042 case SDLK_ESCAPE:
2043 case 'x':
2044 input[0] = command;
2045 return false;
2046
2047 // Unknown
2048 default:
2049 command = 0;
2050 break;
2051 }
2052
2053 return true;
2054 }
2055
2056 //
2057 // Business Schedules
2058 //
2059
BusinessLoop(Actor * actor)2060 void CheatScreen::BusinessLoop(Actor *actor) {
2061 bool looping = true;
2062
2063 // This is for the prompt message
2064 Cheat_Prompt mode = CP_Command;
2065
2066 // This is the command
2067 char input[17];
2068 int i;
2069 int command;
2070 bool activate = false;
2071 int time = 0;
2072 int prev = 0;
2073
2074 for (i = 0; i < 17; i++) input[i] = 0;
2075
2076 while (looping) {
2077 gwin->clear_screen();
2078
2079 // First the display
2080 if (mode == CP_Activity)
2081 ActivityDisplay();
2082 else
2083 BusinessDisplay(actor);
2084
2085 // Now the Menu Column
2086 BusinessMenu(actor);
2087
2088 // Finally the Prompt...
2089 SharedPrompt(input, mode);
2090
2091 // Draw it!
2092 gwin->get_win()->show();
2093
2094 // Check to see if we need to change menus
2095 if (activate) {
2096 BusinessActivate(input, command, mode, actor, time, prev);
2097 activate = false;
2098 continue;
2099 }
2100
2101 if (SharedInput(input, 17, command, mode, activate))
2102 looping = BusinessCheck(input, command, mode, activate, actor, time);
2103 }
2104 }
2105
BusinessDisplay(Actor * actor)2106 void CheatScreen::BusinessDisplay(Actor *actor) {
2107 char buf[512];
2108 Tile_coord t = actor->get_tile();
2109 #ifdef __IPHONEOS__
2110 const int offsetx = 10;
2111 const int offsety1 = 20;
2112 const int offsetx2 = 161;
2113 const int offsety2 = 8;
2114 #else
2115 const int offsetx = 0;
2116 const int offsety1 = 0;
2117 const int offsetx2 = offsetx;
2118 const int offsety2 = 16;
2119 #endif
2120
2121 // Now the info
2122 std::string namestr = actor->get_npc_name();
2123 snprintf(buf, 512, "NPC %i - %s - Schedules:", actor->get_npc_num(), namestr.c_str());
2124 font->paint_text_fixedwidth(ibuf, buf, offsetx, 0, 8);
2125
2126 snprintf(buf, 512, "Loc (%04i, %04i, %02i)", t.tx, t.ty, t.tz);
2127 font->paint_text_fixedwidth(ibuf, buf, 0, 8, 8);
2128
2129 #ifdef __IPHONEOS__
2130 const char activity_msg[] = "-Act: %2i %s";
2131 #else
2132 const char activity_msg[] = "Current Activity: %2i - %s";
2133 #endif
2134 snprintf(buf, 512, activity_msg, actor->get_schedule_type(), schedules[actor->get_schedule_type()]);
2135 font->paint_text_fixedwidth(ibuf, buf, offsetx2, offsety2, 8);
2136
2137
2138 // Avatar can't have schedules
2139 if (actor->get_npc_num() > 0) {
2140 #ifndef __IPHONEOS__
2141 font->paint_text_fixedwidth(ibuf, "Schedules:", offsetx, 16, 8);
2142 #endif
2143
2144 Schedule_change *scheds;
2145 int num;
2146 int types[8] = { -1, -1, -1, -1, -1, -1, -1, -1};
2147 int x[8];
2148 int y[8];
2149
2150 actor->get_schedules(scheds, num);
2151
2152 for (int i = 0; i < num; i++) {
2153 int time = scheds[i].get_time();
2154 types[time] = scheds[i].get_type();
2155 Tile_coord tile = scheds[i].get_pos();
2156 x[time] = tile.tx;
2157 y[time] = tile.ty;
2158 }
2159
2160 font->paint_text_fixedwidth(ibuf, "12 AM:", offsetx, 36 - offsety1, 8);
2161 font->paint_text_fixedwidth(ibuf, " 3 AM:", offsetx, 44 - offsety1, 8);
2162 font->paint_text_fixedwidth(ibuf, " 6 AM:", offsetx, 52 - offsety1, 8);
2163 font->paint_text_fixedwidth(ibuf, " 9 AM:", offsetx, 60 - offsety1, 8);
2164 font->paint_text_fixedwidth(ibuf, "12 PM:", offsetx, 68 - offsety1, 8);
2165 font->paint_text_fixedwidth(ibuf, " 3 PM:", offsetx, 76 - offsety1, 8);
2166 font->paint_text_fixedwidth(ibuf, " 6 PM:", offsetx, 84 - offsety1, 8);
2167 font->paint_text_fixedwidth(ibuf, " 9 PM:", offsetx, 92 - offsety1, 8);
2168
2169 for (int i = 0; i < 8; i++) if (types[i] != -1) {
2170 snprintf(buf, 512, "%2i (%4i,%4i) - %s", types[i], x[i], y[i], schedules[types[i]]);
2171 font->paint_text_fixedwidth(ibuf, buf, offsetx + 56, (36 - offsety1) + i * 8, 8);
2172 }
2173 }
2174 }
2175
BusinessMenu(Actor * actor)2176 void CheatScreen::BusinessMenu(Actor *actor) {
2177 // Left Column
2178 #ifdef __IPHONEOS__
2179 const int offsetx = 10;
2180 #else
2181 const int offsetx = 0;
2182 #endif
2183 // Might break on monster npcs?
2184 if (actor->get_npc_num() > 0) {
2185 font->paint_text_fixedwidth(ibuf, "12 AM: [A] Set [I] Location [1] Clear", offsetx, maxy - 96, 8);
2186 font->paint_text_fixedwidth(ibuf, " 3 AM: [B] Set [J] Location [2] Clear", offsetx, maxy - 88, 8);
2187 font->paint_text_fixedwidth(ibuf, " 6 AM: [C] Set [K] Location [3] Clear", offsetx, maxy - 80, 8);
2188 font->paint_text_fixedwidth(ibuf, " 9 AM: [D] Set [L] Location [4] Clear", offsetx, maxy - 72, 8);
2189 font->paint_text_fixedwidth(ibuf, "12 PM: [E] Set [M] Location [5] Clear", offsetx, maxy - 64, 8);
2190 font->paint_text_fixedwidth(ibuf, " 3 PM: [F] Set [N] Location [6] Clear", offsetx, maxy - 56, 8);
2191 font->paint_text_fixedwidth(ibuf, " 6 PM: [G] Set [O] Location [7] Clear", offsetx, maxy - 48, 8);
2192 font->paint_text_fixedwidth(ibuf, " 9 PM: [H] Set [P] Location [8] Clear", offsetx, maxy - 40, 8);
2193
2194 font->paint_text_fixedwidth(ibuf, "[S]et Current Activity [X]it [R]evert", offsetx, maxy - 30, 8);
2195 } else
2196 font->paint_text_fixedwidth(ibuf, "[S]et Current Activity [X]it", offsetx, maxy - 30, 8);
2197 }
2198
BusinessActivate(char * input,int & command,Cheat_Prompt & mode,Actor * actor,int & time,int & prev)2199 void CheatScreen::BusinessActivate(char *input, int &command, Cheat_Prompt &mode, Actor *actor, int &time, int &prev) {
2200 int i = std::atoi(input);
2201
2202 mode = CP_Command;
2203 int old = command;
2204 command = 0;
2205 switch (old) {
2206 case 'a': // Set Activity
2207 if (i < -1 || i > 31) mode = CP_InvalidValue;
2208 else if (i == -1) mode = CP_Canceled;
2209 else if (!input[0]) {
2210 mode = CP_Activity;
2211 command = 'a';
2212 } else {
2213 actor->set_schedule_time_type(time, i);
2214 }
2215 break;
2216
2217 case 'i': // X Coord
2218 if (i < -1 || i > c_num_tiles) mode = CP_InvalidValue;
2219 else if (i == -1) mode = CP_Canceled;
2220 else if (!input[0]) {
2221 mode = CP_XCoord;
2222 command = 'i';
2223 } else {
2224 prev = i;
2225 mode = CP_YCoord;
2226 command = 'j';
2227 }
2228 break;
2229
2230 case 'j': // Y Coord
2231 if (i < -1 || i > c_num_tiles) mode = CP_InvalidValue;
2232 else if (i == -1) mode = CP_Canceled;
2233 else if (!input[0]) {
2234 mode = CP_YCoord;
2235 command = 'j';
2236 } else {
2237 actor->set_schedule_time_location(time, prev, i);
2238 }
2239 break;
2240
2241
2242 case '1': // Clear
2243 actor->remove_schedule(time);
2244 break;
2245
2246
2247 case 's': // Set Current
2248 if (i < -1 || i > 31) mode = CP_InvalidValue;
2249 else if (i == -1) mode = CP_Canceled;
2250 else if (!input[0]) {
2251 mode = CP_Activity;
2252 command = 's';
2253 } else {
2254 actor->set_schedule_type(i);
2255 }
2256 break;
2257
2258
2259 case 'r': // Revert
2260 Game_window::get_instance()->revert_schedules(actor);
2261 break;
2262
2263
2264 default:
2265 break;
2266 }
2267 for (i = 0; i < 17; i++) input[i] = 0;
2268 }
2269
2270 // Checks the input
BusinessCheck(char * input,int & command,Cheat_Prompt & mode,bool & activate,Actor * actor,int & time)2271 bool CheatScreen::BusinessCheck(char *input, int &command, Cheat_Prompt &mode, bool &activate, Actor *actor, int &time) {
2272 // Might break on monster npcs?
2273 if (actor->get_npc_num() > 0) switch (command) {
2274 case 'a':
2275 case 'b':
2276 case 'c':
2277 case 'd':
2278 case 'e':
2279 case 'f':
2280 case 'g':
2281 case 'h':
2282 time = command - 'a';
2283 command = 'a';
2284 mode = CP_Activity;
2285 return true;
2286
2287 case 'i':
2288 case 'j':
2289 case 'k':
2290 case 'l':
2291 case 'm':
2292 case 'n':
2293 case 'o':
2294 case 'p':
2295 time = command - 'i';
2296 command = 'i';
2297 mode = CP_XCoord;
2298 return true;
2299
2300 case '1':
2301 case '2':
2302 case '3':
2303 case '4':
2304 case '5':
2305 case '6':
2306 case '7':
2307 case '8':
2308 time = command - '1';
2309 command = '1';
2310 activate = true;
2311 return true;
2312
2313 case 'r':
2314 command = 'r';
2315 activate = true;
2316 return true;
2317
2318 default:
2319 break;
2320 }
2321
2322 switch (command) {
2323 // Set Current
2324 case 's':
2325 command = 's';
2326 input[0] = 0;
2327 mode = CP_Activity;
2328 break;
2329
2330 // X and Escape leave
2331 case SDLK_ESCAPE:
2332 case 'x':
2333 input[0] = command;
2334 return false;
2335
2336 // Unknown
2337 default:
2338 command = 0;
2339 mode = CP_InvalidCom;
2340 break;
2341 }
2342
2343 return true;
2344 }
2345
2346 //
2347 // NPC Stats
2348 //
2349
StatLoop(Actor * actor)2350 void CheatScreen::StatLoop(Actor *actor) {
2351 #ifndef __IPHONEOS__
2352 int num = actor->get_npc_num();
2353 #endif
2354 bool looping = true;
2355
2356 // This is for the prompt message
2357 Cheat_Prompt mode = CP_Command;
2358
2359 // This is the command
2360 char input[17];
2361 int i;
2362 int command;
2363 bool activate = false;
2364
2365 for (i = 0; i < 17; i++) input[i] = 0;
2366
2367 while (looping) {
2368 gwin->clear_screen();
2369
2370 #ifndef __IPHONEOS__
2371 // First the display
2372 NPCDisplay(actor, num);
2373 #endif
2374
2375 // Now the Menu Column
2376 StatMenu(actor);
2377
2378 // Finally the Prompt...
2379 SharedPrompt(input, mode);
2380
2381 // Draw it!
2382 gwin->get_win()->show();
2383
2384 // Check to see if we need to change menus
2385 if (activate) {
2386 StatActivate(input, command, mode, actor);
2387 activate = false;
2388 continue;
2389 }
2390
2391 if (SharedInput(input, 17, command, mode, activate))
2392 looping = StatCheck(input, command, mode, activate, actor);
2393 }
2394 }
2395
StatMenu(Actor * actor)2396 void CheatScreen::StatMenu(Actor *actor) {
2397 char buf[512];
2398 #ifdef __IPHONEOS__
2399 const int offsetx = 15;
2400 const int offsety1 = 92;
2401 #else
2402 const int offsetx = 0;
2403 const int offsety1 = 0;
2404 #endif
2405
2406 // Left Column
2407
2408 // Dexterity
2409 snprintf(buf, 512, "[D]exterity....%3i", actor->get_property(Actor::dexterity));
2410 font->paint_text_fixedwidth(ibuf, buf, offsetx, maxy - offsety1 - 108 , 8);
2411
2412 // Food Level
2413 snprintf(buf, 512, "[F]ood Level...%3i", actor->get_property(Actor::food_level));
2414 font->paint_text_fixedwidth(ibuf, buf, offsetx, maxy - offsety1 - 99, 8);
2415
2416 // Intelligence
2417 snprintf(buf, 512, "[I]ntellicence.%3i", actor->get_property(Actor::intelligence));
2418 font->paint_text_fixedwidth(ibuf, buf, offsetx, maxy - offsety1 - 90, 8);
2419
2420 // Strength
2421 snprintf(buf, 512, "[S]trength.....%3i", actor->get_property(Actor::strength));
2422 font->paint_text_fixedwidth(ibuf, buf, offsetx, maxy - offsety1 - 81, 8);
2423
2424 // Combat Skill
2425 snprintf(buf, 512, "[C]ombat Skill.%3i", actor->get_property(Actor::combat));
2426 font->paint_text_fixedwidth(ibuf, buf, offsetx, maxy - offsety1 - 72, 8);
2427
2428 // Hit Points
2429 snprintf(buf, 512, "[H]it Points...%3i", actor->get_property(Actor::health));
2430 font->paint_text_fixedwidth(ibuf, buf, offsetx, maxy - offsety1 - 63, 8);
2431
2432 // Magic
2433 // Magic Points
2434 snprintf(buf, 512, "[M]agic Points.%3i", actor->get_property(Actor::magic));
2435 font->paint_text_fixedwidth(ibuf, buf, offsetx, maxy - offsety1 - 54, 8);
2436
2437 // Mana
2438 snprintf(buf, 512, "[V]ana Level...%3i", actor->get_property(Actor::mana));
2439 font->paint_text_fixedwidth(ibuf, buf, offsetx, maxy - offsety1 - 45, 8);
2440
2441 // Exit
2442 font->paint_text_fixedwidth(ibuf, "[X]it", offsetx, maxy - offsety1 - 36, 8);
2443
2444 }
2445
StatActivate(char * input,int & command,Cheat_Prompt & mode,Actor * actor)2446 void CheatScreen::StatActivate(char *input, int &command, Cheat_Prompt &mode, Actor *actor) {
2447 int i = std::atoi(input);
2448 mode = CP_Command;
2449 // Enforce sane bounds.
2450 if (i > 60) {
2451 i = 60;
2452 } else if (i < 0 && command != 'h') {
2453 if (i == -1) { // canceled
2454 for (i = 0; i < 17; i++)
2455 input[i] = 0;
2456 command = 0;
2457 return;
2458 }
2459 i = 0;
2460 } else if (i < -50) {
2461 i = -50;
2462 }
2463
2464 switch (command) {
2465 case 'd': // Dexterity
2466 actor->set_property(Actor::dexterity, i);
2467 break;
2468
2469 case 'f': // Food Level
2470 actor->set_property(Actor::food_level, i);
2471 break;
2472
2473 case 'i': // Intelligence
2474 actor->set_property(Actor::intelligence, i);
2475 break;
2476
2477 case 's': // Strength
2478 actor->set_property(Actor::strength, i);
2479 break;
2480
2481 case 'c': // Combat Points
2482 actor->set_property(Actor::combat, i);
2483 break;
2484
2485 case 'h': // Hit Points
2486 actor->set_property(Actor::health, i);
2487 break;
2488
2489 case 'm': // Magic
2490 actor->set_property(Actor::magic, i);
2491 break;
2492
2493 case 'v': // [V]ana
2494 actor->set_property(Actor::mana, i);
2495 break;
2496
2497
2498 default:
2499 break;
2500 }
2501 for (i = 0; i < 17; i++) input[i] = 0;
2502 command = 0;
2503 }
2504
2505 // Checks the input
StatCheck(char * input,int & command,Cheat_Prompt & mode,bool & activate,Actor * actor)2506 bool CheatScreen::StatCheck(char *input, int &command, Cheat_Prompt &mode, bool &activate, Actor *actor) {
2507 ignore_unused_variable_warning(activate, actor);
2508 switch (command) {
2509 // Everyone
2510 case 'h': // Hit Points
2511 input[0] = 0;
2512 mode = CP_EnterValueNoCancel;
2513 break;
2514 case 'd': // Dexterity
2515 case 'f': // Food Level
2516 case 'i': // Intelligence
2517 case 's': // Strength
2518 case 'c': // Combat Points
2519 case 'm': // Magic
2520 case 'v': // [V]ana
2521 input[0] = 0;
2522 mode = CP_EnterValue;
2523 break;
2524
2525 // X and Escape leave
2526 case SDLK_ESCAPE:
2527 case 'x':
2528 input[0] = command;
2529 return false;
2530
2531 // Unknown
2532 default:
2533 command = 0;
2534 break;
2535 }
2536
2537 return true;
2538 }
2539
2540
2541 //
2542 // Advanced Flag Edition
2543 //
2544
AdvancedFlagLoop(int num,Actor * actor)2545 CheatScreen::Cheat_Prompt CheatScreen::AdvancedFlagLoop(int num, Actor *actor) {
2546 #ifdef __IPHONEOS__
2547 const int offsetx = 15;
2548 const int offsety1 = 83;
2549 const int offsety2 = 72;
2550 #else
2551 int npc_num = actor->get_npc_num();
2552 const int offsetx = 0;
2553 const int offsety1 = 0;
2554 const int offsety2 = maxy - 36;
2555 #endif
2556 bool looping = true;
2557 // This is for the prompt message
2558 Cheat_Prompt mode = CP_Command;
2559
2560 // This is the command
2561 char input[17];
2562 int i;
2563 int command;
2564 bool activate = false;
2565 char buf[512];
2566
2567 for (i = 0; i < 17; i++) input[i] = 0;
2568
2569 while (looping) {
2570 gwin->clear_screen();
2571
2572 #ifndef __IPHONEOS__
2573 NPCDisplay(actor, npc_num);
2574 #endif
2575
2576 if (num < 0) num = 0;
2577 else if (num > 63) num = 63;
2578
2579 // First the info
2580 if (flag_names[num])
2581 snprintf(buf, 512, "NPC Flag %i: %s", num, flag_names[num]);
2582 else
2583 snprintf(buf, 512, "NPC Flag %i", num);
2584 font->paint_text_fixedwidth(ibuf, buf, offsetx, maxy - offsety1 - 108, 8);
2585
2586 snprintf(buf, 512, "Flag is %s", actor->get_flag(num) ? "SET" : "UNSET");
2587 font->paint_text_fixedwidth(ibuf, buf, offsetx, maxy - offsety1 - 90, 8);
2588
2589
2590 // Now the Menu Column
2591 if (!actor->get_flag(num)) font->paint_text_fixedwidth(ibuf, "[S]et Flag", offsetx + 160, maxy - offsety1 - 90, 8);
2592 else font->paint_text_fixedwidth(ibuf, "[U]nset Flag", offsetx + 160, maxy - offsety1 - 90, 8);
2593
2594 // Change Flag
2595 font->paint_text_fixedwidth(ibuf, "[*] Change Flag", offsetx, maxy - offsety1 - 72, 8);
2596 if (num > 0 && num < 63) font->paint_text_fixedwidth(ibuf, "[+-] Scroll Flags", offsetx, maxy - offsety1 - 63, 8);
2597 else if (num == 0) font->paint_text_fixedwidth(ibuf, "[+] Scroll Flags", offsetx, maxy - offsety1 - 63, 8);
2598 else font->paint_text_fixedwidth(ibuf, "[-] Scroll Flags", offsetx, maxy - offsety1 - 63, 8);
2599
2600 font->paint_text_fixedwidth(ibuf, "[X]it", offsetx, offsety2, 8);
2601
2602 // Finally the Prompt...
2603 SharedPrompt(input, mode);
2604
2605 // Draw it!
2606 gwin->get_win()->show();
2607
2608 // Check to see if we need to change menus
2609 if (activate) {
2610 mode = CP_Command;
2611 if (command == '-') { // Decrement
2612 num--;
2613 if (num < 0) {
2614 num = 0;
2615 }
2616 } else if (command == '+') { // Increment
2617 num++;
2618 if (num > 63) {
2619 num = 63;
2620 }
2621 } else if (command == '*') { // Change Flag
2622 i = std::atoi(input);
2623 if (i < -1 || i > 63) {
2624 mode = CP_InvalidValue;
2625 } else if (i == -1) {
2626 mode = CP_Canceled;
2627 } else if (input[0]) {
2628 num = i;
2629 }
2630 } else if (command == 's') { // Set
2631 actor->set_flag(num);
2632 if (num == Obj_flags::in_party) {
2633 gwin->get_party_man()->add_to_party(actor);
2634 actor->set_schedule_type(Schedule::follow_avatar);
2635 }
2636 } else if (command == 'u') { // Unset
2637 if (num == Obj_flags::in_party) {
2638 gwin->get_party_man()->remove_from_party(actor);
2639 gwin->revert_schedules(actor);
2640 }
2641 actor->clear_flag(num);
2642 }
2643
2644 for (i = 0; i < 17; i++) {
2645 input[i] = 0;
2646 }
2647 command = 0;
2648 activate = false;
2649 continue;
2650 }
2651
2652 if (SharedInput(input, 17, command, mode, activate)) {
2653 switch (command) {
2654 // Simple commands
2655 case 's': // Set Flag
2656 case 'u': // Unset flag
2657 input[0] = command;
2658 activate = true;
2659 break;
2660
2661 // Decrement
2662 case SDLK_KP_MINUS:
2663 case '-':
2664 command = '-';
2665 input[0] = command;
2666 activate = true;
2667 break;
2668
2669 // Increment
2670 case SDLK_KP_PLUS:
2671 case '=':
2672 command = '+';
2673 input[0] = command;
2674 activate = true;
2675 break;
2676
2677 // * Change Flag
2678 case SDLK_KP_MULTIPLY:
2679 case '8':
2680 command = '*';
2681 input[0] = 0;
2682 mode = CP_NFlagNum;
2683 break;
2684
2685 // X and Escape leave
2686 case SDLK_ESCAPE:
2687 case 'x':
2688 input[0] = command;
2689 looping = false;
2690 break;
2691
2692 default:
2693 mode = CP_InvalidCom;
2694 input[0] = command;
2695 command = 0;
2696 break;
2697 }
2698 }
2699 }
2700 return CP_Command;
2701 }
2702
2703
2704 //
2705 // Teleport screen
2706 //
2707
TeleportLoop()2708 void CheatScreen::TeleportLoop() {
2709 bool looping = true;
2710
2711 // This is for the prompt message
2712 Cheat_Prompt mode = CP_Command;
2713
2714 // This is the command
2715 char input[5];
2716 int i;
2717 int command;
2718 bool activate = false;
2719 int prev = 0;
2720
2721 for (i = 0; i < 5; i++) input[i] = 0;
2722
2723 while (looping) {
2724 gwin->clear_screen();
2725
2726 // First the display
2727 TeleportDisplay();
2728
2729 // Now the Menu Column
2730 TeleportMenu();
2731
2732 // Finally the Prompt...
2733 SharedPrompt(input, mode);
2734
2735 // Draw it!
2736 gwin->get_win()->show();
2737
2738 // Check to see if we need to change menus
2739 if (activate) {
2740 TeleportActivate(input, command, mode, prev);
2741 activate = false;
2742 continue;
2743 }
2744
2745 if (SharedInput(input, 5, command, mode, activate))
2746 looping = TeleportCheck(input, command, mode, activate);
2747 }
2748 }
2749
TeleportDisplay()2750 void CheatScreen::TeleportDisplay() {
2751 char buf[512];
2752 Tile_coord t = gwin->get_main_actor()->get_tile();
2753 int curmap = gwin->get_map()->get_num();
2754 int highest = Find_highest_map();
2755 #ifdef __IPHONEOS__
2756 const int offsetx = 15;
2757 const int offsety1 = 54;
2758 #else
2759 const int offsetx = 0;
2760 const int offsety1 = 0;
2761 #endif
2762
2763 #ifdef __IPHONEOS__
2764 font->paint_text_fixedwidth(ibuf, "Teleport Menu - Dangerous!", offsetx, 0, 8);
2765 #else
2766 font->paint_text_fixedwidth(ibuf, "Teleport Menu", offsetx, 0, 8);
2767 font->paint_text_fixedwidth(ibuf, "Dangerous - use with care!", offsetx, 18, 8);
2768 #endif
2769
2770 int longi = ((t.tx - 0x3A5) / 10);
2771 int lati = ((t.ty - 0x46E) / 10);
2772 #ifdef __IPHONEOS__
2773 snprintf(buf, 512, "Coords %d %s %d %s, Map #%d of %d",
2774 abs(lati), (lati < 0 ? "North" : "South"),
2775 abs(longi), (longi < 0 ? "West" : "East"), curmap, highest);
2776 font->paint_text_fixedwidth(ibuf, buf, offsetx, 9, 8);
2777 #else
2778 snprintf(buf, 512, "Coordinates %d %s %d %s",
2779 abs(lati), (lati < 0 ? "North" : "South"),
2780 abs(longi), (longi < 0 ? "West" : "East"));
2781 font->paint_text_fixedwidth(ibuf, buf, offsetx, 63, 8);
2782 #endif
2783
2784 snprintf(buf, 512, "Coords in hex (%04x, %04x, %02x)",
2785 t.tx, t.ty, t.tz);
2786 font->paint_text_fixedwidth(ibuf, buf, offsetx, 72 - offsety1, 8);
2787
2788 snprintf(buf, 512, "Coords in dec (%04i, %04i, %02i)",
2789 t.tx, t.ty, t.tz);
2790 font->paint_text_fixedwidth(ibuf, buf, offsetx, 81 - offsety1, 8);
2791
2792 #ifndef __IPHONEOS__
2793 snprintf(buf, 512, "On Map #%d of %d",
2794 curmap, highest);
2795 font->paint_text_fixedwidth(ibuf, buf, offsetx, 90, 8);
2796 #endif
2797 }
2798
2799
TeleportMenu()2800 void CheatScreen::TeleportMenu() {
2801
2802 #ifdef __IPHONEOS__
2803 const int offsetx = 15;
2804 const int offsety1 = 64;
2805 const int offsetx2 = 175;
2806 const int offsety2 = 63;
2807 const int offsety3 = 72;
2808 #else
2809 const int offsetx = 0;
2810 const int offsety1 = 0;
2811 const int offsetx2 = offsetx;
2812 const int offsety2 = maxy - 63;
2813 const int offsety3 = maxy - 36;
2814 #endif
2815
2816 // Left Column
2817 // Geo
2818 font->paint_text_fixedwidth(ibuf, "[G]eographic Coordinates", offsetx, maxy - offsety1 - 99, 8);
2819
2820
2821 // Hex
2822 font->paint_text_fixedwidth(ibuf, "[H]exadecimal Coordinates", offsetx, maxy - offsety1 - 90, 8);
2823
2824 // Dec
2825 font->paint_text_fixedwidth(ibuf, "[D]ecimal Coordinates", offsetx, maxy - offsety1 - 81, 8);
2826
2827 // NPC
2828 font->paint_text_fixedwidth(ibuf, "[N]PC Number", offsetx, maxy - offsety1 - 72, 8);
2829
2830 // Map
2831 font->paint_text_fixedwidth(ibuf, "[M]ap Number", offsetx2, offsety2, 8);
2832
2833 // eXit
2834 font->paint_text_fixedwidth(ibuf, "[X]it", offsetx, offsety3, 8);
2835 }
2836
TeleportActivate(char * input,int & command,Cheat_Prompt & mode,int & prev)2837 void CheatScreen::TeleportActivate(char *input, int &command, Cheat_Prompt &mode, int &prev) {
2838 int i = std::atoi(input);
2839 static int lat;
2840 Tile_coord t = gwin->get_main_actor()->get_tile();
2841 int highest = Find_highest_map();
2842
2843 mode = CP_Command;
2844 switch (command) {
2845
2846 case 'g': // North or South
2847 if (!input[0]) {
2848 mode = CP_NorthSouth;
2849 command = 'g';
2850 } else if (input[0] == 'n' || input[0] == 's') {
2851 prev = input[0];
2852 if (prev == 'n') mode = CP_NLatitude;
2853 else mode = CP_SLatitude;
2854 command = 'a';
2855 }else
2856 mode = CP_InvalidValue;
2857 break;
2858
2859 case 'a': // latitude
2860 if (i < -1 || (prev == 'n' && i > 113) || (prev == 's' && i > 193)) mode = CP_InvalidValue;
2861 else if (i == -1) mode = CP_Canceled;
2862 else if (!input[0]) {
2863 if (prev == 'n') mode = CP_NLatitude;
2864 else mode = CP_SLatitude;
2865 command = 'a';
2866 } else {
2867 if (prev == 'n')
2868 lat = ((i * -10) + 0x46E);
2869 else
2870 lat = ((i * 10) + 0x46E);
2871 mode = CP_WestEast;
2872 command = 'b';
2873 }
2874 break;
2875
2876 case 'b': // West or East
2877 if (!input[0]) {
2878 mode = CP_WestEast;
2879 command = 'b';
2880 } else if (input[0] == 'w' || input[0] == 'e') {
2881 prev = input[0];
2882 if (prev == 'w') mode = CP_WLongitude;
2883 else mode = CP_ELongitude;
2884 command = 'c';
2885 }
2886 else
2887 mode = CP_InvalidValue;
2888 break;
2889
2890 case 'c': // longitude
2891 if (i < -1 || (prev == 'w' && i > 93) || (prev == 'e' && i > 213)) mode = CP_InvalidValue;
2892 else if (i == -1) mode = CP_Canceled;
2893 else if (!input[0]) {
2894 if (prev == 'w') mode = CP_WLongitude;
2895 else mode = CP_ELongitude;
2896 command = 'c';
2897 } else {
2898 if (prev == 'w')
2899 t.tx = ((i * -10) + 0x3A5);
2900 else
2901 t.tx = ((i * 10) + 0x3A5);
2902 t.ty = lat;
2903 t.tz = 0;
2904 gwin->teleport_party(t);
2905 }
2906 break;
2907
2908 case 'h': // hex X coord
2909 i = strtol(input, nullptr, 16);
2910 if (i < -1 || i > c_num_tiles) mode = CP_InvalidValue;
2911 else if (i == -1) mode = CP_Canceled;
2912 else if (!input[0]) {
2913 mode = CP_HexXCoord;
2914 command = 'h';
2915 } else {
2916 prev = i;
2917 mode = CP_HexYCoord;
2918 command = 'i';
2919 }
2920 break;
2921
2922 case 'i': // hex Y coord
2923 i = strtol(input, nullptr, 16);
2924 if (i < -1 || i > c_num_tiles) mode = CP_InvalidValue;
2925 else if (i == -1) mode = CP_Canceled;
2926 else if (!input[0]) {
2927 mode = CP_HexYCoord;
2928 command = 'i';
2929 } else {
2930 t.tx = prev;
2931 t.ty = i;
2932 t.tz = 0;
2933 gwin->teleport_party(t);
2934 }
2935 break;
2936
2937 case 'd': // dec X coord
2938 if (i < -1 || i > c_num_tiles) mode = CP_InvalidValue;
2939 else if (i == -1) mode = CP_Canceled;
2940 else if (!input[0]) {
2941 mode = CP_XCoord;
2942 command = 'd';
2943 } else {
2944 prev = i;
2945 mode = CP_YCoord;
2946 command = 'e';
2947 }
2948 break;
2949
2950 case 'e': // dec Y coord
2951 if (i < -1 || i > c_num_tiles) mode = CP_InvalidValue;
2952 else if (i == -1) mode = CP_Canceled;
2953 else if (!input[0]) {
2954 mode = CP_YCoord;
2955 command = 'e';
2956 } else {
2957 t.tx = prev;
2958 t.ty = i;
2959 t.tz = 0;
2960 gwin->teleport_party(t);
2961 }
2962 break;
2963
2964 case 'n': // NPC
2965 if (i < -1 || (i >= 356 && i <= 359)) mode = CP_InvalidNPC;
2966 else if (i == -1) mode = CP_Canceled;
2967 else {
2968 Actor *actor = gwin->get_npc(i);
2969 Game_window::get_instance()->teleport_party(actor->get_tile(),
2970 false, actor->get_map_num());
2971 }
2972 break;
2973
2974 case 'm': // map
2975 if (i == -1) mode = CP_Canceled;
2976 else if ((i < 0 || i > 255) || i > highest) mode = CP_InvalidValue;
2977 else
2978 gwin->teleport_party(gwin->get_main_actor()->get_tile(), true, i);
2979 break;
2980
2981 default:
2982 break;
2983 }
2984 for (i = 0; i < 5; i++) input[i] = 0;
2985 }
2986
2987 // Checks the input
TeleportCheck(char * input,int & command,Cheat_Prompt & mode,bool & activate)2988 bool CheatScreen::TeleportCheck(char *input, int &command, Cheat_Prompt &mode, bool &activate) {
2989 ignore_unused_variable_warning(activate);
2990 switch (command) {
2991 // Simple commands
2992 case 'g': // geographic
2993 mode = CP_NorthSouth;
2994 return true;
2995
2996 case 'h': // hex
2997 mode = CP_HexXCoord;
2998 return true;
2999
3000 case 'd': // dec teleport
3001 mode = CP_XCoord;
3002 return true;
3003
3004 case 'n': // NPC teleport
3005 mode = CP_ChooseNPC;
3006 break;
3007
3008 case 'm': // NPC teleport
3009 mode = CP_EnterValue;
3010 break;
3011
3012 // X and Escape leave
3013 case SDLK_ESCAPE:
3014 case 'x':
3015 input[0] = command;
3016 return false;
3017
3018 default:
3019 command = 0;
3020 mode = CP_InvalidCom;
3021 break;
3022 }
3023
3024 return true;
3025 }
3026