1 /*-------------------------------------------------------------------------------
2
3 BARONY
4 File: buttons.cpp
5 Desc: contains code for all buttons in the editor
6
7 Copyright 2013-2016 (c) Turning Wheel LLC, all rights reserved.
8 See LICENSE for details.
9
10 -------------------------------------------------------------------------------*/
11
12 #include "main.hpp"
13 #include "editor.hpp"
14 #include "entity.hpp"
15 #include "files.hpp"
16 #include "player.hpp"
17
18 button_t* butX;
19 button_t* but_;
20 button_t* butTilePalette;
21 button_t* butSprite;
22 button_t* butPencil;
23 button_t* butPoint;
24 button_t* butBrush;
25 button_t* butSelect;
26 button_t* butFill;
27 button_t* butFile;
28 button_t* butNew;
29 button_t* butOpen;
30 button_t* butDir;
31 button_t* butSave;
32 button_t* butSaveAs;
33 button_t* butExit;
34 button_t* butEdit;
35 button_t* butCut;
36 button_t* butCopy;
37 button_t* butPaste;
38 button_t* butDelete;
39 button_t* butSelectAll;
40 button_t* butUndo;
41 button_t* butRedo;
42 button_t* butView;
43 button_t* butToolbox;
44 button_t* butStatusBar;
45 button_t* butAllLayers;
46 button_t* butHoverText;
47 button_t* butViewSprites;
48 button_t* butGrid;
49 button_t* but3DMode;
50 button_t* butMap;
51 button_t* butAttributes;
52 button_t* butClearMap;
53 button_t* butHelp;
54 button_t* butAbout;
55 button_t* butEditorControls;
56 button_t* butMonsterHelm;
57 button_t* butMonsterWeapon;
58 button_t* butMonsterShield;
59 button_t* butMonsterArmor;
60 button_t* butMonsterRing;
61 button_t* butMonsterAmulet;
62 button_t* butMonsterBoots;
63 button_t* butMonsterGloves;
64 button_t* butMonsterItem1;
65 button_t* butMonsterItem2;
66 button_t* butMonsterItem3;
67 button_t* butMonsterItem4;
68 button_t* butMonsterItem5;
69 button_t* butMonsterItem6;
70 button_t* butMonsterCloak;
71 button_t* butMonsterMask;
72 button_t* butMonsterOK;
73 button_t* butMonsterX;
74 button_t* butMonsterCancel;
75 button_t* butMonsterItemOK;
76 button_t* butMonsterItemX;
77 button_t* butMonsterItemCancel;
78 button_t* butItemOK;
79 button_t* butItemCancel;
80 button_t* butItemX;
81
82 bool exitFromItemWindow = false;
83
updateMapNames()84 static void updateMapNames()
85 {
86 DIR* dir;
87 struct dirent* ent;
88 mapNames.clear();
89 // file list
90 std::string path;
91 if ( savewindow > 0 )
92 {
93 path = physfs_saveDirectory + "maps/";
94 }
95 else
96 {
97 path = physfs_openDirectory + "maps/";
98 }
99 if ( (dir = openDataDir(path.c_str())) != NULL )
100 {
101 while ( (ent = readdir(dir)) != NULL )
102 {
103 if ( strstr(ent->d_name, ".lmp") != NULL || (!strcmp(ent->d_name, "..") || !strcmp(ent->d_name, ".")) )
104 {
105 mapNames.push_back(ent->d_name);
106 }
107 }
108 closedir(dir);
109 }
110 else
111 {
112 // could not open directory
113 printlog("failed to open map directory for viewing!\n");
114 return;
115 }
116 std::sort(mapNames.begin(), mapNames.end());
117 }
118
updateModFolderNames()119 static void updateModFolderNames()
120 {
121 modFolderNames.clear();
122 std::string path = outputdir;
123 path.append(PHYSFS_getDirSeparator()).append("mods/");
124 modFolderNames = directoryContents(path.c_str(), true, false);
125 if ( !modFolderNames.empty() )
126 {
127 std::list<std::string>::iterator it = std::find(modFolderNames.begin(), modFolderNames.end(), "..");
128 modFolderNames.erase(it);
129 std::sort(mapNames.begin(), mapNames.end());
130 }
131 }
132
writeLevelsTxt(std::string modFolder)133 void writeLevelsTxt(std::string modFolder)
134 {
135 std::string path = outputdir;
136 path.append(PHYSFS_getDirSeparator()).append("mods/").append(modFolder);
137 if ( access(path.c_str(), F_OK) == 0 )
138 {
139 std::string writeFile = modFolder + "/maps/levels.txt";
140 PHYSFS_File *physfp = PHYSFS_openWrite(writeFile.c_str());
141 if ( physfp != NULL )
142 {
143 PHYSFS_writeBytes(physfp, "map: start\n", 11);
144 PHYSFS_writeBytes(physfp, "gen: mine\n", 10);
145 PHYSFS_writeBytes(physfp, "gen: mine\n", 10);
146 PHYSFS_writeBytes(physfp, "gen: mine\n", 10);
147 PHYSFS_writeBytes(physfp, "gen: mine\n", 10);
148 PHYSFS_writeBytes(physfp, "map: minetoswamp\n", 17);
149 PHYSFS_writeBytes(physfp, "gen: swamp\n", 11);
150 PHYSFS_writeBytes(physfp, "gen: swamp\n", 11);
151 PHYSFS_writeBytes(physfp, "gen: swamp\n", 11);
152 PHYSFS_writeBytes(physfp, "gen: swamp\n", 11);
153 PHYSFS_writeBytes(physfp, "map: swamptolabyrinth\n", 22);
154 PHYSFS_writeBytes(physfp, "gen: labyrinth\n", 15);
155 PHYSFS_writeBytes(physfp, "gen: labyrinth\n", 15);
156 PHYSFS_writeBytes(physfp, "gen: labyrinth\n", 15);
157 PHYSFS_writeBytes(physfp, "gen: labyrinth\n", 15);
158 PHYSFS_writeBytes(physfp, "map: labyrinthtoruins\n", 22);
159 PHYSFS_writeBytes(physfp, "gen: ruins\n", 11);
160 PHYSFS_writeBytes(physfp, "gen: ruins\n", 11);
161 PHYSFS_writeBytes(physfp, "gen: ruins\n", 11);
162 PHYSFS_writeBytes(physfp, "gen: ruins\n", 11);
163 PHYSFS_writeBytes(physfp, "map: boss\n", 10);
164 PHYSFS_writeBytes(physfp, "gen: hell\n", 10);
165 PHYSFS_writeBytes(physfp, "gen: hell\n", 10);
166 PHYSFS_writeBytes(physfp, "gen: hell\n", 10);
167 PHYSFS_writeBytes(physfp, "map: hellboss\n", 14);
168 PHYSFS_writeBytes(physfp, "map: hamlet\n", 12);
169 PHYSFS_writeBytes(physfp, "gen: caves\n", 11);
170 PHYSFS_writeBytes(physfp, "gen: caves\n", 11);
171 PHYSFS_writeBytes(physfp, "gen: caves\n", 11);
172 PHYSFS_writeBytes(physfp, "gen: caves\n", 11);
173 PHYSFS_writeBytes(physfp, "map: cavestocitadel\n", 20);
174 PHYSFS_writeBytes(physfp, "gen: citadel\n", 13);
175 PHYSFS_writeBytes(physfp, "gen: citadel\n", 13);
176 PHYSFS_writeBytes(physfp, "gen: citadel\n", 13);
177 PHYSFS_writeBytes(physfp, "gen: citadel\n", 13);
178 PHYSFS_writeBytes(physfp, "map: sanctum", 12);
179 PHYSFS_close(physfp);
180 }
181 else
182 {
183 printlog("[PhysFS]: Failed to open %s/maps/levels.txt for writing.", path.c_str());
184 }
185 }
186 else
187 {
188 printlog("[PhysFS]: Failed to write levels.txt in %s", path.c_str());
189 }
190 }
191
192 // Corner buttons
193
buttonExit(button_t * my)194 void buttonExit(button_t* my)
195 {
196 button_t* button;
197
198 // this shouldn't work if a window is already open
199 if ( subwindow )
200 {
201 return;
202 }
203
204 menuVisible = 0;
205 subwindow = 1;
206 subx1 = xres / 2 - 128;
207 subx2 = xres / 2 + 128;
208 suby1 = yres / 2 - 32;
209 suby2 = yres / 2 + 32;
210 strcpy(subtext, "Are you sure you want to quit?\nAny unsaved work will be lost.");
211
212 button = newButton();
213 strcpy(button->label, "Yes");
214 button->x = subx1 + 32;
215 button->y = suby2 - 24;
216 button->sizex = 32;
217 button->sizey = 16;
218 button->action = &buttonExitConfirm;
219 button->visible = 1;
220 button->focused = 1;
221
222 button = newButton();
223 strcpy(button->label, "No");
224 button->x = subx2 - 56;
225 button->y = suby2 - 24;
226 button->sizex = 24;
227 button->sizey = 16;
228 button->action = &buttonCloseSubwindow;
229 button->visible = 1;
230 button->focused = 1;
231 }
232
buttonExitConfirm(button_t * my)233 void buttonExitConfirm(button_t* my)
234 {
235 mainloop = 0; // gracefully stops the game/editor
236 }
237
buttonIconify(button_t * my)238 void buttonIconify(button_t* my)
239 {
240 // aka minimize
241 SDL_MinimizeWindow(screen);
242 }
243
244 // Toolbox buttons
245
buttonTilePalette(button_t * my)246 void buttonTilePalette(button_t* my)
247 {
248 tilepalette = 1;
249 }
250
buttonSprite(button_t * my)251 void buttonSprite(button_t* my)
252 {
253 makeUndo();
254 spritepalette = 1;
255 }
256
buttonPencil(button_t * my)257 void buttonPencil(button_t* my)
258 {
259 selectedTool = 0;
260 selectedarea = false;
261 }
262
buttonPoint(button_t * my)263 void buttonPoint(button_t* my)
264 {
265 selectedTool = 1;
266 selectedarea = false;
267 }
268
buttonBrush(button_t * my)269 void buttonBrush(button_t* my)
270 {
271 selectedTool = 2;
272 selectedarea = false;
273 }
274
buttonSelect(button_t * my)275 void buttonSelect(button_t* my)
276 {
277 selectedTool = 3;
278 selectedarea = false;
279 }
280
buttonFill(button_t * my)281 void buttonFill(button_t* my)
282 {
283 selectedTool = 4;
284 selectedarea = false;
285 }
286
287 // File menu
288
buttonFile(button_t * my)289 void buttonFile(button_t* my)
290 {
291 if ( menuVisible != 1 )
292 {
293 menuVisible = 1;
294 }
295 else
296 {
297 menuVisible = 0;
298 }
299 }
300
buttonNew(button_t * my)301 void buttonNew(button_t* my)
302 {
303 button_t* button;
304
305 editproperty = 0;
306 inputstr = map.name;
307 snprintf(widthtext, 4, "%d", map.width);
308 snprintf(heighttext, 4, "%d", map.height);
309 strcpy(nametext, map.name);
310 strcpy(authortext, map.author);
311 snprintf(skyboxtext, 4, "%d", map.skybox);
312 for ( int z = 0; z < MAPFLAGS; ++z )
313 {
314 snprintf(mapflagtext[z], 4, "%d", map.flags[z]);
315 }
316 if ( map.flags[MAP_FLAG_DISABLETRAPS] > 0 )
317 {
318 strcpy(mapflagtext[MAP_FLAG_DISABLETRAPS], "[x]");
319 }
320 else
321 {
322 strcpy(mapflagtext[MAP_FLAG_DISABLETRAPS], "[ ]");
323 }
324 if ( map.flags[MAP_FLAG_DISABLEMONSTERS] > 0 )
325 {
326 strcpy(mapflagtext[MAP_FLAG_DISABLEMONSTERS], "[x]");
327 }
328 else
329 {
330 strcpy(mapflagtext[MAP_FLAG_DISABLEMONSTERS], "[ ]");
331 }
332 if ( map.flags[MAP_FLAG_DISABLELOOT] > 0 )
333 {
334 strcpy(mapflagtext[MAP_FLAG_DISABLELOOT], "[x]");
335 }
336 else
337 {
338 strcpy(mapflagtext[MAP_FLAG_DISABLELOOT], "[ ]");
339 }
340 if ( (map.flags[MAP_FLAG_GENBYTES3] >> 24) & static_cast<int>(0xFF) )
341 {
342 strcpy(mapflagtext[MAP_FLAG_DISABLEDIGGING], "[x]");
343 }
344 else
345 {
346 strcpy(mapflagtext[MAP_FLAG_DISABLEDIGGING], "[ ]");
347 }
348 if ( (map.flags[MAP_FLAG_GENBYTES3] >> 16) & static_cast<int>(0xFF) )
349 {
350 strcpy(mapflagtext[MAP_FLAG_DISABLETELEPORT], "[x]");
351 }
352 else
353 {
354 strcpy(mapflagtext[MAP_FLAG_DISABLETELEPORT], "[ ]");
355 }
356 if ( (map.flags[MAP_FLAG_GENBYTES3] >> 8) & static_cast<int>(0xFF) )
357 {
358 strcpy(mapflagtext[MAP_FLAG_DISABLELEVITATION], "[x]");
359 }
360 else
361 {
362 strcpy(mapflagtext[MAP_FLAG_DISABLELEVITATION], "[ ]");
363 }
364 if ( (map.flags[MAP_FLAG_GENBYTES3] >> 0) & static_cast<int>(0xFF) )
365 {
366 strcpy(mapflagtext[MAP_FLAG_GENADJACENTROOMS], "[x]");
367 }
368 else
369 {
370 strcpy(mapflagtext[MAP_FLAG_GENADJACENTROOMS], "[ ]");
371 }
372 if ( (map.flags[MAP_FLAG_GENBYTES4] >> 24) & static_cast<int>(0xFF) )
373 {
374 strcpy(mapflagtext[MAP_FLAG_DISABLEOPENING], "[x]");
375 }
376 else
377 {
378 strcpy(mapflagtext[MAP_FLAG_DISABLEOPENING], "[ ]");
379 }
380 if ( (map.flags[MAP_FLAG_GENBYTES4] >> 16) & static_cast<int>(0xFF) )
381 {
382 strcpy(mapflagtext[MAP_FLAG_DISABLEMESSAGES], "[x]");
383 }
384 else
385 {
386 strcpy(mapflagtext[MAP_FLAG_DISABLEMESSAGES], "[ ]");
387 }
388 if ( (map.flags[MAP_FLAG_GENBYTES4] >> 8) & static_cast<int>(0xFF) )
389 {
390 strcpy(mapflagtext[MAP_FLAG_DISABLEHUNGER], "[x]");
391 }
392 else
393 {
394 strcpy(mapflagtext[MAP_FLAG_DISABLEHUNGER], "[ ]");
395 }
396 cursorflash = ticks;
397 menuVisible = 0;
398 subwindow = 1;
399 newwindow = 1;
400 subx1 = xres / 2 - 200;
401 subx2 = xres / 2 + 200;
402 suby1 = yres / 2 - 200;
403 suby2 = yres / 2 + 200;
404 strcpy(subtext, "New map:");
405
406 button = newButton();
407 strcpy(button->label, "Create");
408 button->x = subx2 - 64;
409 button->y = suby2 - 48;
410 button->sizex = 56;
411 button->sizey = 16;
412 button->action = &buttonNewConfirm;
413 button->visible = 1;
414 button->focused = 1;
415
416 button = newButton();
417 strcpy(button->label, "Cancel");
418 button->x = subx2 - 64;
419 button->y = suby2 - 24;
420 button->sizex = 56;
421 button->sizey = 16;
422 button->action = &buttonCloseSubwindow;
423 button->visible = 1;
424 button->focused = 1;
425
426 button = newButton();
427 strcpy(button->label, "X");
428 button->x = subx2 - 16;
429 button->y = suby1;
430 button->sizex = 16;
431 button->sizey = 16;
432 button->action = &buttonCloseSubwindow;
433 button->visible = 1;
434 button->focused = 1;
435 }
436
buttonNewConfirm(button_t * my)437 void buttonNewConfirm(button_t* my)
438 {
439 int x, y, z, c;
440 clearUndos();
441 free(map.tiles);
442 list_FreeAll(map.entities);
443 strcpy(map.name, nametext);
444 strcpy(map.author, authortext);
445 map.skybox = atoi(skyboxtext);
446 for ( z = 0; z < MAPFLAGS; ++z )
447 {
448 if ( z == MAP_FLAG_DISABLETRAPS )
449 {
450 if ( !strncmp(mapflagtext[MAP_FLAG_DISABLETRAPS], "[x]", 3) )
451 {
452 map.flags[MAP_FLAG_DISABLETRAPS] = 1;
453 }
454 else
455 {
456 map.flags[MAP_FLAG_DISABLETRAPS] = 0;
457 }
458 }
459 else if ( z == MAP_FLAG_DISABLEMONSTERS )
460 {
461 if ( !strncmp(mapflagtext[MAP_FLAG_DISABLEMONSTERS], "[x]", 3) )
462 {
463 map.flags[MAP_FLAG_DISABLEMONSTERS] = 1;
464 }
465 else
466 {
467 map.flags[MAP_FLAG_DISABLEMONSTERS] = 0;
468 }
469 }
470 else if ( z == MAP_FLAG_DISABLELOOT )
471 {
472 if ( !strncmp(mapflagtext[MAP_FLAG_DISABLELOOT], "[x]", 3) )
473 {
474 map.flags[MAP_FLAG_DISABLELOOT] = 1;
475 }
476 else
477 {
478 map.flags[MAP_FLAG_DISABLELOOT] = 0;
479 }
480 }
481 else if ( z == MAP_FLAG_GENBYTES3 )
482 {
483 map.flags[z] = 0;
484 if ( !strncmp(mapflagtext[MAP_FLAG_DISABLEDIGGING], "[x]", 3) )
485 {
486 map.flags[z] |= (1 << 24) & 0xFF;
487 }
488 if ( !strncmp(mapflagtext[MAP_FLAG_DISABLETELEPORT], "[x]", 3) )
489 {
490 map.flags[z] |= (1 << 16) & 0xFF;
491 }
492 if ( !strncmp(mapflagtext[MAP_FLAG_DISABLELEVITATION], "[x]", 3) )
493 {
494 map.flags[z] |= (1 << 8) & 0xFF;
495 }
496 if ( !strncmp(mapflagtext[MAP_FLAG_GENADJACENTROOMS], "[x]", 3) )
497 {
498 map.flags[z] |= (1 << 0) & 0xFF;
499 }
500 }
501 else if ( z == MAP_FLAG_GENBYTES4 )
502 {
503 map.flags[z] = 0;
504 if ( !strncmp(mapflagtext[MAP_FLAG_DISABLEOPENING], "[x]", 3) )
505 {
506 map.flags[z] |= (1 << 24) & 0xFF;
507 }
508 if ( !strncmp(mapflagtext[MAP_FLAG_DISABLEMESSAGES], "[x]", 3) )
509 {
510 map.flags[z] |= (1 << 16) & 0xFF;
511 }
512 if ( !strncmp(mapflagtext[MAP_FLAG_DISABLEHUNGER], "[x]", 3) )
513 {
514 map.flags[z] |= (1 << 8) & 0xFF;
515 }
516 }
517 else
518 {
519 map.flags[z] = atoi(mapflagtext[z]);
520 }
521 }
522 map.width = atoi(widthtext);
523 map.height = atoi(heighttext);
524 map.width = std::min(std::max(MINWIDTH, map.width), MAXWIDTH);
525 map.height = std::min(std::max(MINHEIGHT, map.height), MAXHEIGHT);
526 map.tiles = (int*) malloc(sizeof(int) * MAPLAYERS * map.height * map.width);
527 for ( z = 0; z < MAPLAYERS; z++ )
528 {
529 for ( y = 0; y < map.height; y++ )
530 {
531 for ( x = 0; x < map.width; x++ )
532 {
533 if ( z == OBSTACLELAYER )
534 {
535 if (x == 0 || y == 0 || x == map.width - 1 || y == map.height - 1)
536 {
537 map.tiles[z + y * MAPLAYERS + x * MAPLAYERS * map.height] = 2;
538 }
539 else
540 {
541 map.tiles[z + y * MAPLAYERS + x * MAPLAYERS * map.height] = 0;
542 }
543 }
544 else
545 {
546 map.tiles[z + y * MAPLAYERS + x * MAPLAYERS * map.height] = 1;
547 }
548 }
549 }
550 }
551 if ( vismap != NULL )
552 {
553 free(vismap);
554 }
555 vismap = (bool*) malloc(sizeof(bool) * map.width * map.height);
556 if ( lightmap != NULL )
557 {
558 free(lightmap);
559 }
560 if ( lightmapSmoothed != NULL )
561 {
562 free(lightmapSmoothed);
563 }
564 lightmap = (int*) malloc(sizeof(Sint32) * map.width * map.height);
565 lightmapSmoothed = (int*)malloc(sizeof(Sint32) * map.width * map.height);
566 for (c = 0; c < map.width * map.height; c++ )
567 {
568 lightmap[c] = 0;
569 lightmapSmoothed[c] = 0;
570 }
571 strcpy(message, " Created a new map.");
572 filename[0] = 0;
573 oldfilename[0] = 0;
574 messagetime = 60;
575 buttonCloseSubwindow(my);
576 }
577
buttonOpen(button_t * my)578 void buttonOpen(button_t* my)
579 {
580 button_t* button;
581 DIR* dir = NULL;
582 struct dirent* ent = NULL;
583 unsigned long c = 0;
584
585 inputstr = filename;
586 cursorflash = ticks;
587 menuVisible = 0;
588 subwindow = 1;
589 openwindow = 1;
590 slidery = 0;
591 selectedFile = 0;
592 subx1 = xres / 2 - 160;
593 subx2 = xres / 2 + 160;
594 suby1 = yres / 2 - 120;
595 suby2 = yres / 2 + 120;
596 strcpy(subtext, "Open file:");
597
598 button = newButton();
599 strcpy(button->label, " Open ");
600 button->x = subx2 - 64;
601 button->y = suby2 - 48;
602 button->sizex = 56;
603 button->sizey = 16;
604 button->action = &buttonOpenConfirm;
605 button->visible = 1;
606 button->focused = 1;
607
608 button = newButton();
609 strcpy(button->label, "Cancel");
610 button->x = subx2 - 64;
611 button->y = suby2 - 24;
612 button->sizex = 56;
613 button->sizey = 16;
614 button->action = &buttonCloseSubwindow;
615 button->visible = 1;
616 button->focused = 1;
617
618 button = newButton();
619 strcpy(button->label, "X");
620 button->x = subx2 - 16;
621 button->y = suby1;
622 button->sizex = 16;
623 button->sizey = 16;
624 button->action = &buttonCloseSubwindow;
625 button->visible = 1;
626 button->focused = 1;
627
628 updateMapNames();
629 }
630
buttonSetSaveDirectoryFolder(button_t * my)631 void buttonSetSaveDirectoryFolder(button_t* my)
632 {
633 std::string filepath = outputdir;
634 bool inModFolder = false;
635 if ( strcmp(foldername, ".") == 0 || strcmp(foldername, "") == 0 )
636 {
637 physfs_saveDirectory = BASE_DATA_DIR;
638 }
639 else if ( strcmp(foldername, BASE_DATA_DIR) )
640 {
641 filepath.append(PHYSFS_getDirSeparator()).append("mods/").append(foldername);
642 physfs_saveDirectory = filepath + PHYSFS_getDirSeparator();
643 inModFolder = true;
644 }
645 else
646 {
647 physfs_saveDirectory = BASE_DATA_DIR;
648 }
649 if ( access(physfs_saveDirectory.c_str(), F_OK) == 0 )
650 {
651 printlog("[PhysFS]: Changed save directory folder to %s", physfs_saveDirectory.c_str());
652 }
653 else if ( inModFolder )
654 {
655 printlog("[PhysFS]: Directory %s does not exist. Creating new mod folder...", physfs_saveDirectory.c_str());
656
657 if ( PHYSFS_mkdir(foldername) )
658 {
659 std::string dir = foldername;
660 std::string folder = "/books";
661 PHYSFS_mkdir((dir + folder).c_str());
662 folder = "/editor";
663 PHYSFS_mkdir((dir + folder).c_str());
664
665 folder = "/images";
666 PHYSFS_mkdir((dir + folder).c_str());
667 std::string subfolder = "/sprites";
668 PHYSFS_mkdir((dir + folder + subfolder).c_str());
669 subfolder = "/system";
670 PHYSFS_mkdir((dir + folder + subfolder).c_str());
671 subfolder = "/tiles";
672 PHYSFS_mkdir((dir + folder + subfolder).c_str());
673
674 folder = "/items";
675 PHYSFS_mkdir((dir + folder).c_str());
676 subfolder = "/images";
677 PHYSFS_mkdir((dir + folder + subfolder).c_str());
678
679 folder = "/lang";
680 PHYSFS_mkdir((dir + folder).c_str());
681 folder = "/maps";
682 PHYSFS_mkdir((dir + folder).c_str());
683 writeLevelsTxt(foldername);
684
685 folder = "/models";
686 PHYSFS_mkdir((dir + folder).c_str());
687 subfolder = "/creatures";
688 PHYSFS_mkdir((dir + folder + subfolder).c_str());
689 subfolder = "/decorations";
690 PHYSFS_mkdir((dir + folder + subfolder).c_str());
691 subfolder = "/doors";
692 PHYSFS_mkdir((dir + folder + subfolder).c_str());
693 subfolder = "/items";
694 PHYSFS_mkdir((dir + folder + subfolder).c_str());
695 subfolder = "/particles";
696 PHYSFS_mkdir((dir + folder + subfolder).c_str());
697
698 folder = "/music";
699 PHYSFS_mkdir((dir + folder).c_str());
700 folder = "/sound";
701 PHYSFS_mkdir((dir + folder).c_str());
702 printlog("[PhysFS]: New folder %s created.", physfs_saveDirectory.c_str());
703 strcpy(message, " Created a new mod folder.");
704 messagetime = 60;
705 }
706 else
707 {
708 physfs_saveDirectory = BASE_DATA_DIR;
709 printlog("[PhysFS]: Unable to create mods/ folder %s.", physfs_saveDirectory.c_str());
710 }
711 }
712 updateModFolderNames();
713 }
714
buttonSetOpenDirectoryFolder(button_t * my)715 void buttonSetOpenDirectoryFolder(button_t* my)
716 {
717 if ( PHYSFS_unmount(physfs_openDirectory.c_str()) )
718 {
719 std::string filepath = outputdir;
720 if ( strcmp(foldername, ".") == 0 || strcmp(foldername, "") == 0 )
721 {
722 physfs_openDirectory = BASE_DATA_DIR;
723 }
724 else if ( strcmp(foldername, BASE_DATA_DIR) )
725 {
726 filepath.append(PHYSFS_getDirSeparator()).append("mods/").append(foldername);
727 physfs_openDirectory = filepath + PHYSFS_getDirSeparator();
728 }
729 else
730 {
731 physfs_openDirectory = BASE_DATA_DIR;
732 }
733 if ( PHYSFS_mount(physfs_openDirectory.c_str(), NULL, 1) )
734 {
735 printlog("[PhysFS]: Changed open directory folder to %s", physfs_openDirectory.c_str());
736 }
737 else
738 {
739 printlog("[PhysFS]: Failed to change open directory folder to %s", physfs_openDirectory.c_str());
740 physfs_openDirectory = BASE_DATA_DIR;
741 PHYSFS_mount(BASE_DATA_DIR, NULL, 1);
742 }
743 }
744 else
745 {
746 printlog("[PhysFS]: Failed to change open directory folder.");
747 }
748 updateModFolderNames();
749 }
750
buttonPHYSFSDirDefault(button_t * my)751 void buttonPHYSFSDirDefault(button_t* my)
752 {
753 strcpy(foldername, BASE_DATA_DIR);
754 buttonSetSaveDirectoryFolder(nullptr);
755 buttonSetOpenDirectoryFolder(nullptr);
756 }
757
buttonOpenDirectory(button_t * my)758 void buttonOpenDirectory(button_t* my)
759 {
760 button_t* button;
761
762 inputstr = foldername;
763 cursorflash = ticks;
764 menuVisible = 0;
765 subwindow = 1;
766 openwindow = 2;
767 slidery = 0;
768 selectedFile = 0;
769 subx1 = xres / 2 - 160;
770 subx2 = xres / 2 + 160;
771 suby1 = yres / 2 - 150;
772 suby2 = yres / 2 + 150;
773 strcpy(subtext, "Choose mod folders to read/write maps:");
774
775 button = newButton();
776 strcpy(button->label, "Set as save directory");
777 button->x = subx2 - 16 - strlen(button->label) * TTF12_WIDTH;
778 button->y = suby2 - 90;
779 button->sizex = strlen(button->label) * TTF12_WIDTH + 8;
780 button->sizey = 16;
781 button->action = &buttonSetSaveDirectoryFolder;
782 button->visible = 1;
783 button->focused = 1;
784
785 button = newButton();
786 strcpy(button->label, "Reset to default");
787 button->x = subx2 - 16 - strlen(button->label) * TTF12_WIDTH;
788 button->y = suby2 - 54;
789 button->sizex = strlen(button->label) * TTF12_WIDTH + 8;
790 button->sizey = 16;
791 button->action = &buttonPHYSFSDirDefault;
792 button->visible = 1;
793 button->focused = 1;
794
795 button = newButton();
796 strcpy(button->label, "Set as load directory");
797 button->x = subx2 - 16 - strlen(button->label) * TTF12_WIDTH;
798 button->y = suby2 - 72;
799 button->sizex = strlen(button->label) * TTF12_WIDTH + 8;
800 button->sizey = 16;
801 button->action = &buttonSetOpenDirectoryFolder;
802 button->visible = 1;
803 button->focused = 1;
804
805 button = newButton();
806 strcpy(button->label, "X");
807 button->x = subx2 - 16;
808 button->y = suby1;
809 button->sizex = 16;
810 button->sizey = 16;
811 button->action = &buttonCloseSubwindow;
812 button->visible = 1;
813 button->focused = 1;
814
815 updateModFolderNames();
816 }
817
buttonOpenConfirm(button_t * my)818 void buttonOpenConfirm(button_t* my)
819 {
820 int c, c2;
821 clearUndos();
822 strcpy(oldfilename, filename);
823 strcpy(message, "");
824 for ( c = 0; c < 32; c++ )
825 {
826 if (filename[c] == 0)
827 {
828 break;
829 }
830 }
831 /*for ( c2 = 0; c2 < 32 - c; c2++ )
832 {
833 strcat(message, " ");
834 }*/
835 std::string fullMapName = physfsFormatMapName(filename);
836 printlog("opening map file '%s'...\n", fullMapName.c_str());
837 if (loadMap(fullMapName.c_str(), &map, map.entities, map.creatures) == -1)
838 {
839 strcat(message, "Failed to open ");
840 strcat(message, filename);
841 }
842 else
843 {
844 strcat(message, "Opened '");
845 strcat(message, filename);
846 strcat(message, "'");
847 }
848 messagetime = 60; // 60*50 ms = 3000 ms (3 seconds)
849 buttonCloseSubwindow(my);
850 }
851
buttonSave(button_t * my)852 void buttonSave(button_t* my)
853 {
854 int c, c2;
855 menuVisible = 0;
856 strcpy(oldfilename, filename);
857 inputstr = filename;
858 if (filename[0] == 0)
859 {
860 buttonSaveAs(my);
861 }
862 else
863 {
864 strcpy(message, "");
865 for ( c = 0; c < 32; c++ )
866 {
867 if (filename[c] == 0)
868 {
869 break;
870 }
871 }
872 /*for ( c2 = 0; c2 < 32 - c; c2++ )
873 {
874 strcat(message, " ");
875 }*/
876 printlog("saving map file '%s'...\n", filename);
877
878 std::string path = physfs_saveDirectory;
879 path.append("maps/").append(filename);
880 if (saveMap(path.c_str()))
881 {
882 strcat(message, "Failed to save ");
883 strcat(message, path.c_str());
884 }
885 else
886 {
887 strcat(message, "Saved '");
888 strcat(message, path.c_str());
889 strcat(message, "'");
890 }
891 messagetime = 60; // 60*50 ms = 3000 ms (3 seconds)
892 buttonCloseSubwindow(my);
893 }
894 }
895
buttonSaveAs(button_t * my)896 void buttonSaveAs(button_t* my)
897 {
898 button_t* button;
899
900 cursorflash = ticks;
901 menuVisible = 0;
902 subwindow = 1;
903 savewindow = 1;
904 slidery = 0;
905 selectedFile = 0;
906 subx1 = xres / 2 - 160;
907 subx2 = xres / 2 + 160;
908 suby1 = yres / 2 - 120;
909 suby2 = yres / 2 + 120;
910 strcpy(subtext, "Save file:");
911
912 button = newButton();
913 strcpy(button->label, " Save ");
914 button->x = subx2 - 64;
915 button->y = suby2 - 48;
916 button->sizex = 56;
917 button->sizey = 16;
918 button->action = &buttonSave;
919 button->visible = 1;
920 button->focused = 1;
921
922 button = newButton();
923 strcpy(button->label, "Cancel");
924 button->x = subx2 - 64;
925 button->y = suby2 - 24;
926 button->sizex = 56;
927 button->sizey = 16;
928 button->action = &buttonCloseSubwindow;
929 button->visible = 1;
930 button->focused = 1;
931
932 button = newButton();
933 strcpy(button->label, "X");
934 button->x = subx2 - 16;
935 button->y = suby1;
936 button->sizex = 16;
937 button->sizey = 16;
938 button->action = &buttonCloseSubwindow;
939 button->visible = 1;
940 button->focused = 1;
941
942 updateMapNames();
943 }
944
945 // Edit menu
946
buttonEdit(button_t * my)947 void buttonEdit(button_t* my)
948 {
949 if ( menuVisible != 2 )
950 {
951 menuVisible = 2;
952 }
953 else
954 {
955 menuVisible = 0;
956 }
957 }
958
buttonCut(button_t * my)959 void buttonCut(button_t* my)
960 {
961 menuVisible = 0;
962 if ( !selectedarea )
963 {
964 return;
965 }
966 buttonCopy(my);
967 selectedarea = true;
968 buttonDelete(my);
969 }
970
buttonCopy(button_t * my)971 void buttonCopy(button_t* my)
972 {
973 menuVisible = 0;
974 int x, y;
975
976 // copy the selected tiles
977 if (selectedarea && !pasting)
978 {
979 copymap.width = selectedarea_x2 - selectedarea_x1 + 1;
980 copymap.height = selectedarea_y2 - selectedarea_y1 + 1;
981 if ( copymap.tiles != NULL )
982 {
983 free(copymap.tiles);
984 }
985 copymap.tiles = (Sint32*) malloc(sizeof(Sint32) * copymap.width * copymap.height * MAPLAYERS);
986 memset(copymap.tiles, 0, sizeof(Sint32)*copymap.width * copymap.height * MAPLAYERS);
987 for ( x = 0; x < copymap.width; x++ )
988 {
989 for ( y = 0; y < copymap.height; y++ )
990 {
991 copymap.tiles[drawlayer + y * MAPLAYERS + x * MAPLAYERS * copymap.height] = map.tiles[drawlayer + (y + selectedarea_y1) * MAPLAYERS + (x + selectedarea_x1) * MAPLAYERS * map.height];
992 }
993 }
994 copymap.name[0] = drawlayer;
995 }
996 selectedarea = false;
997 }
998
buttonPaste(button_t * my)999 void buttonPaste(button_t* my)
1000 {
1001 menuVisible = 0;
1002
1003 // paste the selected tiles
1004 if ( copymap.tiles != NULL )
1005 {
1006 pasting = true;
1007 selectedarea = false;
1008 }
1009 }
1010
buttonDelete(button_t * my)1011 void buttonDelete(button_t* my)
1012 {
1013 menuVisible = 0;
1014 makeUndo();
1015
1016 // delete the selected entity, if there is one
1017 if (selectedEntity != NULL)
1018 {
1019 list_RemoveNode(selectedEntity->mynode);
1020 selectedEntity = NULL;
1021 lastSelectedEntity = NULL;
1022 }
1023 if (selectedarea)
1024 {
1025 // delete all selected tiles
1026 int x, y;
1027 for ( x = selectedarea_x1; x <= selectedarea_x2; x++ )
1028 {
1029 for ( y = selectedarea_y1; y <= selectedarea_y2; y++ )
1030 {
1031 map.tiles[drawlayer + y * MAPLAYERS + x * MAPLAYERS * map.height] = 0;
1032 }
1033 }
1034 selectedarea = false;
1035 }
1036 }
1037
buttonCycleSprites(button_t * my)1038 void buttonCycleSprites(button_t* my)
1039 {
1040 SDL_Rect pos;
1041 char tmp[4];
1042 Entity* entity = nullptr;
1043 Entity* lastEntity = nullptr;
1044 bool entityWasSelected = false;
1045 for ( node_t* node = map.entities->first; node != nullptr; node = node->next )
1046 {
1047 entity = (Entity*)node->element;
1048 pos.x = entity->x * (TEXTURESIZE / 16) - camx;
1049 pos.y = entity->y * (TEXTURESIZE / 16) - camy;
1050 if ( (omousex / TEXTURESIZE) * 32 == pos.x && (omousey / TEXTURESIZE) * 32 == pos.y )
1051 {
1052 // set lastEntity to each entity on the tile.
1053 lastEntity = entity;
1054 }
1055 }
1056
1057 if ( lastEntity != nullptr )
1058 {
1059 if ( selectedEntity )
1060 {
1061 entityWasSelected = true;
1062 }
1063
1064 selectedEntity = nullptr;
1065 lastSelectedEntity = nullptr;
1066
1067 // create new entity on the list, copying and removing the previous last one.
1068 entity = newEntity(lastEntity->sprite, 0, map.entities, nullptr);
1069 setSpriteAttributes(entity, lastEntity, lastEntity);
1070 list_RemoveNode(lastEntity->mynode);
1071
1072 if ( entityWasSelected )
1073 {
1074 selectedEntity = entity;
1075 lastSelectedEntity = selectedEntity;
1076 }
1077 }
1078 }
1079
buttonSelectAll(button_t * my)1080 void buttonSelectAll(button_t* my)
1081 {
1082 menuVisible = 0;
1083 selectedTool = 3;
1084 selectedarea = true;
1085 selectingspace = false;
1086 selectedarea_x1 = 0;
1087 selectedarea_x2 = map.width - 1;
1088 selectedarea_y1 = 0;
1089 selectedarea_y2 = map.height - 1;
1090 }
1091
buttonUndo(button_t * my)1092 void buttonUndo(button_t* my)
1093 {
1094 menuVisible = 0;
1095 undo();
1096 }
1097
buttonRedo(button_t * my)1098 void buttonRedo(button_t* my)
1099 {
1100 menuVisible = 0;
1101 redo();
1102 }
1103
1104 // View menu
1105
buttonView(button_t * my)1106 void buttonView(button_t* my)
1107 {
1108 if ( menuVisible != 3 )
1109 {
1110 menuVisible = 3;
1111 }
1112 else
1113 {
1114 menuVisible = 0;
1115 }
1116 }
1117
buttonToolbox(button_t * my)1118 void buttonToolbox(button_t* my)
1119 {
1120 toolbox = (toolbox == 0);
1121 butTilePalette->visible = (butTilePalette->visible == 0);
1122 butPencil->visible = (butPencil->visible == 0);
1123 butSprite->visible = (butSprite->visible == 0);
1124 butPoint->visible = (butPoint->visible == 0);
1125 butBrush->visible = (butBrush->visible == 0);
1126 butSelect->visible = (butSelect->visible == 0);
1127 butFill->visible = (butFill->visible == 0);
1128 }
1129
buttonStatusBar(button_t * my)1130 void buttonStatusBar(button_t* my)
1131 {
1132 statusbar = (statusbar == 0);
1133 }
1134
buttonAllLayers(button_t * my)1135 void buttonAllLayers(button_t* my)
1136 {
1137 alllayers = (alllayers == 0);
1138 }
1139
buttonViewSprites(button_t * my)1140 void buttonViewSprites(button_t* my)
1141 {
1142 viewsprites = (viewsprites == 0);
1143 }
1144
buttonGrid(button_t * my)1145 void buttonGrid(button_t* my)
1146 {
1147 showgrid = (showgrid == 0);
1148 }
1149
button3DMode(button_t * my)1150 void button3DMode(button_t* my)
1151 {
1152 mode3d = (mode3d == false);
1153 }
1154
buttonHoverText(button_t * my)1155 void buttonHoverText(button_t* my)
1156 {
1157 hovertext = (hovertext == false);
1158 }
1159
1160 // Map menu
1161
buttonMap(button_t * my)1162 void buttonMap(button_t* my)
1163 {
1164 if ( menuVisible != 4 )
1165 {
1166 menuVisible = 4;
1167 }
1168 else
1169 {
1170 menuVisible = 0;
1171 }
1172 }
1173
buttonAttributes(button_t * my)1174 void buttonAttributes(button_t* my)
1175 {
1176 button_t* button;
1177
1178 editproperty = 0;
1179 inputstr = map.name;
1180 snprintf(widthtext, 4, "%d", map.width);
1181 snprintf(heighttext, 4, "%d", map.height);
1182 strcpy(nametext, map.name);
1183 strcpy(authortext, map.author);
1184 snprintf(skyboxtext, 4, "%d", map.skybox);
1185 for ( int z = 0; z < MAPFLAGS; ++z )
1186 {
1187 if ( z < MAP_FLAG_GENBYTES1 || z > MAP_FLAG_GENBYTES6 )
1188 {
1189 snprintf(mapflagtext[z], 4, "%d", map.flags[z]);
1190 }
1191 }
1192
1193 snprintf(mapflagtext[MAP_FLAG_GENTOTALMIN], 4, "%d", (map.flags[MAP_FLAG_GENBYTES1] >> 24) & static_cast<int>(0xFF));
1194 snprintf(mapflagtext[MAP_FLAG_GENTOTALMAX], 4, "%d", (map.flags[MAP_FLAG_GENBYTES1] >> 16) & static_cast<int>(0xFF));
1195 snprintf(mapflagtext[MAP_FLAG_GENMONSTERMIN], 4, "%d", (map.flags[MAP_FLAG_GENBYTES1] >> 8) & static_cast<int>(0xFF));
1196 snprintf(mapflagtext[MAP_FLAG_GENMONSTERMAX], 4, "%d", (map.flags[MAP_FLAG_GENBYTES1] >> 0) & static_cast<int>(0xFF));
1197 snprintf(mapflagtext[MAP_FLAG_GENLOOTMIN], 4, "%d", (map.flags[MAP_FLAG_GENBYTES2] >> 24) & static_cast<int>(0xFF));
1198 snprintf(mapflagtext[MAP_FLAG_GENLOOTMAX], 4, "%d", (map.flags[MAP_FLAG_GENBYTES2] >> 16) & static_cast<int>(0xFF));
1199 snprintf(mapflagtext[MAP_FLAG_GENDECORATIONMIN], 4, "%d", (map.flags[MAP_FLAG_GENBYTES2] >> 8) & static_cast<int>(0xFF));
1200 snprintf(mapflagtext[MAP_FLAG_GENDECORATIONMAX], 4, "%d", (map.flags[MAP_FLAG_GENBYTES2] >> 0) & static_cast<int>(0xFF));
1201 if ( (map.flags[MAP_FLAG_GENBYTES3] >> 24) & static_cast<int>(0xFF) )
1202 {
1203 strcpy(mapflagtext[MAP_FLAG_DISABLEDIGGING], "[x]");
1204 }
1205 else
1206 {
1207 strcpy(mapflagtext[MAP_FLAG_DISABLEDIGGING], "[ ]");
1208 }
1209
1210 if ( (map.flags[MAP_FLAG_GENBYTES3] >> 16) & static_cast<int>(0xFF) )
1211 {
1212 strcpy(mapflagtext[MAP_FLAG_DISABLETELEPORT], "[x]");
1213 }
1214 else
1215 {
1216 strcpy(mapflagtext[MAP_FLAG_DISABLETELEPORT], "[ ]");
1217 }
1218
1219 if ( (map.flags[MAP_FLAG_GENBYTES3] >> 8) & static_cast<int>(0xFF) )
1220 {
1221 strcpy(mapflagtext[MAP_FLAG_DISABLELEVITATION], "[x]");
1222 }
1223 else
1224 {
1225 strcpy(mapflagtext[MAP_FLAG_DISABLELEVITATION], "[ ]");
1226 }
1227
1228 if ( (map.flags[MAP_FLAG_GENBYTES3] >> 0) & static_cast<int>(0xFF) )
1229 {
1230 strcpy(mapflagtext[MAP_FLAG_GENADJACENTROOMS], "[x]");
1231 }
1232 else
1233 {
1234 strcpy(mapflagtext[MAP_FLAG_GENADJACENTROOMS], "[ ]");
1235 }
1236 if ( (map.flags[MAP_FLAG_GENBYTES4] >> 24) & static_cast<int>(0xFF) )
1237 {
1238 strcpy(mapflagtext[MAP_FLAG_DISABLEOPENING], "[x]");
1239 }
1240 else
1241 {
1242 strcpy(mapflagtext[MAP_FLAG_DISABLEOPENING], "[ ]");
1243 }
1244 if ( (map.flags[MAP_FLAG_GENBYTES4] >> 16) & static_cast<int>(0xFF) )
1245 {
1246 strcpy(mapflagtext[MAP_FLAG_DISABLEMESSAGES], "[x]");
1247 }
1248 else
1249 {
1250 strcpy(mapflagtext[MAP_FLAG_DISABLEMESSAGES], "[ ]");
1251 }
1252 if ( (map.flags[MAP_FLAG_GENBYTES4] >> 8) & static_cast<int>(0xFF) )
1253 {
1254 strcpy(mapflagtext[MAP_FLAG_DISABLEHUNGER], "[x]");
1255 }
1256 else
1257 {
1258 strcpy(mapflagtext[MAP_FLAG_DISABLEHUNGER], "[ ]");
1259 }
1260
1261 if ( map.flags[MAP_FLAG_DISABLETRAPS] > 0 )
1262 {
1263 strcpy(mapflagtext[MAP_FLAG_DISABLETRAPS], "[x]");
1264 }
1265 else
1266 {
1267 strcpy(mapflagtext[MAP_FLAG_DISABLETRAPS], "[ ]");
1268 }
1269 if ( map.flags[MAP_FLAG_DISABLEMONSTERS] > 0 )
1270 {
1271 strcpy(mapflagtext[MAP_FLAG_DISABLEMONSTERS], "[x]");
1272 }
1273 else
1274 {
1275 strcpy(mapflagtext[MAP_FLAG_DISABLEMONSTERS], "[ ]");
1276 }
1277 if ( map.flags[MAP_FLAG_DISABLELOOT] > 0 )
1278 {
1279 strcpy(mapflagtext[MAP_FLAG_DISABLELOOT], "[x]");
1280 }
1281 else
1282 {
1283 strcpy(mapflagtext[MAP_FLAG_DISABLELOOT], "[ ]");
1284 }
1285
1286 cursorflash = ticks;
1287 menuVisible = 0;
1288 subwindow = 1;
1289 newwindow = 1;
1290 subx1 = xres / 2 - 200;
1291 subx2 = xres / 2 + 200;
1292 suby1 = yres / 2 - 200;
1293 suby2 = yres / 2 + 200;
1294 strcpy(subtext, "Map properties:");
1295
1296 button = newButton();
1297 strcpy(button->label, " OK ");
1298 button->x = subx2 - 64;
1299 button->y = suby2 - 48;
1300 button->sizex = 56;
1301 button->sizey = 16;
1302 button->action = &buttonAttributesConfirm;
1303 button->visible = 1;
1304 button->focused = 1;
1305
1306 button = newButton();
1307 strcpy(button->label, "Cancel");
1308 button->x = subx2 - 64;
1309 button->y = suby2 - 24;
1310 button->sizex = 56;
1311 button->sizey = 16;
1312 button->action = &buttonCloseSubwindow;
1313 button->visible = 1;
1314 button->focused = 1;
1315
1316 button = newButton();
1317 strcpy(button->label, "X");
1318 button->x = subx2 - 16;
1319 button->y = suby1;
1320 button->sizex = 16;
1321 button->sizey = 16;
1322 button->action = &buttonCloseSubwindow;
1323 button->visible = 1;
1324 button->focused = 1;
1325 }
1326
buttonAttributesConfirm(button_t * my)1327 void buttonAttributesConfirm(button_t* my)
1328 {
1329 int x, y, z, c;
1330 map_t mapcopy;
1331 makeUndo();
1332
1333 // make a copy of the current map
1334 mapcopy.width = map.width;
1335 mapcopy.height = map.height;
1336 mapcopy.tiles = (int*) malloc(sizeof(int) * MAPLAYERS * mapcopy.width * mapcopy.height);
1337 for ( z = 0; z < MAPLAYERS; z++ )
1338 {
1339 for ( y = 0; y < map.height; y++ )
1340 {
1341 for ( x = 0; x < map.width; x++ )
1342 {
1343 mapcopy.tiles[z + y * MAPLAYERS + x * MAPLAYERS * map.height] = map.tiles[z + y * MAPLAYERS + x * MAPLAYERS * mapcopy.height];
1344 }
1345 }
1346 }
1347
1348 // allocate memory for a new map
1349 free(map.tiles);
1350 map.width = atoi(widthtext);
1351 map.height = atoi(heighttext);
1352 map.width = std::min(std::max(MINWIDTH, map.width), MAXWIDTH);
1353 map.height = std::min(std::max(MINHEIGHT, map.height), MAXHEIGHT);
1354 map.skybox = atoi(skyboxtext);
1355 if ( map.skybox > numtiles )
1356 {
1357 map.skybox = 0;
1358 }
1359 map.flags[MAP_FLAG_CEILINGTILE] = atoi(mapflagtext[MAP_FLAG_CEILINGTILE]);
1360 if ( map.flags[MAP_FLAG_CEILINGTILE] >= numtiles )
1361 {
1362 map.flags[MAP_FLAG_CEILINGTILE] = 0;
1363 }
1364
1365 // start storing some misc bytes within the Sint32 flags to save space:
1366 map.flags[MAP_FLAG_GENBYTES1] = 0; // clear the flag 1 slot.
1367 if ( atoi(mapflagtext[MAP_FLAG_GENTOTALMIN]) >= 0 )
1368 {
1369 map.flags[MAP_FLAG_GENBYTES1] |= atoi(mapflagtext[MAP_FLAG_GENTOTALMIN]) << 24; // store in first leftmost byte.
1370 }
1371 if ( atoi(mapflagtext[MAP_FLAG_GENTOTALMAX]) >= 0 )
1372 {
1373 map.flags[MAP_FLAG_GENBYTES1] |= atoi(mapflagtext[MAP_FLAG_GENTOTALMAX]) << 16; // store in second leftmost byte.
1374 }
1375 if ( atoi(mapflagtext[MAP_FLAG_GENMONSTERMIN]) >= 0 )
1376 {
1377 map.flags[MAP_FLAG_GENBYTES1] |= atoi(mapflagtext[MAP_FLAG_GENMONSTERMIN]) << 8; // store in third leftmost byte.
1378 }
1379 if ( atoi(mapflagtext[MAP_FLAG_GENMONSTERMAX]) >= 0 )
1380 {
1381 map.flags[MAP_FLAG_GENBYTES1] |= atoi(mapflagtext[MAP_FLAG_GENMONSTERMAX]) << 0; // store in fourth leftmost byte.
1382 }
1383
1384 map.flags[MAP_FLAG_GENBYTES2] = 0; // clear the flag 2 slot.
1385 if ( atoi(mapflagtext[MAP_FLAG_GENMONSTERMIN]) >= 0 )
1386 {
1387 map.flags[MAP_FLAG_GENBYTES2] |= atoi(mapflagtext[MAP_FLAG_GENLOOTMIN]) << 24; // store in first leftmost byte.
1388 }
1389 if ( atoi(mapflagtext[MAP_FLAG_GENMONSTERMAX]) >= 0 )
1390 {
1391 map.flags[MAP_FLAG_GENBYTES2] |= atoi(mapflagtext[MAP_FLAG_GENLOOTMAX]) << 16; // store in second leftmost byte.
1392 }
1393 if ( atoi(mapflagtext[MAP_FLAG_GENDECORATIONMIN]) >= 0 )
1394 {
1395 map.flags[MAP_FLAG_GENBYTES2] |= atoi(mapflagtext[MAP_FLAG_GENDECORATIONMIN]) << 8; // store in third leftmost byte.
1396 }
1397 if ( atoi(mapflagtext[MAP_FLAG_GENDECORATIONMAX]) >= 0 )
1398 {
1399 map.flags[MAP_FLAG_GENBYTES2] |= atoi(mapflagtext[MAP_FLAG_GENDECORATIONMAX]) << 0; // store in fourth leftmost byte.
1400 }
1401
1402 map.flags[MAP_FLAG_GENBYTES3] = 0; // clear the flag 3 slot.
1403 if ( !strncmp(mapflagtext[MAP_FLAG_DISABLEDIGGING], "[x]", 3) )
1404 {
1405 map.flags[MAP_FLAG_GENBYTES3] |= (1 << 24); // store in first leftmost byte.
1406 }
1407 if ( !strncmp(mapflagtext[MAP_FLAG_DISABLETELEPORT], "[x]", 3) )
1408 {
1409 map.flags[MAP_FLAG_GENBYTES3] |= (1 << 16); // store in second leftmost byte.
1410 }
1411 if ( !strncmp(mapflagtext[MAP_FLAG_DISABLELEVITATION], "[x]", 3) )
1412 {
1413 map.flags[MAP_FLAG_GENBYTES3] |= (1 << 8); // store in third leftmost byte.
1414 }
1415 if ( !strncmp(mapflagtext[MAP_FLAG_GENADJACENTROOMS], "[x]", 3) )
1416 {
1417 map.flags[MAP_FLAG_GENBYTES3] |= (1 << 0); // store in fourth leftmost byte.
1418 }
1419 map.flags[MAP_FLAG_GENBYTES4] = 0; // clear the flag 4 slot.
1420 if ( !strncmp(mapflagtext[MAP_FLAG_DISABLEOPENING], "[x]", 3) )
1421 {
1422 map.flags[MAP_FLAG_GENBYTES4] |= (1 << 24); // store in first leftmost byte.
1423 }
1424 if ( !strncmp(mapflagtext[MAP_FLAG_DISABLEMESSAGES], "[x]", 3) )
1425 {
1426 map.flags[MAP_FLAG_GENBYTES4] |= (1 << 16); // store in second leftmost byte.
1427 }
1428 if ( !strncmp(mapflagtext[MAP_FLAG_DISABLEHUNGER], "[x]", 3) )
1429 {
1430 map.flags[MAP_FLAG_GENBYTES4] |= (1 << 8); // store in third leftmost byte.
1431 }
1432
1433 if ( !strncmp(mapflagtext[MAP_FLAG_DISABLETRAPS], "[x]", 3) )
1434 {
1435 map.flags[MAP_FLAG_DISABLETRAPS] = 1;
1436 }
1437 else
1438 {
1439 map.flags[MAP_FLAG_DISABLETRAPS] = 0;
1440 }
1441 if ( !strncmp(mapflagtext[MAP_FLAG_DISABLEMONSTERS], "[x]", 3) )
1442 {
1443 map.flags[MAP_FLAG_DISABLEMONSTERS] = 1;
1444 }
1445 else
1446 {
1447 map.flags[MAP_FLAG_DISABLEMONSTERS] = 0;
1448 }
1449 if ( !strncmp(mapflagtext[MAP_FLAG_DISABLELOOT], "[x]", 3) )
1450 {
1451 map.flags[MAP_FLAG_DISABLELOOT] = 1;
1452 }
1453 else
1454 {
1455 map.flags[MAP_FLAG_DISABLELOOT] = 0;
1456 }
1457
1458 map.tiles = (int*) malloc(sizeof(int) * MAPLAYERS * map.height * map.width);
1459 strcpy(map.name, nametext);
1460 strcpy(map.author, authortext);
1461 if ( vismap != NULL )
1462 {
1463 free(vismap);
1464 }
1465 vismap = (bool*) malloc(sizeof(bool) * map.width * map.height);
1466 if ( lightmap != NULL )
1467 {
1468 free(lightmap);
1469 }
1470 if ( lightmapSmoothed != NULL )
1471 {
1472 free(lightmapSmoothed);
1473 }
1474 lightmap = (int*)malloc(sizeof(Sint32) * map.width * map.height);
1475 lightmapSmoothed = (int*)malloc(sizeof(Sint32) * map.width * map.height);
1476 for ( c = 0; c < map.width * map.height; c++ )
1477 {
1478 lightmap[c] = 0;
1479 lightmapSmoothed[c] = 0;
1480 }
1481
1482 // transfer data from the new map to the old map and fill extra space with empty data
1483 for ( z = 0; z < MAPLAYERS; z++ )
1484 {
1485 for ( y = 0; y < map.height; y++ )
1486 {
1487 for ( x = 0; x < map.width; x++ )
1488 {
1489 if ( x >= mapcopy.width || y >= mapcopy.height )
1490 {
1491 map.tiles[z + y * MAPLAYERS + x * MAPLAYERS * map.height] = 0;
1492 }
1493 else
1494 {
1495 map.tiles[z + y * MAPLAYERS + x * MAPLAYERS * map.height] = mapcopy.tiles[z + y * MAPLAYERS + x * MAPLAYERS * mapcopy.height];
1496 }
1497 }
1498 }
1499 }
1500 free(mapcopy.tiles);
1501 strcpy(message, " Modified map attributes.");
1502 messagetime = 60;
1503 buttonCloseSubwindow(my);
1504 }
1505
buttonClearMap(button_t * my)1506 void buttonClearMap(button_t* my)
1507 {
1508 button_t* button;
1509
1510 menuVisible = 0;
1511 subwindow = 1;
1512 subx1 = xres / 2 - 160;
1513 subx2 = xres / 2 + 160;
1514 suby1 = yres / 2 - 56;
1515 suby2 = yres / 2 + 56;
1516 strcpy(subtext, "Warning:\n\nThis option will completely erase your\nentire map.\n\nAre you sure you want to continue?\n");
1517
1518 button = newButton();
1519 strcpy(button->label, "OK");
1520 button->x = subx1 + 64;
1521 button->y = suby2 - 24;
1522 button->sizex = 24;
1523 button->sizey = 16;
1524 button->action = &buttonClearMapConfirm;
1525 button->visible = 1;
1526 button->focused = 1;
1527
1528 button = newButton();
1529 strcpy(button->label, "Cancel");
1530 button->x = subx2 - 112;
1531 button->y = suby2 - 24;
1532 button->sizex = 56;
1533 button->sizey = 16;
1534 button->action = &buttonCloseSubwindow;
1535 button->visible = 1;
1536 button->focused = 1;
1537
1538 button = newButton();
1539 strcpy(button->label, "X");
1540 button->x = subx2 - 16;
1541 button->y = suby1;
1542 button->sizex = 16;
1543 button->sizey = 16;
1544 button->action = &buttonCloseSubwindow;
1545 button->visible = 1;
1546 button->focused = 1;
1547 }
1548
buttonClearMapConfirm(button_t * my)1549 void buttonClearMapConfirm(button_t* my)
1550 {
1551 long x, y, z;
1552 makeUndo();
1553 for ( z = 0; z < MAPLAYERS; z++ )
1554 {
1555 for ( y = 0; y < map.height; y++ )
1556 {
1557 for ( x = 0; x < map.width; x++ )
1558 {
1559 map.tiles[z + y * MAPLAYERS + x * MAPLAYERS * map.height] = 0;
1560 }
1561 }
1562 }
1563 list_FreeAll(map.entities);
1564 buttonCloseSubwindow(my);
1565 }
1566
1567 // Help menu
1568
buttonHelp(button_t * my)1569 void buttonHelp(button_t* my)
1570 {
1571 if ( menuVisible != 5 )
1572 {
1573 menuVisible = 5;
1574 }
1575 else
1576 {
1577 menuVisible = 0;
1578 }
1579 }
1580
buttonAbout(button_t * my)1581 void buttonAbout(button_t* my)
1582 {
1583 button_t* button;
1584
1585 menuVisible = 0;
1586 subwindow = 1;
1587 subx1 = xres / 2 - 160;
1588 subx2 = xres / 2 + 160;
1589 suby1 = yres / 2 - 56;
1590 suby2 = yres / 2 + 56;
1591 strcpy(subtext, "Barony: Map Editor v2.4"
1592 "\n\nSee EDITING for full documentation."
1593 "\n\nThis software is copyright 2018 (c)"
1594 "\nSheridan Rathbun, all rights reserved."
1595 "\n\nSee LICENSE for details.\n");
1596
1597 button = newButton();
1598 strcpy(button->label, "OK");
1599 button->x = xres / 2 - 12;
1600 button->y = suby2 - 24;
1601 button->sizex = 24;
1602 button->sizey = 16;
1603 button->action = &buttonCloseSubwindow;
1604 button->visible = 1;
1605 button->focused = 1;
1606
1607 button = newButton();
1608 strcpy(button->label, "X");
1609 button->x = subx2 - 16;
1610 button->y = suby1;
1611 button->sizex = 16;
1612 button->sizey = 16;
1613 button->action = &buttonCloseSubwindow;
1614 button->visible = 1;
1615 button->focused = 1;
1616 }
1617
buttonEditorToolsHelp(button_t * my)1618 void buttonEditorToolsHelp(button_t* my)
1619 {
1620 node_t* node;
1621 node_t* nextnode;
1622 button_t* button;
1623 for ( node = button_l.first; node != NULL; node = nextnode )
1624 {
1625 nextnode = node->next;
1626 button = (button_t*)node->element;
1627 if ( button->focused )
1628 {
1629 list_RemoveNode(button->node);
1630 continue;
1631 }
1632 }
1633 subwindow = 1;
1634 if ( newwindow == 16 )
1635 {
1636 newwindow = 17;
1637 subx1 = xres / 2 - 280;
1638 subx2 = xres / 2 + 280;
1639 suby1 = yres / 2 - 190;
1640 suby2 = yres / 2 + 190;
1641
1642 button = newButton();
1643 strcpy(button->label, "OK");
1644 button->sizex = 9 * 12 + 8;
1645 button->x = xres / 2 - button->sizex - 4;
1646 button->y = suby2 - 24;
1647 button->sizey = 16;
1648 button->action = &buttonCloseSubwindow;
1649 button->visible = 1;
1650 button->focused = 1;
1651
1652 button = newButton();
1653 strcpy(button->label, "Next Page");
1654 button->x = xres / 2 + 4;
1655 button->y = suby2 - 24;
1656 button->sizex = strlen(button->label) * 12 + 8;
1657 button->sizey = 16;
1658 button->action = &buttonEditorToolsHelp;
1659 button->visible = 1;
1660 button->focused = 1;
1661
1662 button = newButton();
1663 strcpy(button->label, "X");
1664 button->x = subx2 - 16;
1665 button->y = suby1;
1666 button->sizex = 16;
1667 button->sizey = 16;
1668 button->action = &buttonCloseSubwindow;
1669 button->visible = 1;
1670 button->focused = 1;
1671 }
1672 else
1673 {
1674 buttonEditorControls(nullptr);
1675 }
1676 }
1677
buttonEditorControls(button_t * my)1678 void buttonEditorControls(button_t* my)
1679 {
1680 button_t* button;
1681
1682 menuVisible = 0;
1683 subwindow = 1;
1684 newwindow = 16;
1685 subx1 = xres / 2 - 250;
1686 subx2 = xres / 2 + 250;
1687 suby1 = yres / 2 - 210;
1688 suby2 = yres / 2 + 210;
1689
1690 button = newButton();
1691 strcpy(button->label, "OK");
1692 button->sizex = 9 * 12 + 8;
1693 button->x = xres / 2 - button->sizex - 4;
1694 button->y = suby2 - 24;
1695 button->sizey = 16;
1696 button->action = &buttonCloseSubwindow;
1697 button->visible = 1;
1698 button->focused = 1;
1699
1700 button = newButton();
1701 strcpy(button->label, "Next Page");
1702 button->x = xres / 2 + 4;
1703 button->y = suby2 - 24;
1704 button->sizex = strlen(button->label) * 12 + 8;
1705 button->sizey = 16;
1706 button->action = &buttonEditorToolsHelp;
1707 button->visible = 1;
1708 button->focused = 1;
1709
1710 button = newButton();
1711 strcpy(button->label, "X");
1712 button->x = subx2 - 16;
1713 button->y = suby1;
1714 button->sizex = 16;
1715 button->sizey = 16;
1716 button->action = &buttonCloseSubwindow;
1717 button->visible = 1;
1718 button->focused = 1;
1719 }
1720
1721 // Subwindows
buttonCloseSubwindow(button_t * my)1722 void buttonCloseSubwindow(button_t* my)
1723 {
1724 int c;
1725
1726 // close window
1727 selectedEntity = NULL;
1728 subwindow = 0;
1729 newwindow = 0;
1730 openwindow = 0;
1731 savewindow = 0;
1732 editproperty = 0;
1733 strcpy(filename, oldfilename);
1734 }
1735
buttonSpriteProperties(button_t * my)1736 void buttonSpriteProperties(button_t* my)
1737 {
1738 button_t* button;
1739 int c = 0;
1740 Stat* tmpSpriteStats = NULL;
1741 int spriteType = 0;
1742 int spacing = 20;
1743 int pad_y2;
1744 int pad_x3;
1745 int pad_x4;
1746 char tmpStr[32] = "";
1747 int itemIndex = 0;
1748
1749 if ( selectedEntity == NULL && lastSelectedEntity != NULL )
1750 {
1751 if ( checkSpriteType(lastSelectedEntity->sprite) != 0 )
1752 {
1753 selectedEntity = lastSelectedEntity;
1754 }
1755 else
1756 {
1757 strcpy(message, "No properties available for previous sprite.");
1758 messagetime = 60;
1759 }
1760 }
1761
1762 if ( selectedEntity != NULL )
1763 {
1764 editproperty = 0;
1765 for ( int i = 0; i < (sizeof(spriteProperties) / sizeof(spriteProperties[0])); i++ )
1766 {
1767 strcpy(spriteProperties[i], "");
1768 }
1769
1770 spriteType = checkSpriteType(selectedEntity->sprite);
1771 switch ( spriteType )
1772 {
1773 case 1: //monsters
1774 tmpSpriteStats = selectedEntity->getStats();
1775 if ( tmpSpriteStats != nullptr )
1776 {
1777 if ( exitFromItemWindow == true )
1778 {
1779 exitFromItemWindow = false;
1780 // retreives any modified monster stats, to be restored when window is closed.
1781
1782 for ( int i = 0; i < sizeof(spriteProperties) / sizeof(spriteProperties[0]); i++ )
1783 {
1784 strcpy(spriteProperties[i], tmpSpriteProperties[i]);
1785 }
1786 }
1787 else
1788 {
1789 copyMonsterStatToPropertyStrings(tmpSpriteStats);
1790 }
1791 inputstr = spriteProperties[0];
1792 initMonsterPropertiesWindow();
1793 }
1794 tmpSpriteStats = NULL;
1795 break;
1796 case 2: //chests
1797 snprintf(spriteProperties[0], 4, "%d", static_cast<int>(selectedEntity->yaw));
1798 snprintf(spriteProperties[1], 4, "%d", selectedEntity->skill[9]);
1799 snprintf(spriteProperties[2], 4, "%d", selectedEntity->chestLocked);
1800 inputstr = spriteProperties[0];
1801 cursorflash = ticks;
1802 menuVisible = 0;
1803 subwindow = 1;
1804 newwindow = 3;
1805 subx1 = xres / 2 - 160;
1806 subx2 = xres / 2 + 160;
1807 suby1 = yres / 2 - 105;
1808 suby2 = yres / 2 + 105;
1809 strcpy(subtext, "Chest Properties:");
1810 break;
1811 case 3: //items
1812 itemSelect = 1;
1813 snprintf(spriteProperties[0], 4, "%d", static_cast<int>(selectedEntity->skill[10])); //ID
1814 snprintf(spriteProperties[1], 4, "%d", static_cast<int>(selectedEntity->skill[11])); //status
1815 if ( (int)selectedEntity->skill[12] == 10 )
1816 {
1817 strcpy(spriteProperties[2], "00"); //bless random
1818 }
1819 else
1820 {
1821 snprintf(spriteProperties[2], 4, "%d", static_cast<int>(selectedEntity->skill[12])); //bless
1822 }
1823 snprintf(spriteProperties[3], 4, "%d", static_cast<int>(selectedEntity->skill[13])); //count
1824 snprintf(spriteProperties[4], 4, "%d", static_cast<int>(selectedEntity->skill[15])); //identified
1825 snprintf(spriteProperties[5], 4, "%d", static_cast<int>(selectedEntity->skill[16])); //category if random
1826 inputstr = spriteProperties[0];
1827 cursorflash = ticks;
1828 menuVisible = 0;
1829 subwindow = 1;
1830 newwindow = 4;
1831 slidery = 0;
1832 subx1 = xres / 2 - 200;
1833 subx2 = xres / 2 + 200;
1834 suby1 = yres / 2 - 140;
1835 suby2 = yres / 2 + 140;
1836 strcpy(subtext, "Item Properties:");
1837 break;
1838 case 4:
1839 snprintf(spriteProperties[0], 4, "%d", static_cast<int>(selectedEntity->skill[0])); //Monster to Spawn
1840 snprintf(spriteProperties[1], 4, "%d", static_cast<int>(selectedEntity->skill[1])); //Qty
1841 snprintf(spriteProperties[2], 4, "%d", static_cast<int>(selectedEntity->skill[2])); //Time Between Spawns
1842 snprintf(spriteProperties[3], 4, "%d", static_cast<int>(selectedEntity->skill[3])); //Amount of Spawns
1843 snprintf(spriteProperties[4], 4, "%d", static_cast<int>(selectedEntity->skill[4])); //Requires Power
1844 snprintf(spriteProperties[5], 4, "%d", static_cast<int>(selectedEntity->skill[5])); //Chance to Stop Working
1845 inputstr = spriteProperties[0];
1846 cursorflash = ticks;
1847 menuVisible = 0;
1848 subwindow = 1;
1849 newwindow = 6;
1850 subx1 = xres / 2 - 210;
1851 subx2 = xres / 2 + 210;
1852 suby1 = yres / 2 - 140;
1853 suby2 = yres / 2 + 140;
1854 strcpy(subtext, "Summoning Trap Properties:");
1855 break;
1856 case 5:
1857 snprintf(spriteProperties[0], 4, "%d", static_cast<int>(selectedEntity->yaw)); //Orientation
1858 snprintf(spriteProperties[1], 4, "%d", static_cast<int>(selectedEntity->crystalNumElectricityNodes)); //Powered Distance
1859 snprintf(spriteProperties[2], 4, "%d", static_cast<int>(selectedEntity->crystalTurnReverse)); //Rotation direction
1860 snprintf(spriteProperties[3], 4, "%d", static_cast<int>(selectedEntity->crystalSpellToActivate)); //Spell to activate
1861 inputstr = spriteProperties[0];
1862 cursorflash = ticks;
1863 menuVisible = 0;
1864 subwindow = 1;
1865 newwindow = 7;
1866 subx1 = xres / 2 - 210;
1867 subx2 = xres / 2 + 210;
1868 suby1 = yres / 2 - 120;
1869 suby2 = yres / 2 + 120;
1870 strcpy(subtext, "Power Crystal Properties:");
1871 break;
1872 case 6:
1873 snprintf(spriteProperties[0], 4, "%d", static_cast<int>(selectedEntity->leverTimerTicks));
1874 inputstr = spriteProperties[0];
1875 cursorflash = ticks;
1876 menuVisible = 0;
1877 subwindow = 1;
1878 newwindow = 8;
1879 subx1 = xres / 2 - 120;
1880 subx2 = xres / 2 + 120;
1881 suby1 = yres / 2 - 60;
1882 suby2 = yres / 2 + 60;
1883 strcpy(subtext, "Lever Timer Properties:");
1884 break;
1885 case 7:
1886 snprintf(spriteProperties[0], 4, "%d", static_cast<int>(selectedEntity->boulderTrapRefireAmount));
1887 snprintf(spriteProperties[1], 4, "%d", static_cast<int>(selectedEntity->boulderTrapRefireDelay));
1888 snprintf(spriteProperties[2], 4, "%d", static_cast<int>(selectedEntity->boulderTrapPreDelay));
1889 inputstr = spriteProperties[0];
1890 cursorflash = ticks;
1891 menuVisible = 0;
1892 subwindow = 1;
1893 newwindow = 9;
1894 subx1 = xres / 2 - 170;
1895 subx2 = xres / 2 + 170;
1896 suby1 = yres / 2 - 100;
1897 suby2 = yres / 2 + 100;
1898 strcpy(subtext, "Boulder Trap Properties:");
1899 break;
1900 case 8:
1901 snprintf(spriteProperties[0], 2, "%d", static_cast<int>(selectedEntity->pedestalOrbType));
1902 snprintf(spriteProperties[1], 2, "%d", static_cast<int>(selectedEntity->pedestalHasOrb));
1903 snprintf(spriteProperties[2], 2, "%d", static_cast<int>(selectedEntity->pedestalInvertedPower));
1904 snprintf(spriteProperties[3], 2, "%d", static_cast<int>(selectedEntity->pedestalInGround));
1905 snprintf(spriteProperties[4], 2, "%d", static_cast<int>(selectedEntity->pedestalLockOrb));
1906 inputstr = spriteProperties[0];
1907 cursorflash = ticks;
1908 menuVisible = 0;
1909 subwindow = 1;
1910 newwindow = 10;
1911 subx1 = xres / 2 - 170;
1912 subx2 = xres / 2 + 170;
1913 suby1 = yres / 2 - 110;
1914 suby2 = yres / 2 + 110;
1915 strcpy(subtext, "Pedestal Properties:");
1916 break;
1917 case 9:
1918 snprintf(spriteProperties[0], 4, "%d", static_cast<int>(selectedEntity->teleporterX));
1919 snprintf(spriteProperties[1], 4, "%d", static_cast<int>(selectedEntity->teleporterY));
1920 snprintf(spriteProperties[2], 2, "%d", static_cast<int>(selectedEntity->teleporterType));
1921 inputstr = spriteProperties[0];
1922 cursorflash = ticks;
1923 menuVisible = 0;
1924 subwindow = 1;
1925 newwindow = 11;
1926 subx1 = xres / 2 - 170;
1927 subx2 = xres / 2 + 170;
1928 suby1 = yres / 2 - 100;
1929 suby2 = yres / 2 + 100;
1930 strcpy(subtext, "Teleporter Properties:");
1931 break;
1932 case 10:
1933 snprintf(spriteProperties[0], 5, "%d", static_cast<int>(selectedEntity->ceilingTileModel));
1934 inputstr = spriteProperties[0];
1935 cursorflash = ticks;
1936 menuVisible = 0;
1937 subwindow = 1;
1938 newwindow = 12;
1939 subx1 = xres / 2 - 170;
1940 subx2 = xres / 2 + 170;
1941 suby1 = yres / 2 - 60;
1942 suby2 = yres / 2 + 60;
1943 strcpy(subtext, "Ceiling Tile Properties:");
1944 break;
1945 case 11:
1946 snprintf(spriteProperties[0], 4, "%d", static_cast<int>(selectedEntity->spellTrapType));
1947 snprintf(spriteProperties[1], 4, "%d", static_cast<int>(selectedEntity->spellTrapRefire));
1948 snprintf(spriteProperties[2], 4, "%d", static_cast<int>(selectedEntity->spellTrapLatchPower));
1949 snprintf(spriteProperties[3], 5, "%d", static_cast<int>(selectedEntity->spellTrapFloorTile));
1950 snprintf(spriteProperties[4], 4, "%d", static_cast<int>(selectedEntity->spellTrapRefireRate));
1951 inputstr = spriteProperties[0];
1952 cursorflash = ticks;
1953 menuVisible = 0;
1954 subwindow = 1;
1955 newwindow = 13;
1956 subx1 = xres / 2 - 200;
1957 subx2 = xres / 2 + 200;
1958 suby1 = yres / 2 - 110;
1959 suby2 = yres / 2 + 110;
1960 strcpy(subtext, "Spell Trap Properties:");
1961 break;
1962 case 12:
1963 snprintf(spriteProperties[0], 4, "%d", static_cast<int>(selectedEntity->furnitureDir));
1964 inputstr = spriteProperties[0];
1965 cursorflash = ticks;
1966 menuVisible = 0;
1967 subwindow = 1;
1968 newwindow = 14;
1969 subx1 = xres / 2 - 170;
1970 subx2 = xres / 2 + 170;
1971 suby1 = yres / 2 - 60;
1972 suby2 = yres / 2 + 60;
1973 strcpy(subtext, "Furniture Properties:");
1974 break;
1975 case 13:
1976 {
1977 snprintf(spriteProperties[0], 5, "%d", static_cast<int>(selectedEntity->floorDecorationModel));
1978 snprintf(spriteProperties[1], 4, "%d", static_cast<int>(selectedEntity->floorDecorationRotation));
1979 snprintf(spriteProperties[2], 5, "%d", static_cast<int>(selectedEntity->floorDecorationHeightOffset));
1980 snprintf(spriteProperties[3], 5, "%d", static_cast<int>(selectedEntity->floorDecorationXOffset));
1981 snprintf(spriteProperties[4], 5, "%d", static_cast<int>(selectedEntity->floorDecorationYOffset));
1982 char buf[256] = "";
1983 int totalChars = 0;
1984 for ( int i = 8; i < 60; ++i )
1985 {
1986 if ( selectedEntity->skill[i] != 0 && i != 28 ) // skill[28] is circuit status.
1987 {
1988 for ( int c = 0; c < 4; ++c )
1989 {
1990 if ( static_cast<char>((selectedEntity->skill[i] >> (c * 8)) & 0xFF) == '\0'
1991 && i != 59 && selectedEntity->skill[i + 1] != 0 )
1992 {
1993 // don't add '\0' termination unless the next skill slot is empty as we have more data to read.
1994 }
1995 else
1996 {
1997 buf[totalChars] = static_cast<char>((selectedEntity->skill[i] >> (c * 8)) & 0xFF);
1998 ++totalChars;
1999 }
2000 }
2001 }
2002 }
2003 if ( buf[totalChars] != '\0' )
2004 {
2005 buf[totalChars] = '\0';
2006 }
2007 strncpy(spriteProperties[5], buf, 48);
2008 strncpy(spriteProperties[6], buf + 48, 48);
2009 strncpy(spriteProperties[7], buf + 96, 48);
2010 strncpy(spriteProperties[8], buf + 144, 48);
2011 inputstr = spriteProperties[0];
2012 cursorflash = ticks;
2013 menuVisible = 0;
2014 subwindow = 1;
2015 newwindow = 15;
2016 subx1 = xres / 2 - 200;
2017 subx2 = xres / 2 + 200;
2018 suby1 = yres / 2 - 180;
2019 suby2 = yres / 2 + 180;
2020 strcpy(subtext, "Decoration Model Properties:");
2021 break;
2022 }
2023 case 14:
2024 snprintf(spriteProperties[0], 4, "%d", static_cast<int>(selectedEntity->soundSourceToPlay));
2025 snprintf(spriteProperties[1], 4, "%d", static_cast<int>(selectedEntity->soundSourceVolume));
2026 snprintf(spriteProperties[2], 2, "%d", static_cast<int>(selectedEntity->soundSourceLatchOn));
2027 snprintf(spriteProperties[3], 5, "%d", static_cast<int>(selectedEntity->soundSourceDelay));
2028 snprintf(spriteProperties[4], 2, "%d", static_cast<int>(selectedEntity->soundSourceOrigin));
2029 inputstr = spriteProperties[0];
2030 cursorflash = ticks;
2031 menuVisible = 0;
2032 subwindow = 1;
2033 newwindow = 18;
2034 subx1 = xres / 2 - 230;
2035 subx2 = xres / 2 + 230;
2036 suby1 = yres / 2 - 112;
2037 suby2 = yres / 2 + 112;
2038 strcpy(subtext, "Sound Source Properties:");
2039 break;
2040 case 15:
2041 snprintf(spriteProperties[0], 2, "%d", static_cast<int>(selectedEntity->lightSourceAlwaysOn));
2042 snprintf(spriteProperties[1], 4, "%d", static_cast<int>(selectedEntity->lightSourceBrightness));
2043 snprintf(spriteProperties[2], 2, "%d", static_cast<int>(selectedEntity->lightSourceInvertPower));
2044 snprintf(spriteProperties[3], 2, "%d", static_cast<int>(selectedEntity->lightSourceLatchOn));
2045 snprintf(spriteProperties[4], 3, "%d", static_cast<int>(selectedEntity->lightSourceRadius));
2046 snprintf(spriteProperties[5], 2, "%d", static_cast<int>(selectedEntity->lightSourceFlicker));
2047 snprintf(spriteProperties[6], 5, "%d", static_cast<int>(selectedEntity->lightSourceDelay));
2048 inputstr = spriteProperties[0];
2049 cursorflash = ticks;
2050 menuVisible = 0;
2051 subwindow = 1;
2052 newwindow = 19;
2053 subx1 = xres / 2 - 200;
2054 subx2 = xres / 2 + 200;
2055 suby1 = yres / 2 - 160;
2056 suby2 = yres / 2 + 160;
2057 strcpy(subtext, "Light Source Properties:");
2058 break;
2059 case 16:
2060 {
2061 Uint32 r = (Uint32)(selectedEntity->textSourceColorRGB >> 16) & 0xFF;
2062 Uint32 g = (Uint32)(selectedEntity->textSourceColorRGB >> 8) & 0xFF;
2063 Uint32 b = (Uint32)(selectedEntity->textSourceColorRGB >> 0) & 0xFF;
2064 snprintf(spriteProperties[0], 4, "%d", r);
2065 snprintf(spriteProperties[1], 4, "%d", g);
2066 snprintf(spriteProperties[2], 4, "%d", b);
2067 char buf[256] = "";
2068 int totalChars = 0;
2069 for ( int i = 4; i < 60; ++i )
2070 {
2071 if ( selectedEntity->skill[i] != 0 && i != 28 ) // skill[28] is circuit status.
2072 {
2073 for ( int c = 0; c < 4; ++c )
2074 {
2075 if ( static_cast<char>((selectedEntity->skill[i] >> (c * 8)) & 0xFF) == '\0'
2076 && i != 59 && selectedEntity->skill[i + 1] != 0 )
2077 {
2078 // don't add '\0' termination unless the next skill slot is empty as we have more data to read.
2079 }
2080 else
2081 {
2082 buf[totalChars] = static_cast<char>((selectedEntity->skill[i] >> (c * 8)) & 0xFF);
2083 ++totalChars;
2084 }
2085 }
2086 }
2087 }
2088 if ( buf[totalChars] != '\0' )
2089 {
2090 buf[totalChars] = '\0';
2091 }
2092 strncpy(spriteProperties[3], buf, 48);
2093 strncpy(spriteProperties[4], buf + 48, 48);
2094 strncpy(spriteProperties[5], buf + 96, 48);
2095 strncpy(spriteProperties[6], buf + 144, 48);
2096 strncpy(spriteProperties[7], buf + 192, 48);
2097 snprintf(spriteProperties[8], 5, "%d", static_cast<int>(selectedEntity->textSourceDelay));
2098 snprintf(spriteProperties[9], 2, "%d", static_cast<int>((selectedEntity->textSourceVariables4W >> 8) & 0xFF));
2099 inputstr = spriteProperties[0];
2100 cursorflash = ticks;
2101 menuVisible = 0;
2102 subwindow = 1;
2103 newwindow = 20;
2104 subx1 = xres / 2 - 200;
2105 subx2 = xres / 2 + 200;
2106 suby1 = yres / 2 - 140;
2107 suby2 = yres / 2 + 140;
2108 strcpy(subtext, "Text Source Properties:");
2109 break;
2110 }
2111 case 17:
2112 snprintf(spriteProperties[0], 2, "%d", static_cast<int>(selectedEntity->signalInputDirection));
2113 snprintf(spriteProperties[1], 5, "%d", static_cast<int>(selectedEntity->signalActivateDelay));
2114 snprintf(spriteProperties[2], 5, "%d", static_cast<int>(selectedEntity->signalTimerInterval));
2115 snprintf(spriteProperties[3], 5, "%d", static_cast<int>(selectedEntity->signalTimerRepeatCount));
2116 snprintf(spriteProperties[4], 2, "%d", static_cast<int>(selectedEntity->signalTimerLatchInput));
2117 inputstr = spriteProperties[0];
2118 cursorflash = ticks;
2119 menuVisible = 0;
2120 subwindow = 1;
2121 newwindow = 21;
2122 subx1 = xres / 2 - 220;
2123 subx2 = xres / 2 + 220;
2124 suby1 = yres / 2 - 120;
2125 suby2 = yres / 2 + 120;
2126 strcpy(subtext, "Signal Timer Properties:");
2127 break;
2128 case 18: // custom portal
2129 {
2130 snprintf(spriteProperties[0], 5, "%d", static_cast<int>(selectedEntity->portalCustomSprite));
2131 snprintf(spriteProperties[1], 2, "%d", static_cast<int>(selectedEntity->portalCustomSpriteAnimationFrames));
2132 snprintf(spriteProperties[2], 5, "%d", static_cast<int>(selectedEntity->portalCustomZOffset));
2133 snprintf(spriteProperties[3], 3, "%d", static_cast<int>(selectedEntity->portalCustomLevelsToJump));
2134 snprintf(spriteProperties[5], 2, "%d", static_cast<int>(selectedEntity->portalCustomRequiresPower));
2135 snprintf(spriteProperties[6], 2, "%d", static_cast<int>((selectedEntity->portalNotSecret ? 0 : 1)));
2136
2137 char buf[64] = "";
2138 int totalChars = 0;
2139 for ( int i = 11; i <= 18; ++i )
2140 {
2141 if ( selectedEntity->skill[i] != 0 && i != 28 ) // skill[28] is circuit status.
2142 {
2143 for ( int c = 0; c < 4; ++c )
2144 {
2145 if ( static_cast<char>((selectedEntity->skill[i] >> (c * 8)) & 0xFF) == '\0'
2146 && i != 18 && selectedEntity->skill[i + 1] != 0 )
2147 {
2148 // don't add '\0' termination unless the next skill slot is empty as we have more data to read.
2149 }
2150 else
2151 {
2152 buf[totalChars] = static_cast<char>((selectedEntity->skill[i] >> (c * 8)) & 0xFF);
2153 ++totalChars;
2154 }
2155 }
2156 }
2157 }
2158 if ( buf[totalChars] != '\0' )
2159 {
2160 buf[totalChars] = '\0';
2161 }
2162 strncpy(spriteProperties[4], buf, 32);
2163
2164 inputstr = spriteProperties[0];
2165 cursorflash = ticks;
2166 menuVisible = 0;
2167 subwindow = 1;
2168 newwindow = 22;
2169 subx1 = xres / 2 - 220;
2170 subx2 = xres / 2 + 220;
2171 suby1 = yres / 2 - 140;
2172 suby2 = yres / 2 + 140;
2173 strcpy(subtext, "Custom Exit Properties:");
2174 break;
2175 }
2176 case 19: // tables
2177 snprintf(spriteProperties[0], 3, "%d", static_cast<int>(selectedEntity->furnitureDir));
2178 snprintf(spriteProperties[1], 3, "%d", static_cast<int>(selectedEntity->furnitureTableSpawnChairs));
2179 snprintf(spriteProperties[2], 4, "%d", static_cast<int>(selectedEntity->furnitureTableRandomItemChance));
2180 inputstr = spriteProperties[0];
2181 cursorflash = ticks;
2182 menuVisible = 0;
2183 subwindow = 1;
2184 newwindow = 23;
2185 subx1 = xres / 2 - 170;
2186 subx2 = xres / 2 + 170;
2187 suby1 = yres / 2 - 100;
2188 suby2 = yres / 2 + 100;
2189 strcpy(subtext, "Table Properties:");
2190 break;
2191 case 20: // readablebook
2192 {
2193 snprintf(spriteProperties[0], 3, "%d", static_cast<int>(selectedEntity->skill[11])); // status
2194 if ( (int)selectedEntity->skill[12] == 10 )
2195 {
2196 strcpy(spriteProperties[1], "00"); //bless random
2197 }
2198 else
2199 {
2200 snprintf(spriteProperties[1], 3, "%d", static_cast<int>(selectedEntity->skill[12])); //bless
2201 }
2202 snprintf(spriteProperties[2], 3, "%d", static_cast<int>(selectedEntity->skill[15])); // identified
2203 char buf[64] = "";
2204 int totalChars = 0;
2205 for ( int i = 40; i <= 52; ++i )
2206 {
2207 if ( selectedEntity->skill[i] != 0 && i != 28 ) // skill[28] is circuit status.
2208 {
2209 for ( int c = 0; c < 4; ++c )
2210 {
2211 if ( static_cast<char>((selectedEntity->skill[i] >> (c * 8)) & 0xFF) == '\0'
2212 && i != 52 && selectedEntity->skill[i + 1] != 0 )
2213 {
2214 // don't add '\0' termination unless the next skill slot is empty as we have more data to read.
2215 }
2216 else
2217 {
2218 buf[totalChars] = static_cast<char>((selectedEntity->skill[i] >> (c * 8)) & 0xFF);
2219 ++totalChars;
2220 }
2221 }
2222 }
2223 }
2224 if ( buf[totalChars] != '\0' )
2225 {
2226 buf[totalChars] = '\0';
2227 }
2228 strncpy(spriteProperties[3], buf, 32);
2229
2230 inputstr = spriteProperties[0];
2231 cursorflash = ticks;
2232 menuVisible = 0;
2233 subwindow = 1;
2234 newwindow = 24;
2235 subx1 = xres / 2 - 220;
2236 subx2 = xres / 2 + 220;
2237 suby1 = yres / 2 - 110;
2238 suby2 = yres / 2 + 110;
2239 strcpy(subtext, "Readable Book Properties:");
2240 }
2241 break;
2242 case 21:
2243 snprintf(spriteProperties[0], 4, "%d", static_cast<int>(selectedEntity->doorForceLockedUnlocked));
2244 snprintf(spriteProperties[1], 4, "%d", static_cast<int>(selectedEntity->doorDisableLockpicks));
2245 snprintf(spriteProperties[2], 4, "%d", static_cast<int>(selectedEntity->doorDisableOpening));
2246 inputstr = spriteProperties[0];
2247 cursorflash = ticks;
2248 menuVisible = 0;
2249 subwindow = 1;
2250 newwindow = 26;
2251 subx1 = xres / 2 - 170;
2252 subx2 = xres / 2 + 170;
2253 suby1 = yres / 2 - 100;
2254 suby2 = yres / 2 + 100;
2255 strcpy(subtext, "Door Properties:");
2256 break;
2257 case 22:
2258 snprintf(spriteProperties[0], 4, "%d", static_cast<int>(selectedEntity->gateDisableOpening));
2259 inputstr = spriteProperties[0];
2260 cursorflash = ticks;
2261 menuVisible = 0;
2262 subwindow = 1;
2263 newwindow = 27;
2264 subx1 = xres / 2 - 170;
2265 subx2 = xres / 2 + 170;
2266 suby1 = yres / 2 - 60;
2267 suby2 = yres / 2 + 60;
2268 strcpy(subtext, "Gate Properties:");
2269 break;
2270 case 23: // player spawn
2271 snprintf(spriteProperties[0], 4, "%d", static_cast<int>(selectedEntity->playerStartDir));
2272 inputstr = spriteProperties[0];
2273 cursorflash = ticks;
2274 menuVisible = 0;
2275 subwindow = 1;
2276 newwindow = 28;
2277 subx1 = xres / 2 - 170;
2278 subx2 = xres / 2 + 170;
2279 suby1 = yres / 2 - 60;
2280 suby2 = yres / 2 + 60;
2281 strcpy(subtext, "Player Spawn Properties:");
2282 break;
2283 default:
2284 strcpy(message, "No properties available for current sprite.");
2285 messagetime = 60;
2286 break;
2287 }
2288
2289 //remaining buttons
2290 switch ( spriteType )
2291 {
2292 case 1: //monsters
2293 tmpSpriteStats = selectedEntity->getStats();
2294 if ( tmpSpriteStats != nullptr )
2295 {
2296
2297 butMonsterOK = newButton();
2298 strcpy(butMonsterOK->label, " OK ");
2299 butMonsterOK->x = subx2 - 64;
2300 butMonsterOK->y = suby2 - 48;
2301 butMonsterOK->sizex = 56;
2302 butMonsterOK->sizey = 16;
2303 butMonsterOK->action = &buttonSpritePropertiesConfirm;
2304 butMonsterOK->visible = 1;
2305 butMonsterOK->focused = 1;
2306
2307 butMonsterCancel = newButton();
2308 strcpy(butMonsterCancel->label, "Cancel");
2309 butMonsterCancel->x = subx2 - 64;
2310 butMonsterCancel->y = suby2 - 24;
2311 butMonsterCancel->sizex = 56;
2312 butMonsterCancel->sizey = 16;
2313 butMonsterCancel->action = &buttonCloseSpriteSubwindow;
2314 butMonsterCancel->visible = 1;
2315 butMonsterCancel->focused = 1;
2316
2317 butMonsterX = newButton();
2318 strcpy(butMonsterX->label, "X");
2319 butMonsterX->x = subx2 - 16;
2320 butMonsterX->y = suby1;
2321 butMonsterX->sizex = 16;
2322 butMonsterX->sizey = 16;
2323 butMonsterX->action = &buttonCloseSpriteSubwindow;
2324 butMonsterX->visible = 1;
2325 butMonsterX->focused = 1;
2326
2327 pad_y2 = suby1 + 28 + 2 * spacing;
2328 pad_x3 = 40;
2329 pad_x4 = subx2 - 112;
2330 itemIndex = 0;
2331 if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 0 )
2332 {
2333 strcpy(tmpStr, "NULL");
2334 }
2335 else if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 1 )
2336 {
2337 strcpy(tmpStr, "RAND");
2338 }
2339 else
2340 {
2341 snprintf(tmpStr, 4, "%d", tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES]);
2342 }
2343
2344 if ( canWearEquip(selectedEntity, itemIndex) )
2345 {
2346 butMonsterHelm = newButton();
2347 strcpy(butMonsterHelm->label, tmpStr);
2348 butMonsterHelm->x = pad_x4 - 10;
2349 butMonsterHelm->y = pad_y2 + spacing - 4;
2350 butMonsterHelm->sizex = pad_x4 + pad_x3 - (pad_x4 - 10);
2351 butMonsterHelm->sizey = 16;
2352 butMonsterHelm->action = &buttonMonsterItems;
2353 butMonsterHelm->visible = 1;
2354 butMonsterHelm->focused = 1;
2355 }
2356
2357 pad_y2 += spacing * 2;
2358 itemIndex = 6;
2359 if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 0 )
2360 {
2361 strcpy(tmpStr, "NULL");
2362 }
2363 else if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 1 )
2364 {
2365 strcpy(tmpStr, "RAND");
2366 }
2367 else
2368 {
2369 snprintf(tmpStr, 4, "%d", tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES]);
2370 }
2371 if ( canWearEquip(selectedEntity, itemIndex) )
2372 {
2373 butMonsterAmulet = newButton();
2374 strcpy(butMonsterAmulet->label, tmpStr);
2375 butMonsterAmulet->x = pad_x4 - 10;
2376 butMonsterAmulet->y = pad_y2 + spacing - 4;
2377 butMonsterAmulet->sizex = pad_x4 + pad_x3 - (pad_x4 - 10);
2378 butMonsterAmulet->sizey = 16;
2379 butMonsterAmulet->action = &buttonMonsterItems;
2380 butMonsterAmulet->visible = 1;
2381 butMonsterAmulet->focused = 1;
2382 }
2383
2384 pad_y2 += spacing * 2;
2385 itemIndex = 3;
2386 if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 0 )
2387 {
2388 strcpy(tmpStr, "NULL");
2389 }
2390 else if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 1 )
2391 {
2392 strcpy(tmpStr, "RAND");
2393 }
2394 else
2395 {
2396 snprintf(tmpStr, 4, "%d", tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES]);
2397 }
2398 if ( canWearEquip(selectedEntity, itemIndex) )
2399 {
2400 butMonsterArmor = newButton();
2401 strcpy(butMonsterArmor->label, tmpStr);
2402 butMonsterArmor->x = pad_x4 - 10;
2403 butMonsterArmor->y = pad_y2 + spacing - 4;
2404 butMonsterArmor->sizex = pad_x4 + pad_x3 - (pad_x4 - 10);
2405 butMonsterArmor->sizey = 16;
2406 butMonsterArmor->action = &buttonMonsterItems;
2407 butMonsterArmor->visible = 1;
2408 butMonsterArmor->focused = 1;
2409 }
2410
2411 pad_y2 += spacing * 2;
2412 itemIndex = 4;
2413 if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 0 )
2414 {
2415 strcpy(tmpStr, "NULL");
2416 }
2417 else if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 1 )
2418 {
2419 strcpy(tmpStr, "RAND");
2420 }
2421 else
2422 {
2423 snprintf(tmpStr, 4, "%d", tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES]);
2424 }
2425 if ( canWearEquip(selectedEntity, itemIndex) )
2426 {
2427 butMonsterBoots = newButton();
2428 strcpy(butMonsterBoots->label, tmpStr);
2429 butMonsterBoots->x = pad_x4 - 10;
2430 butMonsterBoots->y = pad_y2 + spacing - 4;
2431 butMonsterBoots->sizex = pad_x4 + pad_x3 - (pad_x4 - 10);
2432 butMonsterBoots->sizey = 16;
2433 butMonsterBoots->action = &buttonMonsterItems;
2434 butMonsterBoots->visible = 1;
2435 butMonsterBoots->focused = 1;
2436 }
2437
2438 pad_y2 = suby1 + 28 + 2 * spacing; //reset y coord
2439 pad_y2 += 16;
2440 pad_x4 -= 64;
2441 itemIndex = 7;
2442 if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 0 )
2443 {
2444 strcpy(tmpStr, "NULL");
2445 }
2446 else if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 1 )
2447 {
2448 strcpy(tmpStr, "RAND");
2449 }
2450 else
2451 {
2452 snprintf(tmpStr, 4, "%d", tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES]);
2453 }
2454
2455 if ( canWearEquip(selectedEntity, itemIndex) )
2456 {
2457 butMonsterCloak = newButton();
2458 strcpy(butMonsterCloak->label, tmpStr);
2459 butMonsterCloak->x = pad_x4 - 10;
2460 butMonsterCloak->y = pad_y2 + spacing - 4;
2461 butMonsterCloak->sizex = pad_x4 + pad_x3 - (pad_x4 - 10);
2462 butMonsterCloak->sizey = 16;
2463 butMonsterCloak->action = &buttonMonsterItems;
2464 butMonsterCloak->visible = 1;
2465 butMonsterCloak->focused = 1;
2466 }
2467
2468 pad_x4 += 64 * 2;
2469 itemIndex = 8;
2470
2471 if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 0 )
2472 {
2473 strcpy(tmpStr, "NULL");
2474 }
2475 else if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 1 )
2476 {
2477 strcpy(tmpStr, "RAND");
2478 }
2479 else
2480 {
2481 snprintf(tmpStr, 4, "%d", tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES]);
2482 }
2483
2484 if ( canWearEquip(selectedEntity, itemIndex) )
2485 {
2486 butMonsterMask = newButton();
2487 strcpy(butMonsterMask->label, tmpStr);
2488 butMonsterMask->x = pad_x4 - 10;
2489 butMonsterMask->y = pad_y2 + spacing - 4;
2490 butMonsterMask->sizex = pad_x4 + pad_x3 - (pad_x4 - 10);
2491 butMonsterMask->sizey = 16;
2492 butMonsterMask->action = &buttonMonsterItems;
2493 butMonsterMask->visible = 1;
2494 butMonsterMask->focused = 1;
2495 }
2496
2497 pad_y2 += spacing * 2;
2498 itemIndex = 2;
2499 if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 0 )
2500 {
2501 strcpy(tmpStr, "NULL");
2502 }
2503 else if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 1 )
2504 {
2505 strcpy(tmpStr, "RAND");
2506 }
2507 else
2508 {
2509 snprintf(tmpStr, 4, "%d", tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES]);
2510 }
2511 if ( canWearEquip(selectedEntity, itemIndex) )
2512 {
2513 butMonsterShield = newButton();
2514 strcpy(butMonsterShield->label, tmpStr);
2515 butMonsterShield->x = pad_x4 - 10;
2516 butMonsterShield->y = pad_y2 + spacing - 4;
2517 butMonsterShield->sizex = pad_x4 + pad_x3 - (pad_x4 - 10);
2518 butMonsterShield->sizey = 16;
2519 butMonsterShield->action = &buttonMonsterItems;
2520 butMonsterShield->visible = 1;
2521 butMonsterShield->focused = 1;
2522 }
2523
2524 pad_x4 -= 64 * 2;
2525 itemIndex = 1;
2526 if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 0 )
2527 {
2528 strcpy(tmpStr, "NULL");
2529 }
2530 else if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 1 )
2531 {
2532 strcpy(tmpStr, "RAND");
2533 }
2534 else
2535 {
2536 snprintf(tmpStr, 4, "%d", tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES]);
2537 }
2538 if ( canWearEquip(selectedEntity, itemIndex) )
2539 {
2540 butMonsterWeapon = newButton();
2541 strcpy(butMonsterWeapon->label, tmpStr);
2542 butMonsterWeapon->x = pad_x4 - 10;
2543 butMonsterWeapon->y = pad_y2 + spacing - 4;
2544 butMonsterWeapon->sizex = pad_x4 + pad_x3 - (pad_x4 - 10);
2545 butMonsterWeapon->sizey = 16;
2546 butMonsterWeapon->action = &buttonMonsterItems;
2547 butMonsterWeapon->visible = 1;
2548 butMonsterWeapon->focused = 1;
2549 }
2550
2551 pad_y2 += spacing * 2;
2552 itemIndex = 5;
2553 if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 0 )
2554 {
2555 strcpy(tmpStr, "NULL");
2556 }
2557 else if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 1 )
2558 {
2559 strcpy(tmpStr, "RAND");
2560 }
2561 else
2562 {
2563 snprintf(tmpStr, 4, "%d", tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES]);
2564 }
2565
2566 if ( canWearEquip(selectedEntity, itemIndex) )
2567 {
2568 butMonsterRing = newButton();
2569 strcpy(butMonsterRing->label, tmpStr);
2570 butMonsterRing->x = pad_x4 - 10;
2571 butMonsterRing->y = pad_y2 + spacing - 4;
2572 butMonsterRing->sizex = pad_x4 + pad_x3 - (pad_x4 - 10);
2573 butMonsterRing->sizey = 16;
2574 butMonsterRing->action = &buttonMonsterItems;
2575 butMonsterRing->visible = 1;
2576 butMonsterRing->focused = 1;
2577 }
2578 pad_x4 += 64 * 2;
2579 itemIndex = 9;
2580 if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 0 )
2581 {
2582 strcpy(tmpStr, "NULL");
2583 }
2584 else if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 1 )
2585 {
2586 strcpy(tmpStr, "RAND");
2587 }
2588 else
2589 {
2590 snprintf(tmpStr, 4, "%d", tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES]);
2591 }
2592 if ( canWearEquip(selectedEntity, itemIndex) )
2593 {
2594 butMonsterGloves = newButton();
2595 strcpy(butMonsterGloves->label, tmpStr);
2596 butMonsterGloves->x = pad_x4 - 10;
2597 butMonsterGloves->y = pad_y2 + spacing - 4;
2598 butMonsterGloves->sizex = pad_x4 + pad_x3 - (pad_x4 - 10);
2599 butMonsterGloves->sizey = 16;
2600 butMonsterGloves->action = &buttonMonsterItems;
2601 butMonsterGloves->visible = 1;
2602 butMonsterGloves->focused = 1;
2603 }
2604
2605 pad_y2 += 32 + spacing * 2;
2606 itemIndex = 12;
2607 if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 0 )
2608 {
2609 strcpy(tmpStr, "NULL");
2610 }
2611 else if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 1 )
2612 {
2613 strcpy(tmpStr, "RAND");
2614 }
2615 else
2616 {
2617 snprintf(tmpStr, 4, "%d", tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES]);
2618 }
2619 butMonsterItem3 = newButton();
2620 strcpy(butMonsterItem3->label, tmpStr);
2621 butMonsterItem3->x = pad_x4 - 10;
2622 butMonsterItem3->y = pad_y2 + spacing - 4;
2623 butMonsterItem3->sizex = pad_x4 + pad_x3 - (pad_x4 - 10);
2624 butMonsterItem3->sizey = 16;
2625 butMonsterItem3->action = &buttonMonsterItems;
2626 butMonsterItem3->visible = 1;
2627 butMonsterItem3->focused = 1;
2628
2629 itemIndex = 15;
2630 if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 0 )
2631 {
2632 strcpy(tmpStr, "NULL");
2633 }
2634 else if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 1 )
2635 {
2636 strcpy(tmpStr, "RAND");
2637 }
2638 else
2639 {
2640 snprintf(tmpStr, 4, "%d", tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES]);
2641 }
2642 butMonsterItem6 = newButton();
2643 strcpy(butMonsterItem6->label, tmpStr);
2644 butMonsterItem6->x = pad_x4 - 10;
2645 butMonsterItem6->y = pad_y2 + 2 * spacing - 4;
2646 butMonsterItem6->sizex = pad_x4 + pad_x3 - (pad_x4 - 10);
2647 butMonsterItem6->sizey = 16;
2648 butMonsterItem6->action = &buttonMonsterItems;
2649 butMonsterItem6->visible = 1;
2650 butMonsterItem6->focused = 1;
2651
2652 pad_x4 -= 64;
2653 itemIndex = 11;
2654 if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 0 )
2655 {
2656 strcpy(tmpStr, "NULL");
2657 }
2658 else if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 1 )
2659 {
2660 strcpy(tmpStr, "RAND");
2661 }
2662 else
2663 {
2664 snprintf(tmpStr, 4, "%d", tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES]);
2665 }
2666 butMonsterItem2 = newButton();
2667 strcpy(butMonsterItem2->label, tmpStr);
2668 butMonsterItem2->x = pad_x4 - 10;
2669 butMonsterItem2->y = pad_y2 + spacing - 4;
2670 butMonsterItem2->sizex = pad_x4 + pad_x3 - (pad_x4 - 10);
2671 butMonsterItem2->sizey = 16;
2672 butMonsterItem2->action = &buttonMonsterItems;
2673 butMonsterItem2->visible = 1;
2674 butMonsterItem2->focused = 1;
2675
2676 itemIndex = 14;
2677 if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 0 )
2678 {
2679 strcpy(tmpStr, "NULL");
2680 }
2681 else if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 1 )
2682 {
2683 strcpy(tmpStr, "RAND");
2684 }
2685 else
2686 {
2687 snprintf(tmpStr, 4, "%d", tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES]);
2688 }
2689 butMonsterItem5 = newButton();
2690 strcpy(butMonsterItem5->label, tmpStr);
2691 butMonsterItem5->x = pad_x4 - 10;
2692 butMonsterItem5->y = pad_y2 + 2 * spacing - 4;
2693 butMonsterItem5->sizex = pad_x4 + pad_x3 - (pad_x4 - 10);
2694 butMonsterItem5->sizey = 16;
2695 butMonsterItem5->action = &buttonMonsterItems;
2696 butMonsterItem5->visible = 1;
2697 butMonsterItem5->focused = 1;
2698
2699 pad_x4 -= 64;
2700 itemIndex = 10;
2701 if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 0 )
2702 {
2703 strcpy(tmpStr, "NULL");
2704 }
2705 else if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 1 )
2706 {
2707 strcpy(tmpStr, "RAND");
2708 }
2709 else
2710 {
2711 snprintf(tmpStr, 4, "%d", tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES]);
2712 }
2713 butMonsterItem1 = newButton();
2714 strcpy(butMonsterItem1->label, tmpStr);
2715 butMonsterItem1->x = pad_x4 - 10;
2716 butMonsterItem1->y = pad_y2 + spacing - 4;
2717 butMonsterItem1->sizex = pad_x4 + pad_x3 - (pad_x4 - 10);
2718 butMonsterItem1->sizey = 16;
2719 butMonsterItem1->action = &buttonMonsterItems;
2720 butMonsterItem1->visible = 1;
2721 butMonsterItem1->focused = 1;
2722
2723 itemIndex = 13;
2724 if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 0 )
2725 {
2726 strcpy(tmpStr, "NULL");
2727 }
2728 else if ( tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES] == 1 )
2729 {
2730 strcpy(tmpStr, "RAND");
2731 }
2732 else
2733 {
2734 snprintf(tmpStr, 4, "%d", tmpSpriteStats->EDITOR_ITEMS[itemIndex * ITEM_SLOT_NUMPROPERTIES]);
2735 }
2736 butMonsterItem4 = newButton();
2737 strcpy(butMonsterItem4->label, tmpStr);
2738 butMonsterItem4->x = pad_x4 - 10;
2739 butMonsterItem4->y = pad_y2 + 2 * spacing - 4;
2740 butMonsterItem4->sizex = pad_x4 + pad_x3 - (pad_x4 - 10);
2741 butMonsterItem4->sizey = 16;
2742 butMonsterItem4->action = &buttonMonsterItems;
2743 butMonsterItem4->visible = 1;
2744 butMonsterItem4->focused = 1;
2745 }
2746 break;
2747 case 3: //items
2748 butItemOK = newButton();
2749 strcpy(butItemOK->label, " OK ");
2750 butItemOK->x = subx2 - 128;
2751 butItemOK->y = suby2 - 24;
2752 butItemOK->sizex = 56;
2753 butItemOK->sizey = 16;
2754 butItemOK->action = &buttonSpritePropertiesConfirm;
2755 butItemOK->visible = 1;
2756 butItemOK->focused = 1;
2757
2758 butItemCancel = newButton();
2759 strcpy(butItemCancel->label, "Cancel");
2760 butItemCancel->x = subx2 - 64;
2761 butItemCancel->y = suby2 - 24;
2762 butItemCancel->sizex = 56;
2763 butItemCancel->sizey = 16;
2764 butItemCancel->action = &buttonCloseSpriteSubwindow;
2765 butItemCancel->visible = 1;
2766 butItemCancel->focused = 1;
2767
2768 butItemX = newButton();
2769 strcpy(butItemX->label, "X");
2770 butItemX->x = subx2 - 16;
2771 butItemX->y = suby1;
2772 butItemX->sizex = 16;
2773 butItemX->sizey = 16;
2774 butItemX->action = &buttonCloseSpriteSubwindow;
2775 butItemX->visible = 1;
2776 butItemX->focused = 1;
2777 break;
2778 default:
2779 button = newButton();
2780 strcpy(button->label, " OK ");
2781 button->x = subx2 - 64;
2782 button->y = suby2 - 48;
2783 button->sizex = 56;
2784 button->sizey = 16;
2785 button->action = &buttonSpritePropertiesConfirm;
2786 button->visible = 1;
2787 button->focused = 1;
2788 break;
2789 }
2790
2791 if ( spriteType != 1 && spriteType != 3 )
2792 {
2793 button = newButton();
2794 strcpy(button->label, "Cancel");
2795 button->x = subx2 - 64;
2796 button->y = suby2 - 24;
2797 button->sizex = 56;
2798 button->sizey = 16;
2799 button->action = &buttonCloseSpriteSubwindow;
2800 button->visible = 1;
2801 button->focused = 1;
2802
2803 button = newButton();
2804 strcpy(button->label, "X");
2805 button->x = subx2 - 16;
2806 button->y = suby1;
2807 button->sizex = 16;
2808 button->sizey = 16;
2809 button->action = &buttonCloseSpriteSubwindow;
2810 button->visible = 1;
2811 button->focused = 1;
2812 }
2813 }
2814 }
2815
buttonSpritePropertiesConfirm(button_t * my)2816 void buttonSpritePropertiesConfirm(button_t* my)
2817 {
2818 Stat* tmpSpriteStats = NULL;
2819 button_t* button = NULL;
2820 if ( selectedEntity != NULL )
2821 {
2822 int spriteType = checkSpriteType(selectedEntity->sprite);
2823 switch ( spriteType )
2824 {
2825 case 1: //monsters
2826 tmpSpriteStats = selectedEntity->getStats();
2827 if ( tmpSpriteStats != nullptr )
2828 {
2829 if ( my == butMonsterItemOK )
2830 {
2831 if ( strcmp(spriteProperties[0], "0") < 0 )
2832 {
2833 strcpy(spriteProperties[0], "1");
2834 }
2835 tmpSpriteStats->EDITOR_ITEMS[(itemSlotSelected)* ITEM_SLOT_NUMPROPERTIES] = (Sint32)atoi(spriteProperties[0]);
2836 tmpSpriteStats->EDITOR_ITEMS[(itemSlotSelected)* ITEM_SLOT_NUMPROPERTIES + 1] = (Sint32)atoi(spriteProperties[1]);
2837 if ( strcmp(spriteProperties[2], "00") == 0 )
2838 {
2839 selectedEntity->skill[12] = 10; //bless random
2840 }
2841 else
2842 {
2843 tmpSpriteStats->EDITOR_ITEMS[(itemSlotSelected)* ITEM_SLOT_NUMPROPERTIES + 2] = (Sint32)atoi(spriteProperties[2]); //bless
2844 }
2845 if ( strcmp(spriteProperties[3], "0") == 0 )
2846 {
2847 tmpSpriteStats->EDITOR_ITEMS[(itemSlotSelected)* ITEM_SLOT_NUMPROPERTIES + 2] = 1; //reset quantity to 1
2848 }
2849 if ( strcmp(spriteProperties[3], "0") == 0 )
2850 {
2851 tmpSpriteStats->EDITOR_ITEMS[(itemSlotSelected)* ITEM_SLOT_NUMPROPERTIES + 3] = 1; //reset quantity to 1
2852 }
2853 else
2854 {
2855 tmpSpriteStats->EDITOR_ITEMS[(itemSlotSelected)* ITEM_SLOT_NUMPROPERTIES + 3] = (Sint32)atoi(spriteProperties[3]); //quantity
2856 }
2857 tmpSpriteStats->EDITOR_ITEMS[(itemSlotSelected)* ITEM_SLOT_NUMPROPERTIES + 4] = (Sint32)atoi(spriteProperties[4]);
2858 tmpSpriteStats->EDITOR_ITEMS[(itemSlotSelected)* ITEM_SLOT_NUMPROPERTIES + 5] = (Sint32)atoi(spriteProperties[5]);
2859 tmpSpriteStats->EDITOR_ITEMS[(itemSlotSelected)* ITEM_SLOT_NUMPROPERTIES + 6] = (Sint32)atoi(spriteProperties[6]);
2860 newwindow = 2;
2861
2862 /*button = newButton();
2863 strcpy(button->label, "Cancel");
2864 button->x = subx2 - 64;
2865 button->y = suby2 - 24;
2866 button->sizex = 56;
2867 button->sizey = 16;
2868 button->action = &buttonCloseSpriteSubwindow;
2869 button->visible = 1;
2870 button->focused = 1;
2871
2872 button = newButton();
2873 strcpy(button->label, "X");
2874 button->x = subx2 - 16;
2875 button->y = suby1;
2876 button->sizex = 16;
2877 button->sizey = 16;
2878 button->action = &buttonCloseSpriteSubwindow;
2879 button->visible = 1;
2880 button->focused = 1;
2881
2882 button = newButton();
2883 strcpy(button->label, " OK ");
2884 button->x = subx2 - 64;
2885 button->y = suby2 - 48;
2886 button->sizex = 56;
2887 button->sizey = 16;
2888 button->action = &buttonSpritePropertiesConfirm;
2889 button->visible = 1;
2890 button->focused = 1;*/
2891
2892 //butItemOK->visible = 0;
2893 //butItemCancel->visible = 0;
2894 //butItemX->visible = 0;
2895 if ( butMonsterItemOK != NULL )
2896 {
2897 butMonsterItemOK->visible = 0;
2898 }
2899 if ( butMonsterItemX != NULL )
2900 {
2901 butMonsterItemX->visible = 0;
2902 }
2903 if ( butMonsterItemCancel != NULL )
2904 {
2905 butMonsterItemCancel->visible = 0;
2906 }
2907
2908 // retrieves any modified monster stats, restored when window is closed.
2909
2910 for ( int i = 0; i < sizeof(spriteProperties) / sizeof(spriteProperties[0]); i++ )
2911 {
2912 strcpy(spriteProperties[i], tmpSpriteProperties[i]);
2913 }
2914 }
2915 else
2916 {
2917 strcpy(tmpSpriteStats->name, spriteProperties[0]);
2918 tmpSpriteStats->MAXHP = (Sint32)atoi(spriteProperties[1]);
2919 tmpSpriteStats->HP = (Sint32)atoi(spriteProperties[2]);
2920 tmpSpriteStats->MAXMP = (Sint32)atoi(spriteProperties[3]);
2921 tmpSpriteStats->MP = (Sint32)atoi(spriteProperties[4]);
2922 tmpSpriteStats->LVL = (Sint32)atoi(spriteProperties[5]);
2923 tmpSpriteStats->GOLD = (Sint32)atoi(spriteProperties[6]);
2924 tmpSpriteStats->STR = (Sint32)atoi(spriteProperties[7]);
2925 tmpSpriteStats->DEX = (Sint32)atoi(spriteProperties[8]);
2926 tmpSpriteStats->CON = (Sint32)atoi(spriteProperties[9]);
2927 tmpSpriteStats->INT = (Sint32)atoi(spriteProperties[10]);
2928 tmpSpriteStats->PER = (Sint32)atoi(spriteProperties[11]);
2929 tmpSpriteStats->CHR = (Sint32)atoi(spriteProperties[12]);
2930
2931 tmpSpriteStats->RANDOM_MAXHP = (Sint32)atoi(spriteProperties[13]) - tmpSpriteStats->MAXHP;
2932 if ( tmpSpriteStats->RANDOM_MAXHP < 0 )
2933 {
2934 tmpSpriteStats->RANDOM_MAXHP = 0;
2935 }
2936 tmpSpriteStats->RANDOM_HP = (Sint32)atoi(spriteProperties[14]) - tmpSpriteStats->HP;
2937 if ( tmpSpriteStats->RANDOM_HP < 0 )
2938 {
2939 tmpSpriteStats->RANDOM_HP = 0;
2940 }
2941 tmpSpriteStats->RANDOM_MAXMP = (Sint32)atoi(spriteProperties[15]) - tmpSpriteStats->MAXMP;
2942 if ( tmpSpriteStats->RANDOM_MAXMP < 0 )
2943 {
2944 tmpSpriteStats->RANDOM_MAXMP = 0;
2945 }
2946 tmpSpriteStats->RANDOM_MP = (Sint32)atoi(spriteProperties[16]) - tmpSpriteStats->MP;
2947 if ( tmpSpriteStats->RANDOM_MP < 0 )
2948 {
2949 tmpSpriteStats->RANDOM_MP = 0;
2950 }
2951 tmpSpriteStats->RANDOM_LVL = (Sint32)atoi(spriteProperties[17]) - tmpSpriteStats->LVL;
2952 if ( tmpSpriteStats->RANDOM_LVL < 0 )
2953 {
2954 tmpSpriteStats->RANDOM_LVL = 0;
2955 }
2956 tmpSpriteStats->RANDOM_GOLD = (Sint32)atoi(spriteProperties[18]) - tmpSpriteStats->GOLD;
2957 if ( tmpSpriteStats->RANDOM_GOLD < 0 )
2958 {
2959 tmpSpriteStats->RANDOM_GOLD = 0;
2960 }
2961 tmpSpriteStats->RANDOM_STR = (Sint32)atoi(spriteProperties[19]) - tmpSpriteStats->STR;
2962 if ( tmpSpriteStats->RANDOM_STR < 0 )
2963 {
2964 tmpSpriteStats->RANDOM_STR = 0;
2965 }
2966 tmpSpriteStats->RANDOM_DEX = (Sint32)atoi(spriteProperties[20]) - tmpSpriteStats->DEX;
2967 if ( tmpSpriteStats->RANDOM_DEX < 0 )
2968 {
2969 tmpSpriteStats->RANDOM_DEX = 0;
2970 }
2971 tmpSpriteStats->RANDOM_CON = (Sint32)atoi(spriteProperties[21]) - tmpSpriteStats->CON;
2972 if ( tmpSpriteStats->RANDOM_CON < 0 )
2973 {
2974 tmpSpriteStats->RANDOM_CON = 0;
2975 }
2976 tmpSpriteStats->RANDOM_INT = (Sint32)atoi(spriteProperties[22]) - tmpSpriteStats->INT;
2977 if ( tmpSpriteStats->RANDOM_INT < 0 )
2978 {
2979 tmpSpriteStats->RANDOM_INT = 0;
2980 }
2981 tmpSpriteStats->RANDOM_PER = (Sint32)atoi(spriteProperties[23]) - tmpSpriteStats->PER;
2982 if ( tmpSpriteStats->RANDOM_PER < 0 )
2983 {
2984 tmpSpriteStats->RANDOM_PER = 0;
2985 }
2986 tmpSpriteStats->RANDOM_CHR = (Sint32)atoi(spriteProperties[24]) - tmpSpriteStats->CHR;
2987 if ( tmpSpriteStats->RANDOM_CHR < 0 )
2988 {
2989 tmpSpriteStats->RANDOM_CHR = 0;
2990 }
2991 tmpSpriteStats->MISC_FLAGS[STAT_FLAG_NPC] = (Sint32)atoi(spriteProperties[25]);
2992 if ( !strcmp(spriteProperties[31], "disable") )
2993 {
2994 tmpSpriteStats->MISC_FLAGS[STAT_FLAG_DISABLE_MINIBOSS] = 1;
2995 }
2996 else
2997 {
2998 tmpSpriteStats->MISC_FLAGS[STAT_FLAG_DISABLE_MINIBOSS] = 0;
2999 }
3000 }
3001 }
3002 break;
3003 case 2: //chest
3004 selectedEntity->yaw = (real_t)atoi(spriteProperties[0]);
3005 selectedEntity->skill[9] = (Sint32)atoi(spriteProperties[1]);
3006 selectedEntity->chestLocked = (Sint32)atoi(spriteProperties[2]);
3007 break;
3008 case 3: //items
3009 if ( strcmp(spriteProperties[0], "0") == 0 )
3010 {
3011 strcpy(spriteProperties[0], "1");
3012 }
3013 selectedEntity->skill[10] = (Sint32)atoi(spriteProperties[0]); //id
3014 selectedEntity->skill[11] = (Sint32)atoi(spriteProperties[1]); //status
3015 if ( strcmp(spriteProperties[2], "00") == 0 )
3016 {
3017 selectedEntity->skill[12] = 10; //bless random
3018 }
3019 else
3020 {
3021 selectedEntity->skill[12] = (Sint32)atoi(spriteProperties[2]); //bless
3022 }
3023 if ( strcmp(spriteProperties[3], "0") == 0 )
3024 {
3025 selectedEntity->skill[13] = 1; //reset quantity to 1
3026 }
3027 else
3028 {
3029 selectedEntity->skill[13] = (Sint32)atoi(spriteProperties[3]); //quantity
3030 }
3031 selectedEntity->skill[15] = (Sint32)atoi(spriteProperties[4]); //identified
3032 selectedEntity->skill[16] = (Sint32)atoi(spriteProperties[5]); //cateogry if random
3033 break;
3034 case 4: //summoning traps
3035 if ( (Sint32)atoi(spriteProperties[0]) < -1 || (Sint32)atoi(spriteProperties[0]) == 6
3036 || (Sint32)atoi(spriteProperties[0]) == 12 || (Sint32)atoi(spriteProperties[0]) == 16 )
3037 {
3038 selectedEntity->skill[0] = 0;
3039 }
3040 else
3041 {
3042 selectedEntity->skill[0] = (Sint32)atoi(spriteProperties[0]); //Monster to Spawn
3043 }
3044
3045 if ( (Sint32)atoi(spriteProperties[1]) == 0 )
3046 {
3047 selectedEntity->skill[1] = 1;
3048 }
3049 else
3050 {
3051 selectedEntity->skill[1] = (Sint32)atoi(spriteProperties[1]); //Qty
3052 }
3053
3054 if ( (Sint32)atoi(spriteProperties[2]) == 0 )
3055 {
3056 selectedEntity->skill[2] = 1;
3057 }
3058 else
3059 {
3060 selectedEntity->skill[2] = (Sint32)atoi(spriteProperties[2]); //Time Between Spawns
3061 }
3062
3063 if ( (Sint32)atoi(spriteProperties[3]) == 0 )
3064 {
3065 selectedEntity->skill[3] = 1;
3066 }
3067 else
3068 {
3069 selectedEntity->skill[3] = (Sint32)atoi(spriteProperties[3]); //Amount of Spawns
3070 }
3071 selectedEntity->skill[4] = (Sint32)atoi(spriteProperties[4]); //Requires Power
3072 selectedEntity->skill[5] = (Sint32)atoi(spriteProperties[5]); //Chance to Stop Working
3073 break;
3074 case 5: //power crystal
3075 selectedEntity->yaw = (real_t)atoi(spriteProperties[0]);
3076 selectedEntity->crystalNumElectricityNodes = (Sint32)atoi(spriteProperties[1]);
3077 selectedEntity->crystalTurnReverse = (Sint32)atoi(spriteProperties[2]);
3078 selectedEntity->crystalSpellToActivate = (Sint32)atoi(spriteProperties[3]);
3079 break;
3080 case 6: //lever timer
3081 if ( (Sint32)atoi(spriteProperties[0]) == 0 )
3082 {
3083 selectedEntity->leverTimerTicks = 1;
3084 }
3085 else
3086 {
3087 selectedEntity->leverTimerTicks = (Sint32)atoi(spriteProperties[0]);
3088 }
3089 break;
3090 case 7: //boulder trap
3091 selectedEntity->boulderTrapRefireAmount = (Sint32)atoi(spriteProperties[0]);
3092 if ( (Sint32)atoi(spriteProperties[1]) < 2 )
3093 {
3094 selectedEntity->boulderTrapRefireDelay = 2;
3095 }
3096 else
3097 {
3098 selectedEntity->boulderTrapRefireDelay = (Sint32)atoi(spriteProperties[1]);
3099 }
3100 if ( (Sint32)atoi(spriteProperties[2]) < 0 )
3101 {
3102 selectedEntity->boulderTrapPreDelay = 0;
3103 }
3104 else
3105 {
3106 selectedEntity->boulderTrapPreDelay = (Sint32)atoi(spriteProperties[2]);
3107 }
3108 break;
3109 case 8: //pedestal
3110 selectedEntity->pedestalOrbType = (Sint32)atoi(spriteProperties[0]);
3111 selectedEntity->pedestalHasOrb = (Sint32)atoi(spriteProperties[1]);
3112 selectedEntity->pedestalInvertedPower = (Sint32)atoi(spriteProperties[2]);
3113 selectedEntity->pedestalInGround = (Sint32)atoi(spriteProperties[3]);
3114 selectedEntity->pedestalLockOrb = (Sint32)atoi(spriteProperties[4]);
3115 break;
3116 case 9: //teleporter
3117 selectedEntity->teleporterX = (Sint32)atoi(spriteProperties[0]);
3118 selectedEntity->teleporterY = (Sint32)atoi(spriteProperties[1]);
3119 selectedEntity->teleporterType = (Sint32)atoi(spriteProperties[2]);
3120 break;
3121 case 10: //ceiling tile model
3122 selectedEntity->ceilingTileModel = (Sint32)atoi(spriteProperties[0]);
3123 break;
3124 case 11: //spell trap ceiling
3125 selectedEntity->spellTrapType = (Sint32)atoi(spriteProperties[0]);
3126 selectedEntity->spellTrapRefire = (Sint32)atoi(spriteProperties[1]);
3127 selectedEntity->spellTrapLatchPower = (Sint32)atoi(spriteProperties[2]);
3128 selectedEntity->spellTrapFloorTile = (Sint32)atoi(spriteProperties[3]);
3129 selectedEntity->spellTrapRefireRate = (Sint32)atoi(spriteProperties[4]);
3130 break;
3131 case 12: //furniture
3132 selectedEntity->furnitureDir = (Sint32)atoi(spriteProperties[0]);
3133 break;
3134 case 13: //floor decoration
3135 {
3136 selectedEntity->floorDecorationModel = (Sint32)atoi(spriteProperties[0]);
3137 selectedEntity->floorDecorationRotation = (Sint32)atoi(spriteProperties[1]);
3138 selectedEntity->floorDecorationHeightOffset = (Sint32)atoi(spriteProperties[2]);
3139 selectedEntity->floorDecorationXOffset = (Sint32)atoi(spriteProperties[3]);
3140 selectedEntity->floorDecorationYOffset = (Sint32)atoi(spriteProperties[4]);
3141
3142 int totalChars = 0;
3143 char checkChr = 'a';
3144 const int kMaxCharacters = 192; // 4x48 char fields.
3145 for ( int i = 8; i < 60 && totalChars < kMaxCharacters; ++i )
3146 {
3147 selectedEntity->skill[i] = 0;
3148 }
3149 for ( int i = 8; i < 60 && totalChars < kMaxCharacters; ++i )
3150 {
3151 if ( i == 28 ) // circuit_status
3152 {
3153 continue;
3154 }
3155 for ( int c = 0; c < 4; ++c )
3156 {
3157 if ( totalChars >= 144 )
3158 {
3159 selectedEntity->skill[i] |= (spriteProperties[8][totalChars - 144]) << (c * 8);
3160 checkChr = spriteProperties[8][totalChars - 144];
3161 }
3162 else if ( totalChars >= 96 )
3163 {
3164 selectedEntity->skill[i] |= (spriteProperties[7][totalChars - 96]) << (c * 8);
3165 checkChr = spriteProperties[7][totalChars - 96];
3166 }
3167 else if ( totalChars >= 48 )
3168 {
3169 selectedEntity->skill[i] |= (spriteProperties[6][totalChars - 48]) << (c * 8);
3170 checkChr = spriteProperties[6][totalChars - 48];
3171 }
3172 else
3173 {
3174 selectedEntity->skill[i] |= (spriteProperties[5][totalChars]) << (c * 8);
3175 checkChr = spriteProperties[5][totalChars];
3176 }
3177 if ( checkChr == '\0' )
3178 {
3179 totalChars += (48 - (totalChars % 48));
3180 }
3181 else
3182 {
3183 ++totalChars;
3184 }
3185 }
3186 }
3187 }
3188 break;
3189 case 14: //sound source
3190 selectedEntity->soundSourceToPlay = (Sint32)atoi(spriteProperties[0]);
3191 selectedEntity->soundSourceVolume = (Sint32)atoi(spriteProperties[1]);
3192 selectedEntity->soundSourceLatchOn = (Sint32)atoi(spriteProperties[2]);
3193 selectedEntity->soundSourceDelay = (Sint32)atoi(spriteProperties[3]);
3194 selectedEntity->soundSourceOrigin = (Sint32)atoi(spriteProperties[4]);
3195 break;
3196 case 15: //light source
3197 selectedEntity->lightSourceAlwaysOn = (Sint32)atoi(spriteProperties[0]);
3198 selectedEntity->lightSourceBrightness = (Sint32)atoi(spriteProperties[1]);
3199 selectedEntity->lightSourceInvertPower = (Sint32)atoi(spriteProperties[2]);
3200 selectedEntity->lightSourceLatchOn = (Sint32)atoi(spriteProperties[3]);
3201 selectedEntity->lightSourceRadius = (Sint32)atoi(spriteProperties[4]);
3202 selectedEntity->lightSourceFlicker = (Sint32)atoi(spriteProperties[5]);
3203 selectedEntity->lightSourceDelay = (Sint32)atoi(spriteProperties[6]);
3204 break;
3205 case 16: // text source
3206 {
3207 Uint32 r = (Uint32)atoi(spriteProperties[0]);
3208 Uint32 g = (Uint32)atoi(spriteProperties[1]);
3209 Uint32 b = (Uint32)atoi(spriteProperties[2]);
3210 selectedEntity->textSourceColorRGB = 0;
3211 selectedEntity->textSourceColorRGB |= (r << 16);
3212 selectedEntity->textSourceColorRGB |= (g << 8);
3213 selectedEntity->textSourceColorRGB |= (b << 0);
3214 selectedEntity->textSourceDelay = (Sint32)atoi(spriteProperties[8]);
3215 selectedEntity->textSourceVariables4W = 0;
3216 selectedEntity->textSourceVariables4W |= ((Sint32)atoi(spriteProperties[9]) & 0xFF) << 8;
3217 int totalChars = 0;
3218 char checkChr = 'a';
3219 const int kMaxCharacters = 220; //55 skills, starting at 4 ending at 59, skipping 28. storing 4 chars each.
3220 for ( int i = 4; i < 60 && totalChars < kMaxCharacters; ++i )
3221 {
3222 selectedEntity->skill[i] = 0;
3223 }
3224 for ( int i = 4; i < 60 && totalChars < kMaxCharacters; ++i )
3225 {
3226 if ( i == 28 ) // circuit_status
3227 {
3228 continue;
3229 }
3230 for ( int c = 0; c < 4; ++c )
3231 {
3232 if ( totalChars >= 192 )
3233 {
3234 selectedEntity->skill[i] |= (spriteProperties[7][totalChars - 192]) << (c * 8);
3235 checkChr = spriteProperties[7][totalChars - 192];
3236 }
3237 else if ( totalChars >= 144 )
3238 {
3239 selectedEntity->skill[i] |= (spriteProperties[6][totalChars - 144]) << (c * 8);
3240 checkChr = spriteProperties[6][totalChars - 144];
3241 }
3242 else if ( totalChars >= 96 )
3243 {
3244 selectedEntity->skill[i] |= (spriteProperties[5][totalChars - 96]) << (c * 8);
3245 checkChr = spriteProperties[5][totalChars - 96];
3246 }
3247 else if ( totalChars >= 48 )
3248 {
3249 selectedEntity->skill[i] |= (spriteProperties[4][totalChars - 48]) << (c * 8);
3250 checkChr = spriteProperties[4][totalChars - 48];
3251 }
3252 else
3253 {
3254 selectedEntity->skill[i] |= (spriteProperties[3][totalChars]) << (c * 8);
3255 checkChr = spriteProperties[3][totalChars];
3256 }
3257 if ( checkChr == '\0' )
3258 {
3259 totalChars += (48 - (totalChars % 48));
3260 }
3261 else
3262 {
3263 ++totalChars;
3264 }
3265 }
3266 }
3267 break;
3268 }
3269 case 17:
3270 selectedEntity->signalInputDirection = (Sint32)atoi(spriteProperties[0]);
3271 selectedEntity->signalActivateDelay = (Sint32)atoi(spriteProperties[1]);
3272 selectedEntity->signalTimerInterval = (Sint32)atoi(spriteProperties[2]);
3273 selectedEntity->signalTimerRepeatCount = (Sint32)atoi(spriteProperties[3]);
3274 selectedEntity->signalTimerLatchInput = (Sint32)atoi(spriteProperties[4]);
3275 break;
3276 case 18: // custom portal
3277 {
3278 selectedEntity->portalCustomSprite = (Sint32)atoi(spriteProperties[0]);
3279 selectedEntity->portalCustomSpriteAnimationFrames = (Sint32)atoi(spriteProperties[1]);
3280 selectedEntity->portalCustomZOffset = (Sint32)atoi(spriteProperties[2]);
3281 selectedEntity->portalCustomLevelsToJump = (Sint32)atoi(spriteProperties[3]);
3282 selectedEntity->portalCustomRequiresPower = (Sint32)atoi(spriteProperties[5]);
3283 int isSecret = (Sint32)atoi(spriteProperties[6]);
3284 selectedEntity->portalNotSecret = isSecret ? 0 : 1;
3285
3286 int totalChars = 0;
3287 char checkChr = 'a';
3288 const int kMaxCharacters = 32;
3289 for ( int i = 11; i <= 18 && totalChars < kMaxCharacters; ++i )
3290 {
3291 selectedEntity->skill[i] = 0;
3292 }
3293 for ( int i = 11; i <= 18 && totalChars < kMaxCharacters; ++i )
3294 {
3295 if ( i == 28 ) // circuit_status
3296 {
3297 continue;
3298 }
3299 for ( int c = 0; c < 4; ++c )
3300 {
3301 selectedEntity->skill[i] |= (spriteProperties[4][totalChars]) << (c * 8);
3302 checkChr = spriteProperties[4][totalChars];
3303 ++totalChars;
3304 }
3305 }
3306 }
3307 break;
3308 case 19: // tables
3309 selectedEntity->furnitureDir = (Sint32)atoi(spriteProperties[0]);
3310 selectedEntity->furnitureTableSpawnChairs = (Sint32)atoi(spriteProperties[1]);
3311 selectedEntity->furnitureTableRandomItemChance = (Sint32)atoi(spriteProperties[2]);
3312 break;
3313 case 20: // readablebook
3314 {
3315 selectedEntity->skill[11] = (Sint32)atoi(spriteProperties[0]); // status
3316 if ( strcmp(spriteProperties[1], "00") == 0 )
3317 {
3318 selectedEntity->skill[12] = 10; //bless random
3319 }
3320 else
3321 {
3322 selectedEntity->skill[12] = (Sint32)atoi(spriteProperties[1]); //bless
3323 }
3324 selectedEntity->skill[15] = (Sint32)atoi(spriteProperties[2]); // identified
3325 int totalChars = 0;
3326 char checkChr = 'a';
3327 const int kMaxCharacters = 48;
3328 for ( int i = 40; i <= 52 && totalChars < kMaxCharacters; ++i )
3329 {
3330 selectedEntity->skill[i] = 0;
3331 }
3332 for ( int i = 40; i <= 52 && totalChars < kMaxCharacters; ++i )
3333 {
3334 if ( i == 28 ) // circuit_status
3335 {
3336 continue;
3337 }
3338 for ( int c = 0; c < 4; ++c )
3339 {
3340 selectedEntity->skill[i] |= (spriteProperties[3][totalChars]) << (c * 8);
3341 checkChr = spriteProperties[3][totalChars];
3342 ++totalChars;
3343 }
3344 }
3345 }
3346 break;
3347 case 21: // doors
3348 selectedEntity->doorForceLockedUnlocked = (Sint32)atoi(spriteProperties[0]);
3349 selectedEntity->doorDisableLockpicks = (Sint32)atoi(spriteProperties[1]);
3350 selectedEntity->doorDisableOpening = (Sint32)atoi(spriteProperties[2]);
3351 break;
3352 case 22: // gates
3353 selectedEntity->gateDisableOpening = (Sint32)atoi(spriteProperties[0]);
3354 break;
3355 case 23: // player spawn
3356 selectedEntity->playerStartDir = (Sint32)atoi(spriteProperties[0]);
3357 break;
3358 default:
3359 break;
3360 }
3361
3362 strcpy(message, " Modified sprite properties.");
3363 messagetime = 60;
3364 }
3365
3366 if ( my == butMonsterItemOK && tmpSpriteStats != NULL )
3367 {
3368 //copyMonsterStatToPropertyStrings(tmpSpriteStats);
3369 exitFromItemWindow = true;
3370 inputstr = spriteProperties[0];
3371 initMonsterPropertiesWindow();
3372
3373 buttonSpriteProperties(my);
3374 itemSlotSelected = -1;
3375 }
3376 else
3377 {
3378 if ( my == butMonsterOK )
3379 {
3380 makeUndo();
3381 }
3382 buttonCloseSpriteSubwindow(my);
3383 }
3384 }
3385
buttonCloseSpriteSubwindow(button_t * my)3386 void buttonCloseSpriteSubwindow(button_t* my)
3387 {
3388 Stat* tmpSpriteStats = NULL;
3389 // close window
3390 if ( my == butMonsterItemCancel || my == butMonsterItemX )
3391 {
3392 if ( selectedEntity != NULL )
3393 {
3394 tmpSpriteStats = selectedEntity->getStats();
3395 }
3396 if ( tmpSpriteStats != NULL )
3397 {
3398 //copyMonsterStatToPropertyStrings(tmpSpriteStats);
3399 exitFromItemWindow = true;
3400 inputstr = spriteProperties[0];
3401 initMonsterPropertiesWindow();
3402
3403 buttonSpriteProperties(my);
3404 itemSlotSelected = -1;
3405 if ( butMonsterItemOK != NULL )
3406 {
3407 butMonsterItemOK->visible = 0;
3408 }
3409 if ( butMonsterItemX != NULL )
3410 {
3411 butMonsterItemX->visible = 0;
3412 }
3413 if ( butMonsterItemCancel != NULL )
3414 {
3415 butMonsterItemCancel->visible = 0;
3416 }
3417 }
3418 }
3419 else {
3420 selectedEntity = NULL;
3421 newwindow = 0;
3422 subwindow = 0;
3423 editproperty = 0;
3424 spritepalette = 0;
3425 }
3426 }
3427
buttonMonsterItems(button_t * my)3428 void buttonMonsterItems(button_t* my)
3429 {
3430 int spacing = 20;
3431 int pad_y2 = suby1 + 28 + 2 * spacing;
3432 int pad_x3 = 40;
3433 int pad_x4 = subx2 - 112;
3434 char tmpStr[32] = "";
3435 button_t* button = NULL;
3436
3437 itemSelect = 0;
3438
3439 inputstr = spriteProperties[0];
3440 cursorflash = ticks;
3441 menuVisible = 0;
3442 subwindow = 1;
3443 slidery = 0;
3444 subx1 = xres / 2 - 200;
3445 subx2 = xres / 2 + 200;
3446 suby1 = yres / 2 - 158;
3447 suby2 = yres / 2 + 158;
3448 strcpy(subtext, "Monster Item Properties:");
3449
3450 Stat* tmpSpriteStats = selectedEntity->getStats();
3451
3452 // stores any modified monster stats, to be restored when window is closed.
3453
3454 for ( int i = 0; i < sizeof(spriteProperties) / sizeof(spriteProperties[0]); i++ )
3455 {
3456 strcpy(tmpSpriteProperties[i], spriteProperties[i]);
3457 }
3458
3459 if ( my == butMonsterHelm )
3460 {
3461 itemSlotSelected = 0;
3462 }
3463 else if ( my == butMonsterWeapon )
3464 {
3465 itemSlotSelected = 1;
3466 }
3467 else if ( my == butMonsterShield )
3468 {
3469 itemSlotSelected = 2;
3470 }
3471 else if ( my == butMonsterArmor )
3472 {
3473 itemSlotSelected = 3;
3474 }
3475 else if ( my == butMonsterBoots )
3476 {
3477 itemSlotSelected = 4;
3478 }
3479 else if ( my == butMonsterRing )
3480 {
3481 itemSlotSelected = 5;
3482 }
3483 else if ( my == butMonsterAmulet )
3484 {
3485 itemSlotSelected = 6;
3486 }
3487 else if ( my == butMonsterCloak )
3488 {
3489 itemSlotSelected = 7;
3490 }
3491 else if ( my == butMonsterMask )
3492 {
3493 itemSlotSelected = 8;
3494 }
3495 else if ( my == butMonsterGloves )
3496 {
3497 itemSlotSelected = 9;
3498 }
3499 else if ( my == butMonsterItem1 )
3500 {
3501 itemSlotSelected = 10;
3502 }
3503 else if ( my == butMonsterItem2 )
3504 {
3505 itemSlotSelected = 11;
3506 }
3507 else if ( my == butMonsterItem3 )
3508 {
3509 itemSlotSelected = 12;
3510 }
3511 else if ( my == butMonsterItem4 )
3512 {
3513 itemSlotSelected = 13;
3514 }
3515 else if ( my == butMonsterItem5 )
3516 {
3517 itemSlotSelected = 14;
3518 }
3519 else if ( my == butMonsterItem6 )
3520 {
3521 itemSlotSelected = 15;
3522 }
3523 else
3524 {
3525 itemSlotSelected = -1;
3526 }
3527
3528 newwindow = 5;
3529
3530
3531 if ( butMonsterHelm != NULL )
3532 {
3533 butMonsterHelm->visible = 0;
3534 }
3535 if ( butMonsterWeapon != NULL )
3536 {
3537 butMonsterWeapon->visible = 0;
3538 }
3539 if ( butMonsterShield != NULL )
3540 {
3541 butMonsterShield->visible = 0;
3542 }
3543 if ( butMonsterArmor != NULL )
3544 {
3545 butMonsterArmor->visible = 0;
3546 }
3547 if ( butMonsterRing != NULL )
3548 {
3549 butMonsterRing->visible = 0;
3550 }
3551 if ( butMonsterAmulet != NULL )
3552 {
3553 butMonsterAmulet->visible = 0;
3554 }
3555 if ( butMonsterBoots != NULL )
3556 {
3557 butMonsterBoots->visible = 0;
3558 }
3559 if ( butMonsterCloak != NULL )
3560 {
3561 butMonsterCloak->visible = 0;
3562 }
3563 if ( butMonsterMask != NULL )
3564 {
3565 butMonsterMask->visible = 0;
3566 }
3567 if ( butMonsterGloves != NULL )
3568 {
3569 butMonsterGloves->visible = 0;
3570 }
3571 if ( butMonsterItem1 != NULL )
3572 {
3573 butMonsterItem1->visible = 0;
3574 }
3575 if ( butMonsterItem2 != NULL )
3576 {
3577 butMonsterItem2->visible = 0;
3578 }
3579 if ( butMonsterItem3 != NULL )
3580 {
3581 butMonsterItem3->visible = 0;
3582 }
3583 if ( butMonsterItem4 != NULL )
3584 {
3585 butMonsterItem4->visible = 0;
3586 }
3587 if ( butMonsterItem5 != NULL )
3588 {
3589 butMonsterItem5->visible = 0;
3590 }
3591 if ( butMonsterItem6 != NULL )
3592 {
3593 butMonsterItem6->visible = 0;
3594 }
3595 if ( butMonsterOK != NULL )
3596 {
3597 butMonsterOK->visible = 0;
3598 }
3599 if ( butMonsterCancel != NULL )
3600 {
3601 butMonsterCancel->visible = 0;
3602 }
3603 if ( butMonsterX != NULL )
3604 {
3605 butMonsterX->visible = 0;
3606 }
3607 snprintf(spriteProperties[0], 5, "%d", tmpSpriteStats->EDITOR_ITEMS[itemSlotSelected * ITEM_SLOT_NUMPROPERTIES + 0]);
3608 snprintf(spriteProperties[1], 5, "%d", tmpSpriteStats->EDITOR_ITEMS[itemSlotSelected * ITEM_SLOT_NUMPROPERTIES + 1]);
3609 if ( (int)tmpSpriteStats->EDITOR_ITEMS[itemSlotSelected * ITEM_SLOT_NUMPROPERTIES + 2] == 10 )
3610 {
3611 strcpy(spriteProperties[2], "00"); //bless random
3612 }
3613 else
3614 {
3615 snprintf(spriteProperties[2], 4, "%d", (int)tmpSpriteStats->EDITOR_ITEMS[itemSlotSelected * ITEM_SLOT_NUMPROPERTIES + 2]); //bless
3616 }
3617 snprintf(spriteProperties[3], 5, "%d", tmpSpriteStats->EDITOR_ITEMS[itemSlotSelected * ITEM_SLOT_NUMPROPERTIES + 3]);
3618 snprintf(spriteProperties[4], 5, "%d", tmpSpriteStats->EDITOR_ITEMS[itemSlotSelected * ITEM_SLOT_NUMPROPERTIES + 4]);
3619 snprintf(spriteProperties[5], 5, "%d", tmpSpriteStats->EDITOR_ITEMS[itemSlotSelected * ITEM_SLOT_NUMPROPERTIES + 5]);
3620 snprintf(spriteProperties[6], 5, "%d", tmpSpriteStats->EDITOR_ITEMS[itemSlotSelected * ITEM_SLOT_NUMPROPERTIES + 6]);
3621
3622 butMonsterItemOK = newButton();
3623 strcpy(butMonsterItemOK->label, " OK ");
3624 butMonsterItemOK->x = subx2 - 128;
3625 butMonsterItemOK->y = suby2 - 24;
3626 butMonsterItemOK->sizex = 56;
3627 butMonsterItemOK->sizey = 16;
3628 butMonsterItemOK->action = &buttonSpritePropertiesConfirm;
3629 butMonsterItemOK->visible = 1;
3630 butMonsterItemOK->focused = 1;
3631
3632 butMonsterItemCancel = newButton();
3633 strcpy(butMonsterItemCancel->label, "Cancel");
3634 butMonsterItemCancel->x = subx2 - 64;
3635 butMonsterItemCancel->y = suby2 - 24;
3636 butMonsterItemCancel->sizex = 56;
3637 butMonsterItemCancel->sizey = 16;
3638 butMonsterItemCancel->action = &buttonCloseSpriteSubwindow;
3639 butMonsterItemCancel->visible = 1;
3640 butMonsterItemCancel->focused = 1;
3641
3642 butMonsterItemX = newButton();
3643 strcpy(butMonsterItemX->label, "X");
3644 butMonsterItemX->x = subx2 - 16;
3645 butMonsterItemX->y = suby1;
3646 butMonsterItemX->sizex = 16;
3647 butMonsterItemX->sizey = 16;
3648 butMonsterItemX->action = &buttonCloseSpriteSubwindow;
3649 butMonsterItemX->visible = 1;
3650 butMonsterItemX->focused = 1;
3651 }
3652
initMonsterPropertiesWindow()3653 void initMonsterPropertiesWindow() {
3654 cursorflash = ticks;
3655 menuVisible = 0;
3656 subwindow = 1;
3657 newwindow = 2;
3658 subx1 = xres / 2 - 200;
3659 subx2 = xres / 2 + 200;
3660 suby1 = yres / 2 - 190;
3661 suby2 = yres / 2 + 190;
3662 strcpy(subtext, "Sprite properties: ");
3663 strcat(subtext, spriteEditorNameStrings[selectedEntity->sprite]);
3664 }
3665
copyMonsterStatToPropertyStrings(Stat * tmpSpriteStats)3666 void copyMonsterStatToPropertyStrings(Stat* tmpSpriteStats)
3667 {
3668 if ( tmpSpriteStats != NULL )
3669 {
3670 strcpy(spriteProperties[0], tmpSpriteStats->name);
3671 snprintf(spriteProperties[1], 5, "%d", tmpSpriteStats->MAXHP);
3672 snprintf(spriteProperties[2], 5, "%d", tmpSpriteStats->HP);
3673 snprintf(spriteProperties[3], 5, "%d", tmpSpriteStats->MAXMP);
3674 snprintf(spriteProperties[4], 5, "%d", tmpSpriteStats->MP);
3675 snprintf(spriteProperties[5], 4, "%d", tmpSpriteStats->LVL);
3676 snprintf(spriteProperties[6], 4, "%d", tmpSpriteStats->GOLD);
3677 snprintf(spriteProperties[7], 4, "%d", tmpSpriteStats->STR);
3678 snprintf(spriteProperties[8], 4, "%d", tmpSpriteStats->DEX);
3679 snprintf(spriteProperties[9], 4, "%d", tmpSpriteStats->CON);
3680 snprintf(spriteProperties[10], 4, "%d", tmpSpriteStats->INT);
3681 snprintf(spriteProperties[11], 4, "%d", tmpSpriteStats->PER);
3682 snprintf(spriteProperties[12], 4, "%d", tmpSpriteStats->CHR);
3683 snprintf(spriteProperties[13], 5, "%d", tmpSpriteStats->RANDOM_MAXHP + tmpSpriteStats->MAXHP);
3684 snprintf(spriteProperties[14], 5, "%d", tmpSpriteStats->RANDOM_HP + tmpSpriteStats->HP);
3685 snprintf(spriteProperties[15], 5, "%d", tmpSpriteStats->RANDOM_MAXMP + tmpSpriteStats->MAXMP);
3686 snprintf(spriteProperties[16], 5, "%d", tmpSpriteStats->RANDOM_MP + tmpSpriteStats->MP);
3687 snprintf(spriteProperties[17], 4, "%d", tmpSpriteStats->RANDOM_LVL + tmpSpriteStats->LVL);
3688 snprintf(spriteProperties[18], 4, "%d", tmpSpriteStats->RANDOM_GOLD + tmpSpriteStats->GOLD);
3689 snprintf(spriteProperties[19], 4, "%d", tmpSpriteStats->RANDOM_STR + tmpSpriteStats->STR);
3690 snprintf(spriteProperties[20], 4, "%d", tmpSpriteStats->RANDOM_DEX + tmpSpriteStats->DEX);
3691 snprintf(spriteProperties[21], 4, "%d", tmpSpriteStats->RANDOM_CON + tmpSpriteStats->CON);
3692 snprintf(spriteProperties[22], 4, "%d", tmpSpriteStats->RANDOM_INT + tmpSpriteStats->INT);
3693 snprintf(spriteProperties[23], 4, "%d", tmpSpriteStats->RANDOM_PER + tmpSpriteStats->PER);
3694 snprintf(spriteProperties[24], 4, "%d", tmpSpriteStats->RANDOM_CHR + tmpSpriteStats->CHR);
3695 snprintf(spriteProperties[25], 4, "%d", tmpSpriteStats->MISC_FLAGS[STAT_FLAG_NPC]);
3696 if ( tmpSpriteStats->MISC_FLAGS[STAT_FLAG_DISABLE_MINIBOSS] == 0 )
3697 {
3698 strcpy(spriteProperties[31], "");
3699 }
3700 else
3701 {
3702 strcpy(spriteProperties[31], "disable");
3703 }
3704 }
3705 return;
3706 }
3707