LibreWands/Source/editMaps.c

503 lines
14 KiB
C

// This file is part of LibreWands.
// LibreWands is free software: you can redistribute it and/or modify it under the terms of the
// GNU General Public License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
// LibreWands is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
// the GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along with LibreWands. If
// not, see https://www.gnu.org/licenses/.
#include <ncurses.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "engineCore.c"
// Our selected tool and tooltip for base tiles
uint_fast8_t continuousPainting = 0;
uint_fast16_t Btip = '#';
uint_fast8_t BtipColor = 0;
uint_fast8_t BtipWalk = 0;
// Show a menu where the user can select their colour
int colorPick()
{
// Declared Variables
char buffer1[8] = "";
char buffer2[8] = "";
uint_fast8_t a;
uint_fast8_t b;
echo();
clear();
// Prompt for foreground colour
mvprintw(0, 0, "Foreground:");
mvprintw(1, 0, "Black) 0");
mvprintw(2, 0, "Red) 1");
mvprintw(3, 0, "Green) 2");
mvprintw(4, 0, "Yellow) 3");
mvprintw(5, 0, "Blue) 4");
mvprintw(6, 0, "Magenta) 5");
mvprintw(7, 0, "Cyan) 6");
mvprintw(8, 0, "White) 7\n");
getnstr(buffer1, 8);
// Prompt for background colour
mvprintw(10, 0, "Background:");
mvprintw(11, 0, "Black) 0");
mvprintw(12, 0, "Red) 1");
mvprintw(13, 0, "Green) 2");
mvprintw(14, 0, "Yellow) 3");
mvprintw(15, 0, "Blue) 4");
mvprintw(16, 0, "Magenta) 5");
mvprintw(17, 0, "Cyan) 6");
mvprintw(18, 0, "White) 7\n");
getnstr(buffer2, 8);
a = atoi(buffer1);
b = atoi(buffer2);
return 10 * (b) + (a + 1);
}
// Change our tooltip for a different one
int turnTip()
{
// Declared Variables
char buffer1[1] = "";
char buffer2[1] = "";
uint_fast8_t walk = 0;
echo();
// Ask our necessary details.
mvprintw(5, 0, "What character would you like to print? ");
getnstr(buffer1, 1);
mvprintw(6, 0, "Are these tiles walkable? (1 = yes, 0 = no) ");
getnstr(buffer2, 1);
walk = atoi(buffer2);
// Set our variables to our aquired values
BtipColor = colorPick();
BtipWalk = walk;
Btip = buffer1[0];
// end gracefully
return 0;
}
// Show a help screen for the user
int help()
{
char buffer[1] = "";
clear();
mvprintw(0, 0,
"Tile types:\nb - Basic tile\ni - Information sign\no - Collectable Object\nd - "
"Door\np - Person\n\nKeyboard functions:\nF5 - Save\nF6 - Load\nF8 - Continuous "
"Painting\nBackspace - Erase\n\nSee documentation for details and extra "
"goodies!\nPress enter to escape this screen.");
getnstr(buffer, 1);
return 0;
}
// Map editor for our game
int main()
{
// Our current map
uint_fast8_t aMap = 0;
// Our screen size
uint_fast16_t xmax = 0;
uint_fast16_t ymax = 0;
// Our cursor location
uint_fast16_t x = 0;
uint_fast16_t y = 0;
// Our keypress
uint_fast16_t k = 0;
// Animated tiles
char tile_W[8] = {'~', '.', ' ', ' ', ' ', '.', '~', '^'};
// Potential tile values
uint_fast8_t c = 0;
uint_fast8_t t = 0;
char dialog[256] = "";
uint_fast8_t ID = 0;
uint_fast8_t lock = 0;
uint_fast8_t nx = 0;
uint_fast8_t ny = 0;
uint_fast8_t type = 0;
uint_fast8_t move = 0;
char name[256] = "";
char text1[256] = "";
char text2[256] = "";
struct mapmonster mon[5];
// Text buffers
char buffer1[256] = "";
char buffer2[256] = "";
char buffer3[256] = "";
char buffer4[256] = "";
char buffer5[256] = "";
char buffer6[256] = "";
char buffer7[256] = "";
char buffer8[256] = "";
char buffer9[256] = "";
char bufferA[256] = "";
char bufferB[256] = "";
char bufferC[256] = "";
char bufferD[256] = "";
// Start our game engine and start a blank map
initEngine();
newMaps();
// Run through our animation cycle while we draw our tiles. Get and control our input.
for (uint_fast8_t A = 0;; A++)
{
// Init
getmaxyx(stdscr, ymax, xmax);
noecho();
halfdelay(2);
clear();
// For all existing base tiles, draw them.
for (int C = 0; C < map[aMap].nBase; C++)
{
// If this tile is active, unwalkable, invisible and white-on-blue
if ((map[aMap].Base[C].active) && (map[aMap].Base[C].walk == 0) &&
(map[aMap].Base[C].t == ' ') && (map[aMap].Base[C].c == 48))
{
// Draw an animated water tile
attron(COLOR_PAIR(map[aMap].Base[C].c));
mvprintw(map[aMap].Base[C].y - y, map[aMap].Base[C].x - x, "%c",
tile_W[A % 8]);
attroff(COLOR_PAIR(map[aMap].Base[C].c));
}
// If this tile isn't all-of-the-above
else if (map[aMap].Base[C].active)
{
// Draw it normally
attron(COLOR_PAIR(map[aMap].Base[C].c));
mvprintw(map[aMap].Base[C].y - y, map[aMap].Base[C].x - x, "%c",
map[aMap].Base[C].t);
attroff(COLOR_PAIR(map[aMap].Base[C].c));
}
// If we're hovering over this base tile and it's active
if ((map[aMap].Base[C].x - (xmax / 2) == x) && (map[aMap].Base[C].active) &&
(map[aMap].Base[C].y - (ymax / 2) == y))
{
// Print out useful info in the bottom-left screen
mvprintw(ymax - 2, 0, "Walkable: %s\nColor: %i",
map[aMap].Base[C].walk ? "True" : "False",
map[aMap].Base[C].c);
}
}
// For all existing info tiles, draw them.
for (int C = 0; C < map[aMap].nInfo; C++)
{
// If the given info tile is active
if (map[aMap].Info[C].active)
{
// Draw it with the appropriate character and colour
attron(COLOR_PAIR(map[aMap].Info[C].c));
mvprintw(map[aMap].Info[C].y - y, map[aMap].Info[C].x - x, "%c",
map[aMap].Info[C].t);
attroff(COLOR_PAIR(map[aMap].Info[C].c));
}
// If we're hovering over the given info tile and it's active
if ((map[aMap].Info[C].x - (xmax / 2) == x) && (map[aMap].Info[C].active) &&
(map[aMap].Info[C].y - (ymax / 2) == y))
{
// Print out its dialog in the bottom left of the screen
mvprintw(ymax - 1, 0, "%s", map[aMap].Info[C].dialog);
}
}
// For all existing item tiles, draw them.
for (int C = 0; C < map[aMap].nItem; C++)
{
// If the given item tile is active
if (map[aMap].Item[C].active)
{
// Draw it with the appropriate character and colour
attron(COLOR_PAIR(map[aMap].Item[C].c));
mvprintw(map[aMap].Item[C].y - y, map[aMap].Item[C].x - x, "%c",
map[aMap].Item[C].t);
attroff(COLOR_PAIR(map[aMap].Item[C].c));
}
// If we're hovering over the given item tile and it's active
if ((map[aMap].Item[C].x - (xmax / 2) == x) && (map[aMap].Item[C].active) &&
(map[aMap].Item[C].y - (ymax / 2) == y))
{
// Print out its the item ID in the bottom left of the screen
mvprintw(ymax - 1, 0, "ID#: %i", map[aMap].Item[C].ID);
}
}
// For all existing door tiles, draw them.
for (int C = 0; C < map[aMap].nDoor; C++)
{
// If the given door tile is active
if (map[aMap].Door[C].active)
{
// Draw it with the appropriate character and colour
attron(COLOR_PAIR(map[aMap].Door[C].c));
mvprintw(map[aMap].Door[C].y - y, map[aMap].Door[C].x - x, "%c",
map[aMap].Door[C].t);
attroff(COLOR_PAIR(map[aMap].Door[C].c));
}
// If we're hovering over the given item tile and it's active
if ((map[aMap].Door[C].x - (xmax / 2) == x) && (map[aMap].Door[C].active) &&
(map[aMap].Door[C].y - (ymax / 2) == y))
{
// Print out useful info in the bottom-left screen
mvprintw(ymax - 2, 0, "Status: %s\nMap: %i X: %li Y: %li",
map[aMap].Door[C].lock ? "Locked" : "Unlocked",
map[aMap].Door[C].ID, map[aMap].Door[C].nx,
map[aMap].Door[C].ny);
}
}
// For all existing character tiles, draw them.
for (int C = 0; C < map[aMap].nChar; C++)
{
// If the given char tile is active
if (map[aMap].Char[C].active)
{
// Draw it with the appropriate text character and colour
attron(COLOR_PAIR(map[aMap].Char[C].c));
mvprintw(map[aMap].Char[C].y - y, map[aMap].Char[C].x - x, "%c",
map[aMap].Char[C].t);
attroff(COLOR_PAIR(map[aMap].Char[C].c));
}
// If we're hovering over the given char tile and it's active
if ((map[aMap].Char[C].x - (xmax / 2) == x) && (map[aMap].Char[C].active) &&
(map[aMap].Char[C].y - (ymax / 2) == y))
{
// Print out useful info in the bottom-left screen
mvprintw(ymax - 1, 0, "Name: %s - Type: %s - Moves: %s",
map[aMap].Char[C].name,
map[aMap].Char[C].type ? "Aggressive" : "Passive",
map[aMap].Char[C].move ? "Yes" : "No");
mvprintw(ymax - 2, 0, "Dialogue 1: %s", map[aMap].Char[C].dialog1);
mvprintw(ymax - 3, 0, "Dialogue 2: %s", map[aMap].Char[C].dialog2);
mvprintw(
ymax - 4, 0, "Monsters: %i-%i %i-%i %i-%i %i-%i %i-%i",
map[aMap].Char[C].mon[0].type, map[aMap].Char[C].mon[0].level,
map[aMap].Char[C].mon[1].type, map[aMap].Char[C].mon[1].level,
map[aMap].Char[C].mon[2].type, map[aMap].Char[C].mon[2].level,
map[aMap].Char[C].mon[3].type, map[aMap].Char[C].mon[3].level,
map[aMap].Char[C].mon[4].type, map[aMap].Char[C].mon[4].level);
}
}
// Display coordinates and tool/tips in the top left.
attron(COLOR_PAIR(0));
mvprintw(0, 0, "Map: %i X: %li Y: %li", aMap, x, y);
mvprintw(1, 0, "Tooltip: %c Color: %i Walkable: %s", (char)Btip, BtipColor,
BtipWalk ? "True" : "False");
mvprintw(2, 0, "Press 'h' for help.");
// Display our cursor based on what tool we're using.
switch (continuousPainting)
{
// If continuous painting is off
case 0:
mvprintw(ymax / 2, xmax / 2, "!");
break;
// If continuous painting is on
case 1:
mvprintw(ymax / 2, xmax / 2, "#");
break;
}
// Get and process our user input.
k = getch();
if (k == KEY_UP)
y--;
if (k == KEY_DOWN)
y++;
if (k == KEY_LEFT)
x--;
if (k == KEY_RIGHT)
x++;
if (k == KEY_F(5))
{
echo();
// Get our save name
mvprintw(4, 0, "Save name: ");
getnstr(buffer1, 256);
saveMaps(buffer1);
}
if (k == KEY_F(6))
{
echo();
// Get our load name
mvprintw(4, 0, "Load name: ");
getnstr(buffer1, 256);
loadMaps(buffer1);
}
// if(k == KEY_F(7))
// copyMap();
if (k == KEY_F(8))
// Toggle continuous painting
continuousPainting = !continuousPainting;
if (k == 'b')
// Change our tooltip
turnTip();
if (k == ' ')
addBase(x, y, aMap, xmax, ymax, Btip, BtipColor, BtipWalk);
if (continuousPainting == 1)
{
// If continuous painting is on
addBase(x, y, aMap, xmax, ymax, Btip, BtipColor, BtipWalk);
}
if (k == 'i')
{
echo();
// Prompt for our info
mvprintw(5, 0, "Which character would you like to print? ");
getnstr(buffer1, 1);
t = buffer1[0];
mvprintw(6, 0, "What would you like the sign to say? ");
getnstr(dialog, 256);
c = colorPick();
addInfo(x, y, aMap, xmax, ymax, t, c, dialog);
}
if (k == 'o')
{
echo();
// Prompt for our info
mvprintw(5, 0, "Which character would you like to print? ");
getnstr(buffer1, 1);
t = buffer1[0];
mvprintw(6, 0, "Which item is this? ");
getnstr(buffer2, 8);
ID = atoi(buffer2);
c = colorPick();
addItem(x, y, aMap, xmax, ymax, t, c, ID);
}
if (k == 'd')
{
echo();
// Prompt for our info
mvprintw(5, 0, "Which character would you like to print? ");
getnstr(buffer1, 1);
t = buffer1[0];
mvprintw(6, 0, "Is the door locked? (1 = YES/0 = NO) ");
getnstr(buffer2, 1);
lock = atoi(buffer2);
mvprintw(7, 0, "Which map does this door go to? (#) ");
getnstr(buffer3, 8);
ID = atoi(buffer3);
mvprintw(8, 0, "Which X value does this door go to? (#) ");
getnstr(buffer4, 8);
nx = atoi(buffer4);
mvprintw(9, 0, "Which Y value does this door go to? (#) ");
getnstr(buffer5, 8);
ny = atoi(buffer5);
c = colorPick();
addDoor(x, y, aMap, xmax, ymax, t, c, lock, ID, nx, ny);
}
if (k == 'p')
{
echo();
// Prompt for our info
mvprintw(5, 0, "Which character would you like to print? ");
getnstr(buffer1, 1);
t = buffer1[0];
mvprintw(6, 0, "Is this character aggressive? (1 = YES/0 = NO) ");
getnstr(buffer2, 1);
type = atoi(buffer2);
mvprintw(7, 0, "Does this character wander? (1 = YES/0 = NO) ");
getnstr(buffer3, 1);
move = atoi(buffer3);
mvprintw(8, 0, "What is their name? ");
getnstr(name, 256);
mvprintw(9, 0, "What do they say when they want to fight? ");
getnstr(text1, 256);
mvprintw(10, 0, "What do they say when they don't want to fight? ");
getnstr(text2, 256);
mvprintw(11, 0, "What type is their 1st monster? ");
getnstr(buffer4, 8);
mon[0].type = atoi(buffer4);
mvprintw(12, 0, "What type is their 2nd monster? ");
getnstr(buffer5, 8);
mon[1].type = atoi(buffer5);
mvprintw(13, 0, "What type is their 3rd monster? ");
getnstr(buffer6, 8);
mon[2].type = atoi(buffer6);
mvprintw(14, 0, "What type is their 4th monster? ");
getnstr(buffer7, 8);
mon[3].type = atoi(buffer7);
mvprintw(15, 0, "What type is their 5th monster? ");
getnstr(buffer8, 8);
mon[4].type = atoi(buffer8);
mvprintw(16, 0, "What level is their 1st monster? ");
getnstr(buffer9, 8);
mon[0].level = atoi(buffer9);
mvprintw(17, 0, "What level is their 2nd monster? ");
getnstr(bufferA, 8);
mon[1].level = atoi(bufferA);
mvprintw(18, 0, "What level is their 3rd monster? ");
getnstr(bufferB, 8);
mon[2].level = atoi(bufferB);
mvprintw(19, 0, "What level is their 4th monster? ");
getnstr(bufferC, 8);
mon[3].level = atoi(bufferC);
mvprintw(20, 0, "What level is their 5th monster? ");
getnstr(bufferD, 8);
mon[4].level = atoi(bufferD);
c = colorPick();
addChar(x, y, aMap, xmax, ymax, t, c, type, move, name, text1, text2, mon);
}
if (k == 'h')
help();
if (k == KEY_BACKSPACE)
delTile(x, y, aMap, xmax, ymax);
if ((k == KEY_PPAGE) && (aMap < (nMap - 1)))
aMap++;
if ((k == KEY_NPAGE) && (aMap > 0))
aMap--;
}
// Shutdown properly if needed
endwin();
return 0;
}