1 /* Tower Toppler - Nebulus
2 * Copyright (C) 2000-2012 Andreas R�ver
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (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 #include "leveledit.h"
20
21 #include "decl.h"
22 #include "level.h"
23 #include "screen.h"
24 #include "keyb.h"
25 #include "game.h"
26 #include "sound.h"
27 #include "robots.h"
28 #include "snowball.h"
29 #include "menu.h"
30 #include "txtsys.h"
31 #include "configuration.h"
32
33 #include <stdlib.h>
34 #include <string.h>
35
36 /* Editor key actions.
37 If you add here, change _ed_key_actions[] in leveledit.cc */
38
39 typedef enum {
40 EDACT_QUIT,
41 EDACT_MOVEUP,
42 EDACT_MOVEDOWN,
43 EDACT_MOVELEFT,
44 EDACT_MOVERIGHT,
45 EDACT_INSROW,
46 EDACT_DELROW,
47 EDACT_ROT180,
48 EDACT_PUTSPACE,
49 EDACT_PUTSTEP,
50 EDACT_PUTVANISHER,
51 EDACT_PUTSLIDERLEFT,
52 EDACT_PUTSLIDERRIGHT,
53 EDACT_PUTDOOR,
54 EDACT_PUTGOAL,
55 EDACT_CHECKTOWER,
56 EDACT_PUTROBOT1,
57 EDACT_PUTROBOT2,
58 EDACT_PUTROBOT3,
59 EDACT_PUTROBOT4,
60 EDACT_PUTROBOT5,
61 EDACT_PUTROBOT6,
62 EDACT_PUTROBOT7,
63 EDACT_PUTLIFT,
64 EDACT_PUTLIFTMID,
65 EDACT_PUTLIFTTOP,
66 EDACT_PUTSTICK,
67 EDACT_PUTBOX,
68 EDACT_LOADTOWER,
69 EDACT_SAVETOWER,
70 EDACT_TESTTOWER,
71 EDACT_SETTOWERCOLOR,
72 EDACT_INCTIME,
73 EDACT_DECTIME,
74 EDACT_CREATEMISSION,
75 EDACT_MOVEPAGEUP,
76 EDACT_MOVEPAGEDOWN,
77 EDACT_GOTOSTART,
78 EDACT_SHOWKEYHELP,
79 EDACT_NAMETOWER,
80 EDACT_SETTIME,
81 EDACT_REC_DEMO,
82 EDACT_PLAY_DEMO,
83 EDACT_ADJHEIGHT,
84 EDACT_GOTOEND,
85 EDACT_CUTROW,
86 EDACT_PASTEROW,
87 EDACT_TOGGLEROBOT,
88
89 NUMEDITORACTIONS
90 } key_actions;
91
92 struct _ed_key {
93 key_actions action;
94 SDLKey key;
95 char character;
96 Uint16 mod; /* KMOD_NONE|KMOD_SHIFT|KMOD_CTRL|KMOD_ALT */
97 };
98
99 #define TOWERPAGESIZE 5 /* pageup/pagedown moving */
100 #define TOWERSTARTHEI 4 /* tower starting height */
101
102 const char *_ed_key_actions[NUMEDITORACTIONS] = {
103 N_("Quit"), N_("Move up"), N_("Move down"), N_("Move left"),
104 N_("Move right"), N_("Insert row"), N_("Delete row"), N_("Rotate 180"),
105 N_("Put space"), N_("Put step"), N_("Put vanisher"), N_("Put slider left"),
106 N_("Put slider right"),
107 N_("Put door"), N_("Put goal"), N_("Check tower"), N_("Put rolling ball"),
108 N_("Put jumping ball moving"), N_("Put jumping ball"), N_("Put robot up down"), N_("Put robot up down fast"),
109 N_("Put robot left right"), N_("Put robot left right fast"), N_("Put lift"), N_("Lift middle stop"),
110 N_("Lift top stop"), N_("Put pillar"), N_("Put box"), N_("Load tower"),
111 N_("Save tower"), N_("Test tower"), N_("Set tower color"), N_("Increase time"),
112 N_("Decrease time"), N_("Create mission"), N_("Move page up"), N_("Move page down"),
113 N_("Go to start"), N_("Show this help"), N_("Name the tower"), N_("Set tower time"),
114 N_("Record demo"), N_("Play demo"), N_("Adjust tower height"), N_("Go to end"),
115 N_("Cut row"), N_("Paste row"), N_("Change robot type")
116 };
117
118 const struct _ed_key _ed_keys[] = {
119 {EDACT_QUIT, SDLK_ESCAPE},
120 {EDACT_SHOWKEYHELP, SDLK_F1},
121 {EDACT_SHOWKEYHELP, SDLK_h, 'h'},
122 {EDACT_MOVEUP, SDLK_UP},
123 {EDACT_MOVEDOWN, SDLK_DOWN},
124 {EDACT_MOVELEFT, SDLK_LEFT},
125 {EDACT_MOVERIGHT, SDLK_RIGHT},
126 {EDACT_MOVEPAGEUP, SDLK_PAGEUP},
127 {EDACT_MOVEPAGEDOWN, SDLK_PAGEDOWN},
128 {EDACT_GOTOSTART, SDLK_HOME},
129 {EDACT_GOTOEND, SDLK_END},
130 {EDACT_ROT180, SDLK_y, 'y'},
131 {EDACT_INSROW, SDLK_INSERT},
132 {EDACT_DELROW, SDLK_DELETE},
133 {EDACT_CUTROW, SDLK_MINUS, '-'},
134 {EDACT_PASTEROW, SDLK_PLUS, '+'},
135 {EDACT_PUTSPACE, SDLK_SPACE, ' '},
136 {EDACT_PUTSTEP, SDLK_w, 'w'},
137 {EDACT_PUTVANISHER, SDLK_s, 's'},
138 {EDACT_PUTSLIDERLEFT, SDLK_x, 'x'},
139 {EDACT_PUTSLIDERRIGHT,SDLK_x, 'X', KMOD_SHIFT},
140 {EDACT_PUTDOOR, SDLK_i, 'i'},
141 {EDACT_PUTGOAL, SDLK_k, 'k'},
142 {EDACT_PUTROBOT1, SDLK_1, '1'},
143 {EDACT_PUTROBOT2, SDLK_2, '2'},
144 {EDACT_PUTROBOT3, SDLK_3, '3'},
145 {EDACT_PUTROBOT4, SDLK_4, '4'},
146 {EDACT_PUTROBOT5, SDLK_5, '5'},
147 {EDACT_PUTROBOT6, SDLK_6, '6'},
148 {EDACT_PUTROBOT7, SDLK_7, '7'},
149 {EDACT_TOGGLEROBOT, SDLK_8, '8'},
150 {EDACT_PUTLIFT, SDLK_c, 'c'},
151 {EDACT_PUTLIFTMID, SDLK_d, 'd'},
152 {EDACT_PUTLIFTTOP, SDLK_e, 'e'},
153 {EDACT_PUTSTICK, SDLK_q, 'q'},
154 {EDACT_PUTBOX, SDLK_a, 'a'},
155 {EDACT_CHECKTOWER, SDLK_z, 'z'},
156 {EDACT_LOADTOWER, SDLK_l, 'l'},
157 {EDACT_SAVETOWER, SDLK_o, 'o'},
158 {EDACT_TESTTOWER, SDLK_p, 'p'},
159 {EDACT_SETTOWERCOLOR, SDLK_v, 'v'},
160 {EDACT_SETTIME, SDLK_b, 'b'},
161 {EDACT_INCTIME, SDLK_n, 'n'},
162 {EDACT_DECTIME, SDLK_n, 'N', KMOD_SHIFT},
163 {EDACT_CREATEMISSION, SDLK_m, 'm'},
164 {EDACT_NAMETOWER, SDLK_t, 't'},
165 {EDACT_REC_DEMO, SDLK_F10},
166 {EDACT_PLAY_DEMO, SDLK_F11},
167 {EDACT_ADJHEIGHT, SDLK_F8}
168 };
169
170 static int bg_row;
171 static int bg_col;
172 static char *bg_text = NULL;
173 static bool bg_darken = false;
174
175 /* men_yn() background drawing callback proc */
editor_background_proc(void)176 static void editor_background_proc(void) {
177 scr_drawedit(bg_row * 4, bg_col * 8, false);
178 if (bg_darken) scr_darkenscreen();
179 if (bg_text) scr_writetext_center(5, bg_text);
180 }
181
editor_background_menu_proc(_menusystem * ms)182 static const char *editor_background_menu_proc(_menusystem *ms) {
183 editor_background_proc();
184 return 0;
185 }
186
really_quit(int row,int col)187 static bool really_quit(int row, int col) {
188 bg_darken = true;
189 if (men_yn(_("Tower changed, really quit"), false)) {
190 return true;
191 } else {
192 return false;
193 }
194 bg_darken = false;
195 }
196
really_load(int row,int col)197 static bool really_load(int row, int col) {
198 bg_darken = true;
199 if (men_yn(_("Tower changed, really load"), false)) {
200 return true;
201 } else {
202 return false;
203 }
204 bg_darken = false;
205 }
206
edit_towercolor(int row,int col)207 static bool edit_towercolor(int row, int col) {
208
209 int activecol = 0, abg_r = 10, abg_g = 50, abg_b = 120;
210 bool ende = false, oldpal = false;
211 char cbuf[32];
212 int tmpcol, z, tmp;
213 int oldc[3], newc[3], curc[3];
214 SDLKey c;
215
216 const char *colorname[] = {_("Red"), _("Green"), _("Blue")};
217
218 curc[0] = newc[0] = oldc[0] = lev_towercol_red();
219 curc[1] = newc[1] = oldc[1] = lev_towercol_green();
220 curc[2] = newc[2] = oldc[2] = lev_towercol_blue();
221 bg_darken = false;
222 do {
223
224 scr_drawedit(row * 4, col * 8, false);
225 scr_writetext_center(22, _("Tower Color"));
226
227 for (tmp = 0 ; tmp < 3; tmp++) {
228 scr_color_ramp(&abg_r, &abg_g, &abg_b);
229 tmpcol = newc[tmp];
230 z = ((SCREENHEI * 2) / 3) + tmp * (FONTHEI + 2);
231
232 if (tmp == activecol) {
233 scr_putbar((SCREENWID / 2) - (128 + 8), z, 8, FONTHEI, abg_r, abg_g, abg_b, 255);
234 scr_putbar((SCREENWID / 2) + 128 - 1, z, 8, FONTHEI, abg_r, abg_g, abg_b, 255);
235 } else {
236 scr_putbar((SCREENWID / 2) - (128 + 8), z, 8, FONTHEI, 66, 66, 66, 255);
237 scr_putbar((SCREENWID / 2) + 128 - 1, z, 8, FONTHEI, 66, 66, 66, 255);
238 }
239 scr_putbar((SCREENWID / 2) - 128 + tmpcol, z, 255 - tmpcol, FONTHEI, 0,0,0, 255);
240 switch (tmp) {
241 default:
242 case 0: scr_putbar((SCREENWID / 2) - 128, z, tmpcol, FONTHEI, tmpcol / 3 + 64, 0, 0, 255); break;
243 case 1: scr_putbar((SCREENWID / 2) - 128, z, tmpcol, FONTHEI, 0, tmpcol / 3 + 64, 0, 255); break;
244 case 2: scr_putbar((SCREENWID / 2) - 128, z, tmpcol, FONTHEI, 0, 0, tmpcol / 3 + 64, 255); break;
245 }
246 cbuf[0] = '\0';
247 snprintf(cbuf, 32, "%5s %.3d", colorname[tmp], tmpcol);
248 scr_writetext_center(z, cbuf);
249 }
250
251 scr_swap();
252 dcl_wait();
253
254 c = key_sdlkey();
255
256 switch (c) {
257 case SDLK_UP: if (activecol > 0) activecol--; break;
258 case SDLK_DOWN: if (activecol < 2) activecol++; break;
259 case SDLK_LEFT: if (newc[activecol] > 0) newc[activecol]--; break;
260 case SDLK_RIGHT: if (newc[activecol] < 255) newc[activecol]++; break;
261 case SDLK_PAGEDOWN: if (newc[activecol] > 10) newc[activecol] = newc[activecol] - 10;
262 else newc[activecol] = 0; break;
263 case SDLK_PAGEUP: if (newc[activecol] < 245) newc[activecol] = newc[activecol] + 10;
264 else newc[activecol] = 255; break;
265 case SDLK_0: case SDLK_1: case SDLK_2: case SDLK_3: case SDLK_4:
266 case SDLK_5: case SDLK_6: case SDLK_7: case SDLK_8:
267 case SDLK_9: newc[activecol] = (int) ((c - '0') * 256) / 10; break;
268 case SDLK_PERIOD: for (tmp = 0; tmp < 3; tmp++) newc[tmp] = rand() % 256; break;
269 case SDLK_r: activecol = 0; break;
270 case SDLK_g: activecol = 1; break;
271 case SDLK_b: activecol = 2; break;
272 case SDLK_ESCAPE: ende = true; oldpal = true; break;
273 case SDLK_SPACE:
274 case SDLK_RETURN: ende = true;
275 default: break;
276 }
277
278 if ((newc[0] != curc[0]) || (newc[1] != curc[1]) ||
279 (newc[2] != curc[2]) || oldpal) {
280 if (oldpal)
281 lev_set_towercol(oldc[0],oldc[1],oldc[2]);
282 else
283 lev_set_towercol(newc[0],newc[1],newc[2]);
284
285 scr_settowercolor(lev_towercol_red(),
286 lev_towercol_green(),
287 lev_towercol_blue());
288
289 curc[0] = newc[0];
290 curc[1] = newc[1];
291 curc[2] = newc[2];
292 }
293
294 } while (!ende);
295
296 return (!oldpal && ((curc[0] != oldc[0]) || (curc[1] != oldc[1]) || (curc[2] != oldc[2])));
297 }
298
edit_checktower(int & row,int & col)299 static void edit_checktower(int &row, int &col) {
300 int r, c, pr;
301 r = row;
302 c = -col;
303
304 static char *problemstr[NUM_TPROBLEMS] = {
305 _("No problems found"),
306 _("No starting step"),
307 _("Start is blocked"),
308 _("Unknown block"),
309 _("No elevator stop"),
310 _("Elevator is blocked"),
311 _("No opposing doorway"),
312 _("Broken doorway"),
313 _("No exit"),
314 _("Exit is unreachable"),
315 _("Not enough time"),
316 _("Tower is too short"),
317 _("Tower has no name")
318 };
319
320 pr = lev_is_consistent(r, c);
321 if ((r >= lev_towerrows()) && (lev_towerrows() > 0)) r = lev_towerrows() - 1;
322 bg_row = r;
323 bg_col = -c;
324
325 bg_text = _("Tower check:");
326 bg_darken = true;
327 men_info(problemstr[pr % NUM_TPROBLEMS], 50, 2);
328 bg_darken = false;
329 row = bg_row;
330 col = bg_col;
331 bg_text = NULL;
332 }
333
keymod2str(Uint16 kmod)334 char *keymod2str(Uint16 kmod) {
335 static char buf[256];
336 buf[0] = '\0';
337 if (kmod != KMOD_NONE) {
338 if ((kmod & KMOD_LSHIFT) ||
339 (kmod & KMOD_RSHIFT)) snprintf(buf, 256, "shift+");
340 if ((kmod & KMOD_LCTRL) ||
341 (kmod & KMOD_RCTRL)) snprintf(&buf[strlen(buf)], 256-strlen(buf), "ctrl+");
342 if ((kmod & KMOD_LALT) ||
343 (kmod & KMOD_RALT)) snprintf(&buf[strlen(buf)], 256-strlen(buf), "alt+");
344 }
345 return buf;
346 }
347
createMission(void)348 static void createMission(void) {
349
350 scr_drawedit(0, 0, false);
351 scr_writetext_center(30, _("Mission creation"));
352 scr_writetext_center(80, _("enter mission name"));
353 scr_writetext_center(110, _("empty to abort"));
354
355 set_men_bgproc(NULL);
356
357 char missionname[25];
358 missionname[0] = 0;
359 while (!men_input(missionname, 15)) ;
360
361 if (!missionname[0])
362 return;
363
364 if (!lev_mission_new(missionname)) {
365
366 scr_drawedit(0, 0, false);
367 scr_writetext_center(30, _("Mission creation"));
368
369 scr_writetext_center(80, _("could not create file"));
370 scr_writetext_center(110, _("aborting"));
371
372 scr_swap();
373
374 int inp;
375
376 do {
377 inp = key_chartyped();
378 } while (!inp);
379
380 return;
381 }
382
383 int currenttower = 1;
384 char towername[30];
385
386 while (true) {
387
388 scr_drawedit(0, 0, false);
389 scr_writetext_center(30, _("Mission creation"));
390 scr_writetext_center(80, _("enter name of"));
391
392 char s[30];
393 snprintf(s, 30, _("tower no %i"), currenttower);
394 scr_writetext_center(110, s);
395
396 towername[0] = 0;
397 while (!men_input(towername, 25)) ;
398
399 if (!towername[0]) break;
400
401 lev_mission_addtower(towername);
402
403 currenttower++;
404 }
405
406 lev_mission_finish();
407
408 lev_findmissions();
409 }
410
le_showkeyhelp(int row,int col)411 static void le_showkeyhelp(int row, int col) {
412 int k;
413 int maxkeylen = 0;
414 textsystem *ts = new textsystem(_("Editor Key Help"), editor_background_menu_proc);
415 char tabbuf1[6], tabbuf2[6];
416
417 if (!ts) return;
418
419 for (k = 0; k < SIZE(_ed_keys); k++) {
420 char knam[256];
421 snprintf(knam, 256, "%s%s", keymod2str(_ed_keys[k].mod), SDL_GetKeyName(_ed_keys[k].key));
422 int l = scr_textlength(knam);
423
424 if (l > maxkeylen) maxkeylen = l;
425 }
426
427 snprintf(tabbuf1, 6, "%3i", maxkeylen + FONTWID);
428 if (tabbuf1[0] < '0') tabbuf1[0] = '0';
429 if (tabbuf1[1] < '0') tabbuf1[1] = '0';
430 if (tabbuf1[2] < '0') tabbuf1[2] = '0';
431
432 for (k = 0; k < SIZE(_ed_keys); k++) {
433 char buf[256];
434 char tmpb[256];
435 char knam[256];
436
437 snprintf(knam, 256, "%s%s", keymod2str(_ed_keys[k].mod), SDL_GetKeyName(_ed_keys[k].key));
438
439 snprintf(tabbuf2, 6, "%3i", maxkeylen - scr_textlength(knam));
440 if (tabbuf2[0] < '0') tabbuf2[0] = '0';
441 if (tabbuf2[1] < '0') tabbuf2[1] = '0';
442 if (tabbuf2[2] < '0') tabbuf2[2] = '0';
443
444 snprintf(tmpb, 256, "~T%s%%s~T%s%%s", tabbuf2, tabbuf1);
445 snprintf(buf, 256, tmpb, knam, _(_ed_key_actions[_ed_keys[k].action]));
446
447 ts->addline(buf);
448 }
449 bg_darken = true;
450 ts->run();
451 bg_darken = false;
452 delete ts;
453 }
454
455 static int clipboard_rows = 0;
456 static Uint8 clipboard_tower[256][16];
457 static bool cursor_moved = false;
458
le_tower_cut(int row,int col)459 void le_tower_cut(int row, int col) {
460 if (cursor_moved) clipboard_rows = 0;
461
462 if (clipboard_rows < 255) {
463 for (int i = 0; i < 16; i++)
464 clipboard_tower[clipboard_rows][i] = lev_tower(row, (col+i) % 16);
465 lev_deleterow(row);
466 clipboard_rows++;
467 }
468
469 cursor_moved = false;
470 }
471
le_tower_paste(int row,int col)472 void le_tower_paste(int row, int col) {
473 if (clipboard_rows > 0) {
474 for (int z = 0; z < clipboard_rows; z++) {
475 lev_insertrow(row);
476 for (int i = 0; i < 16; i++) {
477 lev_set_tower(row, (col+i) % 16, clipboard_tower[clipboard_rows - (z + 1)][i]);
478 }
479 }
480 } else lev_insertrow(row);
481
482 cursor_moved = false;
483 }
484
le_edit(void)485 void le_edit(void) {
486
487 bool ende = false;
488 bool changed = false;
489 SDLKey inp = SDLK_UNKNOWN;
490 char inp_char;
491 Uint16 keymod;
492 int row = 0, col = 0;
493 int tstep = 0;
494 int blink_r = 70, blink_g = 40, blink_b = 10;
495 char status[80];
496 int towerstarthei;
497 int pagesize;
498
499 if (config.editor_towerstarthei() < 0)
500 towerstarthei = TOWERSTARTHEI + (rand() % abs(config.editor_towerstarthei()));
501 else towerstarthei = TOWERSTARTHEI + config.editor_towerstarthei();
502
503 lev_new(towerstarthei % 256);
504
505 if (config.editor_towerpagesize() < 1) {
506 config.editor_towerpagesize(TOWERPAGESIZE);
507 pagesize = TOWERPAGESIZE;
508 } else pagesize = config.editor_towerpagesize();
509
510 set_men_bgproc(editor_background_proc);
511
512 lev_set_towertime(100 + (rand() % 10) * 50);
513
514 lev_set_towercol(rand() % 256,rand() % 256,rand() % 256);
515 scr_settowercolor(lev_towercol_red(),
516 lev_towercol_green(),
517 lev_towercol_blue());
518
519 lev_set_towername("");
520 lev_set_towerdemo(0, NULL);
521
522 while (!ende) {
523
524 bg_row = row;
525 bg_col = col;
526 bg_darken = false;
527
528 scr_drawedit(row * 4, col * 8, true);
529
530 status[0] = '\0';
531 snprintf(status, 80, "%c~t050X%d~t150Y%d~t250%s:%d",
532 changed ? '*' : ' ', -col & 0xf, row, _("cut#"), clipboard_rows);
533
534 scr_putbar(SCREENWID-8, SCREENHEI-lev_towerrows(), 8, lev_towerrows(),
535 lev_towercol_red(), lev_towercol_green(), lev_towercol_blue(), 255);
536 scr_putbar(SCREENWID-8, SCREENHEI-row-1, 8, 1, blink_r, blink_g, blink_b, 128);
537
538 scr_color_ramp(&blink_r, &blink_g, &blink_b);
539
540 scr_writeformattext(0, SCREENHEI-FONTHEI, status);
541
542 scr_swap();
543 dcl_wait();
544
545 inp_char = key_chartyped();
546 inp = key_sdlkey();
547 keymod = (SDL_GetModState() & ~(KMOD_NUM|KMOD_CAPS|KMOD_MODE));
548 if (keymod & KMOD_SHIFT) keymod |= KMOD_SHIFT;
549 if (keymod & KMOD_CTRL) keymod |= KMOD_CTRL;
550 if (keymod & KMOD_ALT) keymod |= KMOD_ALT;
551 if (keymod & KMOD_META) keymod |= KMOD_META;
552
553
554 int k, action = -1;
555
556 if (inp_char != 0)
557 for (k = 0; k < SIZE(_ed_keys); k++)
558 if (_ed_keys[k].character == inp_char) {
559 action = _ed_keys[k].action;
560 break;
561 }
562
563 if ((inp != SDLK_UNKNOWN) && (action == -1))
564 for (k = 0; k < SIZE(_ed_keys); k++)
565 if (_ed_keys[k].key == inp && _ed_keys[k].mod == keymod) {
566 action = _ed_keys[k].action;
567 break;
568 }
569
570 if ((action != -1) || (inp_char != 0) || (inp != SDLK_UNKNOWN))
571 debugprintf(3, _("key: %s, char: %c, action: %i\n"), SDL_GetKeyName(inp), inp_char, action);
572
573 if (action != -1) {
574
575 switch (action) {
576 case EDACT_QUIT:
577 if (changed) ende = really_quit(row, col);
578 else ende = true;
579 break;
580 case EDACT_MOVEUP:
581 if (row + 1 < lev_towerrows()) {
582 row++;
583 cursor_moved = true;
584 }
585 break;
586 case EDACT_MOVEDOWN:
587 if (row > 0) {
588 row--;
589 cursor_moved = true;
590 }
591 break;
592 case EDACT_MOVELEFT:
593 col++;
594 cursor_moved = true;
595 break;
596 case EDACT_MOVERIGHT:
597 col--;
598 cursor_moved = true;
599 break;
600 case EDACT_ROT180:
601 col += 8;
602 cursor_moved = true;
603 break;
604 case EDACT_INSROW:
605 lev_insertrow(row);
606 changed = true;
607 break;
608 case EDACT_DELROW:
609 lev_deleterow(row);
610 changed = true;
611 break;
612 case EDACT_PASTEROW:
613 le_tower_paste(row, -col & 0xf);
614 changed = true;
615 break;
616 case EDACT_CUTROW:
617 le_tower_cut(row, -col & 0xf);
618 changed = true;
619 break;
620 case EDACT_PUTSPACE:
621 lev_putspace(row, -col & 0xf);
622 changed = true;
623 break;
624 case EDACT_PUTSTEP:
625 lev_putstep(row, -col & 0xf);
626 changed = true;
627 break;
628 case EDACT_PUTVANISHER:
629 lev_putvanishingstep(row, -col & 0xf);
630 changed = true;
631 break;
632 case EDACT_PUTSLIDERLEFT:
633 lev_putslidingstep_left(row, -col & 0xf);
634 changed = true;
635 break;
636 case EDACT_PUTSLIDERRIGHT:
637 lev_putslidingstep_right(row, -col & 0xf);
638 changed = true;
639 break;
640 case EDACT_PUTDOOR:
641 lev_putdoor(row, -col & 0xf);
642 changed = true;
643 break;
644 case EDACT_PUTGOAL:
645 lev_puttarget(row, -col & 0xf);
646 changed = true;
647 break;
648 case EDACT_CHECKTOWER:
649 edit_checktower(row, col);
650 break;
651 case EDACT_PUTROBOT1:
652 lev_putrobot1(row, -col & 0xf);
653 changed = true;
654 break;
655 case EDACT_PUTROBOT2:
656 lev_putrobot2(row, -col & 0xf);
657 changed = true;
658 break;
659 case EDACT_PUTROBOT3:
660 lev_putrobot3(row, -col & 0xf);
661 changed = true;
662 break;
663 case EDACT_PUTROBOT4:
664 lev_putrobot4(row, -col & 0xf);
665 changed = true;
666 break;
667 case EDACT_PUTROBOT5:
668 lev_putrobot5(row, -col & 0xf);
669 changed = true;
670 break;
671 case EDACT_PUTROBOT6:
672 lev_putrobot6(row, -col & 0xf);
673 changed = true;
674 break;
675 case EDACT_PUTROBOT7:
676 lev_putrobot7(row, -col & 0xf);
677 changed = true;
678 break;
679 case EDACT_PUTLIFTTOP:
680 lev_puttopstation(row, -col & 0xf);
681 changed = true;
682 break;
683 case EDACT_PUTLIFTMID:
684 lev_putmiddlestation(row, -col & 0xf);
685 changed = true;
686 break;
687 case EDACT_PUTLIFT:
688 lev_putelevator(row, -col & 0xf);
689 changed = true;
690 break;
691 case EDACT_PUTSTICK:
692 lev_putstick(row, -col & 0xf);
693 changed = true;
694 break;
695 case EDACT_PUTBOX:
696 lev_putbox(row, -col & 0xf);
697 changed = true;
698 break;
699 case EDACT_LOADTOWER:
700 if (changed)
701 if (!really_load(row, col))
702 break;
703 bg_text = _("Load tower:");
704 bg_darken = true;
705 key_wait_for_none(editor_background_proc);
706 {
707 char name[TOWERNAMELEN+1];
708 strncpy(name, config.editor_towername(), TOWERNAMELEN);
709 name[TOWERNAMELEN] = 0;
710 while (!men_input(name, TOWERNAMELEN)) ;
711 config.editor_towername(name);
712 }
713 bg_text = NULL;
714 if ((strlen(config.editor_towername()) > 0) &&
715 lev_loadtower(config.editor_towername())) {
716 scr_settowercolor(lev_towercol_red(),
717 lev_towercol_green(),
718 lev_towercol_blue());
719 changed = false;
720 }
721 if (row >= lev_towerrows()) row = lev_towerrows()-1;
722 break;
723 case EDACT_SAVETOWER:
724 bg_text = _("Save tower:");
725 bg_darken = true;
726 key_wait_for_none(editor_background_proc);
727 {
728 char name[TOWERNAMELEN+1];
729 strncpy(name, config.editor_towername(), TOWERNAMELEN);
730 name[TOWERNAMELEN] = 0;
731 while (!men_input(name, TOWERNAMELEN)) ;
732 config.editor_towername(name);
733 }
734 bg_text = NULL;
735 lev_savetower(config.editor_towername());
736 changed = false;
737 break;
738
739 case EDACT_REC_DEMO:
740 {
741 Uint8 dummy1;
742 Uint16 dummy2;
743 unsigned char *p;
744 int demolen = -1;
745 Uint16 *demobuf = NULL;
746 int speed = dcl_update_speed(config.game_speed());
747 lev_set_towerdemo(0, NULL);
748 lev_save(p);
749 gam_newgame();
750 rob_initialize();
751 snb_init();
752 ttsounds::instance()->startsound(SND_WATER);
753 gam_towergame(dummy1, dummy2, demolen, &demobuf);
754 ttsounds::instance()->stopsound(SND_WATER);
755 lev_restore(p);
756 lev_set_towerdemo(demolen, demobuf);
757 key_readkey();
758 set_men_bgproc(editor_background_proc);
759 dcl_update_speed(speed);
760 }
761 break;
762 case EDACT_PLAY_DEMO:
763 {
764 int demolen = 0;
765 Uint16 *demobuf = NULL;
766 lev_get_towerdemo(demolen, demobuf);
767 if (demolen > 0) {
768 Uint8 dummy1;
769 Uint16 dummy2;
770 unsigned char *p;
771 int speed = dcl_update_speed(config.game_speed());
772 lev_save(p);
773 gam_newgame();
774 rob_initialize();
775 snb_init();
776 ttsounds::instance()->startsound(SND_WATER);
777 gam_towergame(dummy1, dummy2, demolen, &demobuf);
778 ttsounds::instance()->stopsound(SND_WATER);
779 lev_restore(p);
780 key_readkey();
781 set_men_bgproc(editor_background_proc);
782 dcl_update_speed(speed);
783 } else {
784 bg_darken = true;
785 men_info(_("No recorded demo"), 150, 2);
786 }
787 }
788 break;
789 case EDACT_TESTTOWER:
790 {
791 Uint8 dummy1;
792 Uint16 dummy2;
793 int dummy3 = -2;
794 int speed = dcl_update_speed(config.game_speed());
795 Uint16 *dummybuf = NULL;
796 unsigned char *p;
797 lev_save(p);
798 gam_newgame();
799 rob_initialize();
800 snb_init();
801 ttsounds::instance()->startsound(SND_WATER);
802 gam_towergame(dummy1, dummy2, dummy3, &dummybuf);
803 ttsounds::instance()->stopsound(SND_WATER);
804 lev_restore(p);
805 key_readkey();
806 set_men_bgproc(editor_background_proc);
807 dcl_update_speed(speed);
808 }
809 break;
810 case EDACT_SETTOWERCOLOR:
811 changed |= edit_towercolor(row, col);
812 break;
813 case EDACT_INCTIME:
814 if (tstep <= 0) tstep = 1;
815 lev_set_towertime(lev_towertime() + tstep);
816 if (tstep < 10) tstep++;
817 changed = true;
818 break;
819 case EDACT_DECTIME:
820 if (tstep >= 0) tstep = -1;
821 lev_set_towertime(lev_towertime() + tstep);
822 if (tstep > -10) tstep--;
823 changed = true;
824 break;
825 case EDACT_SETTIME:
826 {
827 char buf[64];
828
829 snprintf(buf, 64, "%d", lev_towertime());
830
831 bg_text = _("Enter tower time:");
832 bg_darken = true;
833 key_wait_for_none(editor_background_proc);
834 while (!men_input((char *)buf, 15, -1, -1, "0123456789")) ;
835 bg_text = NULL;
836
837 lev_set_towertime(atoi(buf));
838 }
839 break;
840 case EDACT_ADJHEIGHT:
841 {
842 char buf[64];
843 int i;
844
845 snprintf(buf, 64, "0");
846
847 bg_text = _("Adjust tower height:");
848 bg_darken = true;
849 key_wait_for_none(editor_background_proc);
850 while (!men_input((char *)buf, 15, -1, -1, "-+0123456789")) ;
851 bg_text = NULL;
852
853 i = atoi(buf);
854 if ((i > 0) && (buf[0] == '+')) {
855 while (i-- > 0) lev_insertrow(row);
856 } else
857 if (i < 0) {
858 i = abs(i);
859 while (i-- > 0) lev_deleterow(row);
860 } else
861 if (i>0) {
862 if (i < lev_towerrows()) {
863 while ((i > 0) && (i < lev_towerrows())) {
864 lev_deleterow(row);
865 if ((row > 0) && (row >= lev_towerrows())) row--;
866 }
867 } else {
868 while ((i < 255) && (i > lev_towerrows())) {
869 lev_insertrow(row);
870 }
871 }
872 }
873 }
874 break;
875 case EDACT_CREATEMISSION:
876 createMission();
877 break;
878 case EDACT_MOVEPAGEUP:
879 if (row + pagesize < lev_towerrows())
880 row += pagesize;
881 else
882 row = lev_towerrows() - 1;
883 break;
884 case EDACT_MOVEPAGEDOWN:
885 if (row > pagesize)
886 row -= pagesize;
887 else
888 row = 0;
889 break;
890 case EDACT_GOTOSTART:
891 col = 0;
892 row = 1;
893 break;
894 case EDACT_GOTOEND:
895 {
896 int trow = row;
897 int tcol = col;
898 int coladj = 0;
899 int rowadj = 0;
900 bool ende = false;
901 bool skip = lev_is_targetdoor(trow, -tcol & 0xf);
902
903 do {
904 tcol++;
905 coladj++;
906
907 if (coladj >= 16) {
908 tcol = col;
909 trow = (trow + 1) % lev_towerrows();
910 coladj = 0;
911 rowadj++;
912 }
913
914 if (rowadj >= lev_towerrows()) ende = true;
915 else if (!skip && lev_is_targetdoor(trow, -tcol & 0xf) &&
916 lev_is_door_upperend(trow, -tcol & 0xf)) ende = true;
917 skip = false;
918 } while (!ende);
919
920 if (rowadj < lev_towerrows()) {
921 row = trow;
922 col = tcol;
923 }
924 }
925 break;
926 case EDACT_NAMETOWER:
927 bg_text = _("Name the tower:");
928 bg_darken = true;
929 key_wait_for_none(editor_background_proc);
930 while (!men_input(lev_towername(), TOWERNAMELEN)) ;
931 bg_text = NULL;
932 changed = true;
933 break;
934 case EDACT_SHOWKEYHELP:
935 le_showkeyhelp(row, col);
936 break;
937 case EDACT_TOGGLEROBOT:
938 lev_set_robotnr((lev_robotnr() + 1) % scr_numrobots());
939 break;
940 default: break;
941 }
942 }
943 }
944 }
945