Lephisto/src/land.c

582 lines
15 KiB
C

#include "lephisto.h"
#include "log.h"
#include "toolkit.h"
#include "player.h"
#include "rng.h"
#include "music.h"
#include "economy.h"
#include "land.h"
// Global/main window.
#define LAND_WIDTH 700
#define LAND_HEIGHT 600
#define BUTTON_WIDTH 200
#define BUTTON_HEIGHT 40
// Commodity window.
#define COMMODITY_WIDTH 400
#define COMMODITY_HEIGHT 400
// Outfits.
#define OUTFITS_WIDTH 700
#define OUTFITS_HEIGHT 600
// Shipyard.
#define SHIPYARD_WIDTH 700
#define SHIPYARD_HEIGHT 600
// News window.
#define NEWS_WIDTH 400
#define NEWS_HEIGHT 500
// Bar window.
#define BAR_WIDTH 460
#define BAR_HEIGHT 300
#define MUSIC_TAKEOFF "liftoff"
#define MUSIC_LAND "agriculture"
int landed = 0;
static int land_wid = 0; // Primary land window.
// For the second opened land window (We can only have 2 max).
static int secondary_wid = 0;
static Planet* planet = NULL;
// Commodity excahnge.
static void commodity_exchange(void);
static void commodity_exchange_close(char* str);
static void commodity_update(char* str);
static void commodity_buy(char* str);
static void commodity_sell(char* str);
// Outfits.
static void outfits(void);
static void outfits_close(char* str);
static void outfits_update(char* str);
static void outfits_buy(char* str);
static void outfits_sell(char* str);
static int outfits_getMod(void);
static void outfits_renderMod(double bx, double by, double w, double h);
// Shipyard.
static void shipyard(void);
static void shipyard_close(char* str);
static void shipyard_update(char* str);
static void shipyard_info(char* str);
static void shipyard_buy(char* str);
// Spaceport bar.
static void spaceport_bar(void);
static void spaceport_bar_close(char* str);
// News.
static void news(void);
static void news_close(char* str);
// The local market.
static void commodity_exchange(void) {
int i;
char** goods;
secondary_wid = window_create("Commodity Exchange", -1, -1,
COMMODITY_WIDTH, COMMODITY_HEIGHT);
window_addButton(secondary_wid, -20, 20,
BUTTON_WIDTH, BUTTON_HEIGHT, "btnCommodityClose",
"Close", commodity_exchange_close);
window_addButton(secondary_wid, -40-((BUTTON_WIDTH-20)/2), 20*2+BUTTON_HEIGHT,
(BUTTON_WIDTH-20)/2, BUTTON_HEIGHT, "btnCommodityBuy",
"Buy", commodity_buy);
window_addButton(secondary_wid, -20, 20*2+BUTTON_HEIGHT,
(BUTTON_WIDTH-20)/2, BUTTON_HEIGHT, "btnCommoditySell",
"Sell", commodity_sell);
window_addText(secondary_wid, -20, -40, BUTTON_WIDTH, 20, 0,
"txtSInfo", &gl_smallFont, &cDConsole,
"You have:\n"
"Market price:\n");
window_addText(secondary_wid, -20, -40, BUTTON_WIDTH/2, 20, 0,
"txtDInfo", &gl_smallFont, &cBlack, NULL);
window_addText(secondary_wid, -40, -80, BUTTON_WIDTH-20, 60, 0,
"txtDesc", &gl_smallFont, &cBlack, NULL);
goods = malloc(sizeof(char*)*planet->ncommodities);
for(i = 0; i < planet->ncommodities; i++)
goods[i] = strdup(planet->commodities[i]->name);
window_addList(secondary_wid, 20, -40,
COMMODITY_WIDTH-BUTTON_WIDTH-60, COMMODITY_HEIGHT-80-BUTTON_HEIGHT,
"lstGoods", goods, planet->ncommodities, 0, commodity_update);
commodity_update(NULL);
}
static void commodity_exchange_close(char* str) {
if(strcmp(str, "btnCommodityClose")==0)
window_destroy(secondary_wid);
}
static void commodity_update(char* str) {
(void)str;
char buf[128];
char* comname;
Commodity* com;
comname = toolkit_getList(secondary_wid, "lstGoods");
com = commodity_get(comname);
snprintf(buf, 128,
"%d\n"
"%d Screds/ton\n",
player_cargoOwned(comname),
com->medium);
window_modifyText(secondary_wid, "txtDInfo", buf);
window_modifyText(secondary_wid, "txtDesc", com->description);
}
static void commodity_buy(char* str) {
(void)str;
char* comname;
Commodity* com;
int q;
q = 10;
comname = toolkit_getList(secondary_wid, "lstGoods");
com = commodity_get(comname);
if(player_credits <= q * com->medium) {
toolkit_alert("Not enough Scred!");
return;
}
else if(player->cargo_free <= 0) {
toolkit_alert("not enough free space!");
return;
}
q = pilot_addCargo(player, com, q);
player_credits -= q * com->medium;
commodity_update(NULL);
}
static void commodity_sell(char* str) {
(void)str;
char* comname;
Commodity* com;
int q;
q = 10;
comname = toolkit_getList(secondary_wid, "lstGoods");
com = commodity_get(comname);
q = pilot_rmCargo(player, com, q);
player_credits += q * com->medium;
commodity_update(NULL);
}
static void outfits(void) {
char** outfits;
int noutfits;
char buf[128];
snprintf(buf, 128, "%s - Outfits", planet->name);
secondary_wid = window_create(buf, -1, -1,
OUTFITS_WIDTH, OUTFITS_HEIGHT);
window_addButton(secondary_wid, -20, 20,
BUTTON_WIDTH, BUTTON_HEIGHT, "btnCloseOutfits",
"Close", outfits_close);
window_addButton(secondary_wid, -40-BUTTON_WIDTH, 20,
BUTTON_WIDTH, BUTTON_HEIGHT, "btnBuyOutfits",
"Buy", outfits_buy);
window_addButton(secondary_wid, -40-BUTTON_WIDTH, 40+BUTTON_HEIGHT,
BUTTON_WIDTH, BUTTON_HEIGHT, "btnSellOutfit",
"Sell", outfits_sell);
window_addCust(secondary_wid, -40-BUTTON_WIDTH, 60+2*BUTTON_HEIGHT,
BUTTON_WIDTH, BUTTON_HEIGHT, "cstMod", 0, outfits_renderMod, NULL);
window_addText(secondary_wid, 40+200+20, -60,
80, 96, 0, "txtSDesc", &gl_smallFont, &cDConsole,
"Name:\n"
"Type:\n"
"Owned:\n"
"\n"
"Space taken:\n"
"Free Space:\n"
"\n"
"Price:\n"
"Money:\n");
window_addText(secondary_wid, 40+200+40+60, -60,
250, 96, 0, "txtDDesc", &gl_smallFont, &cBlack, NULL);
window_addText(secondary_wid, 20+200+40, -200,
OUTFITS_WIDTH-360, 200, 0, "txtDescription",
&gl_smallFont, NULL, NULL);
// Set up the outfits to buy/sell.
outfits = outfit_getTech(&noutfits, planet->tech, PLANET_TECH_MAX);
window_addList(secondary_wid, 20, 40,
200, OUTFITS_HEIGHT-80, "lstOutfits",
outfits, noutfits, 0, outfits_update);
// Write the outfits stuff.
outfits_update(NULL);
}
static void outfits_close(char* str) {
if(strcmp(str, "btnCloseOutfits")==0)
window_destroy(secondary_wid);
}
static void outfits_update(char* str) {
(void)str;
char* outfitname;
Outfit* outfit;
char buf[80], buf2[16], buf3[16];
outfitname = toolkit_getList(secondary_wid, "lstOutfits");
outfit = outfit_get(outfitname);
window_modifyText(secondary_wid, "txtDescription", outfit->description);
credits2str(buf2, outfit->price, 2);
credits2str(buf3, player_credits, 2);
snprintf(buf, 80,
"%s\n"
"%s\n"
"%d\n"
"\n"
"%d\n"
"%d\n"
"\n"
"%s SCred\n"
"%s SCred\n",
outfit->name,
outfit_getType(outfit),
player_outfitOwned(outfitname),
outfit->mass,
player_freeSpace(),
buf2,
buf3);
window_modifyText(secondary_wid, "txtDDesc", buf);
}
static void outfits_buy(char* str) {
(void)str;
char* outfitname;
Outfit* outfit;
int q;
char buf[16];
outfitname = toolkit_getList(secondary_wid, "lstOutfits");
outfit = outfit_get(outfitname);
q = outfits_getMod();
// Can player actually fit the outfit?
if((player_freeSpace() - outfit->mass) < 0) {
toolkit_alert("No enough free space (you need %d more slots).",
outfit->mass - player_freeSpace());
return;
}
else if(player_outfitOwned(outfitname) >= outfit->max) {
// Already has too many.
toolkit_alert("You can only carry %d of this outfit.", outfit->max);
return;
}
// Not enough.
else if(q*(int)outfit->price >= player_credits) {
credits2str(buf, q*outfit->price - player_credits, 2);
toolkit_alert("You need %s more SCred.", buf);
return;
}
player_credits -= outfit->price * pilot_addOutfit(player, outfit,
MIN(q, outfit->max));
outfits_update(NULL);
}
static void outfits_sell(char* str) {
(void)str;
char* outfitname;
Outfit* outfit;
int q;
outfitname = toolkit_getList(secondary_wid, "lstOutfits");
outfit = outfit_get(outfitname);
q = outfits_getMod();
if(player_outfitOwned(outfitname) <= 0) {
// No outfits to sell.
toolkit_alert("You can't sell something you don't have!");
return;
}
player_credits += outfit->price * pilot_rmOutfit(player, outfit, q);
outfits_update(NULL);
}
// Return the current modifier status.
static int outfits_getMod(void) {
SDLMod mods;
int q;
mods = SDL_GetModState();
q = 1;
if(mods & (KMOD_LCTRL | KMOD_RCTRL)) q *= 5;
if(mods & (KMOD_LSHIFT | KMOD_RSHIFT)) q *= 10;
return q;
}
static void outfits_renderMod(double bx, double by, double w, double h) {
(void) h;
int q;
char buf[8];
q = outfits_getMod();
if(q == 1) return;
snprintf(buf, 8, "%dx", q);
gl_printMid(&gl_smallFont, w,
bx + (double)gl_screen.w/2.,
by + (double)gl_screen.h/2.,
&cBlack, buf);
}
static void shipyard(void) {
char** ships;
int nships;
char buf[128];
snprintf(buf, 128, "%s - Shipyard", planet->name);
secondary_wid = window_create(buf,
-1, -1, SHIPYARD_WIDTH, SHIPYARD_HEIGHT);
window_addButton(secondary_wid, -20, 20,
BUTTON_WIDTH, BUTTON_HEIGHT, "btnCloseShipyard",
"Close", shipyard_close);
window_addButton(secondary_wid, -40-BUTTON_WIDTH, 20,
BUTTON_WIDTH, BUTTON_HEIGHT, "btnBuyShip",
"Buy", shipyard_buy);
window_addButton(secondary_wid, -40-BUTTON_WIDTH, 40+BUTTON_HEIGHT,
BUTTON_WIDTH, BUTTON_HEIGHT, "btnInfoShip",
"Info", shipyard_info);
window_addRect(secondary_wid, -40, -50,
128, 96, "rctTarget", &cBlack, 0);
window_addImage(secondary_wid, -40-128, -50-96,
"imgTarget", NULL);
window_addText(secondary_wid, 40+200+40, -55,
80, 96, 0, "txtSDesc", &gl_smallFont, &cDConsole,
"Name:\n"
"Class:\n"
"Fabricator:\n"
"\n"
"Price:\n"
"Money:\n");
window_addText(secondary_wid, 40+200+40+80, -55,
130, 96, 0, "txtDDesc", &gl_smallFont, &cBlack, NULL);
window_addText(secondary_wid, 20+200+40, -160,
SHIPYARD_WIDTH-360, 200, 0, "txtDescription",
&gl_smallFont, NULL, NULL);
// Setup the ships to buy/sell.
ships = ship_getTech(&nships, planet->tech, PLANET_TECH_MAX);
window_addList(secondary_wid, 20, 40,
200, SHIPYARD_HEIGHT-80, "lstShipyard",
ships, nships, 0, shipyard_update);
// Write the shipyard stuff.
shipyard_update(NULL);
}
static void shipyard_close(char* str) {
if(strcmp(str, "btnCloseShipyard")==0)
window_destroy(secondary_wid);
}
static void shipyard_update(char* str) {
(void)str;
char* shipname;
Ship* ship;
char buf[80], buf2[16], buf3[16];
shipname = toolkit_getList(secondary_wid, "lstShipyard");
ship = ship_get(shipname);
window_modifyText(secondary_wid, "txtDescription", ship->description);
window_modifyImage(secondary_wid, "imgTarget", ship->gfx_target);
credits2str(buf2, ship->price, 2);
credits2str(buf3, player_credits, 2);
snprintf(buf, 80,
"%s\n"
"%s\n"
"%s\n"
"\n"
"%s SCred\n"
"%s SCred\n",
ship->name,
ship_class(ship),
ship->fabricator,
buf2,
buf3);
window_modifyText(secondary_wid, "txtDDesc", buf);
}
static void shipyard_info(char* str) {
(void)str;
char* shipname;
shipname = toolkit_getList(secondary_wid, "lstShipyard");
ship_view(shipname);
}
static void shipyard_buy(char* str) {
(void)str;
char* shipname;
Ship* ship;
shipname = toolkit_getList(secondary_wid, "lstShipyard");
ship = ship_get(shipname);
player_newShip(ship);
}
// Spaceport bar.
static void spaceport_bar(void) {
secondary_wid = window_create("SpacePort Bar", -1, -1, BAR_WIDTH, BAR_HEIGHT);
window_addText(secondary_wid, 20, -30,
BAR_WIDTH-140, BAR_HEIGHT - 40 - BUTTON_HEIGHT, 0,
"txtDescription", &gl_smallFont, &cBlack, planet->bar_description);
window_addButton(secondary_wid, -20, 20, BUTTON_WIDTH, BUTTON_HEIGHT,
"btnCloseBar", "Close", spaceport_bar_close);
window_addButton(secondary_wid, 20, 20,
BUTTON_WIDTH, BUTTON_HEIGHT, "btnNews",
"News", (void(*)(char*))news);
}
static void spaceport_bar_close(char* str) {
if(strcmp(str, "btnCloseBar")==0)
window_destroy(secondary_wid);
}
// Planet news reports.
static void news(void) {
unsigned int news_wid;
news_wid = window_create("News Reports",
-1, -1, NEWS_WIDTH, NEWS_HEIGHT);
window_addText(news_wid, 20, 20 + BUTTON_HEIGHT + 20,
NEWS_WIDTH-40, NEWS_HEIGHT - 20 - BUTTON_HEIGHT - 20 - 20 -20,
0, "txtNews", &gl_smallFont, &cBlack,
"News reporters report that they are on strike right now! D:");
window_addButton(news_wid, -20, 20,
BUTTON_WIDTH, BUTTON_HEIGHT,
"btnCloseNews", "Close", news_close);
}
static void news_close(char* str) {
if(strcmp(str, "btnCloseNews")==0)
window_destroy(window_get("News Reports"));
}
// Land the player.
void land(Planet* p) {
if(landed) return;
// Change music.
music_load(MUSIC_LAND);
music_play();
planet = p;
land_wid = window_create(p->name, -1, -1, LAND_WIDTH, LAND_HEIGHT);
// Pretty display.
window_addImage(land_wid, 20, -40, "imgPlanet", p->gfx_exterior);
window_addText(land_wid, 440, 80, 200, 460, 0,
"txtPlanetDesc", &gl_smallFont, &cBlack, p->description);
// Buttons.
window_addButton(land_wid, -20, 20, BUTTON_WIDTH, BUTTON_HEIGHT,
"btnTakeoff", "Takeoff", (void(*)(char*))takeoff);
if(planet_hasService(planet, PLANET_SERVICE_COMMODITY))
window_addButton(land_wid, -20, 20 + BUTTON_HEIGHT + 20,
BUTTON_WIDTH, BUTTON_HEIGHT, "btnCommodity",
"Commodity Exchange", (void(*)(char*))commodity_exchange);
if(planet_hasService(planet, PLANET_SERVICE_SHIPYARD))
window_addButton(land_wid, -20 - BUTTON_WIDTH - 20, 20,
BUTTON_WIDTH, BUTTON_HEIGHT, "btnShipyard",
"Shipyard", (void(*)(char*))shipyard);
if(planet_hasService(planet, PLANET_SERVICE_OUTFITS))
window_addButton(land_wid, -20 - BUTTON_WIDTH - 20, 20 + BUTTON_HEIGHT + 20,
BUTTON_WIDTH, BUTTON_HEIGHT, "btnOutfits",
"Outfits", (void(*)(char*))outfits);
if(planet_hasService(planet, PLANET_SERVICE_BASIC)) {
window_addButton(land_wid, 20, 20,
BUTTON_WIDTH, BUTTON_HEIGHT, "btnNews",
"Mission Terminal", NULL);
window_addButton(land_wid, 20, 20 + BUTTON_HEIGHT + 20,
BUTTON_WIDTH, BUTTON_HEIGHT, "btnBar",
"Spaceport Bar", (void(*)(char*))spaceport_bar);
}
landed = 1;
}
// Takeoff from the planet.
void takeoff(void) {
if(!landed) return;
music_load(MUSIC_TAKEOFF);
music_play();
int sw, sh;
sw = planet->gfx_space->w;
sh = planet->gfx_space->h;
// No longer authorized to land.
player_rmFlag(PLAYER_LANDACK);
// Set player to another position with random facing direction and no velocity.
player_warp(planet->pos.x + RNG(-sw/2, sw/2), planet->pos.y + RNG(-sh/2, sh/2));
vect_pset(&player->solid->vel, 0., 0.);
player->solid->dir = RNG(0, 359) * M_PI/180.;
// Heal the player.
player->armour = player->armour_max;
player->shield = player->shield_max;
player->energy = player->energy_max;
space_init(NULL);
planet = NULL;
window_destroy(land_wid);
landed = 0;
}