1140 lines
32 KiB
C
1140 lines
32 KiB
C
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
|
|
#include "lephisto.h"
|
|
#include "log.h"
|
|
#include "toolkit.h"
|
|
#include "player.h"
|
|
#include "rng.h"
|
|
#include "music.h"
|
|
#include "economy.h"
|
|
#include "hook.h"
|
|
#include "mission.h"
|
|
#include "ltime.h"
|
|
#include "save.h"
|
|
#include "music.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
|
|
|
|
/* Mission computer window. */
|
|
#define MISSION_WIDTH 700
|
|
#define MISSION_HEIGHT 600
|
|
|
|
/* We use visited flags to not duplicate missions generated. */
|
|
#define VISITED_LAND (1<<0)
|
|
#define VISITED_COMMODITY (1<<1)
|
|
#define VISITED_BAR (1<<2)
|
|
#define VISITED_OUTFITS (1<<3)
|
|
#define VISITED_SHIPYARD (1<<4)
|
|
#define visited(f) (land_visited |= (f))
|
|
#define has_visited(f) (land_visited & (f))
|
|
static unsigned int land_visited = 0;
|
|
|
|
/* Land variables. */
|
|
int landed = 0;
|
|
Planet* land_planet = NULL;
|
|
|
|
/* Mission computer stack. */
|
|
static Mission* mission_computer = NULL;
|
|
static int mission_ncomputer = 0;
|
|
|
|
/* Player stuff. */
|
|
extern int hyperspace_target;
|
|
|
|
/* Window stuff. */
|
|
static int land_wid = 0; /* Primary land window. */
|
|
/* For the second opened land window */
|
|
static int secondary_wid = 0;
|
|
static int terciary_wid = 0; /* For fancy things like news, your ship etc.. */
|
|
|
|
/* 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 int outfit_canBuy(Outfit* outfit, int q, int errmsg);
|
|
static void outfits_buy(char* str);
|
|
static int outfit_canSell(Outfit* outfit, int q, int errmsg);
|
|
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);
|
|
/* Your ship. */
|
|
static void shipyard_yours(char* str);
|
|
static void shipyard_yoursClose(char* str);
|
|
static void shipyard_yoursUpdate(char* str);
|
|
static void shipyard_yoursChange(char* str);
|
|
static void shipyard_yoursTransport(char* str);
|
|
static int shipyard_yoursTransportPrice(char* shipname);
|
|
/* 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);
|
|
/* Mission computer. */
|
|
static void misn(void);
|
|
static void misn_close(char* str);
|
|
static void misn_accept(char* str);
|
|
static void misn_genList(int first);
|
|
static void misn_update(char* str);
|
|
/* Refuel. */
|
|
static int refuel_price(void);
|
|
static void spaceport_refuel(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, 60, 0,
|
|
"txtSInfo", &gl_smallFont, &cDConsole,
|
|
"You have:\n"
|
|
"Market price:\n"
|
|
"\n"
|
|
"Free Space:\n");
|
|
|
|
window_addText(secondary_wid, -20, -40, BUTTON_WIDTH/2, 60, 0,
|
|
"txtDInfo", &gl_smallFont, &cBlack, NULL);
|
|
|
|
window_addText(secondary_wid, -40, -100, BUTTON_WIDTH-20,
|
|
BUTTON_WIDTH, 0, "txtDesc", &gl_smallFont, &cBlack, NULL);
|
|
|
|
goods = malloc(sizeof(char*)*land_planet->ncommodities);
|
|
for(i = 0; i < land_planet->ncommodities; i++)
|
|
goods[i] = strdup(land_planet->commodities[i]->name);
|
|
|
|
window_addList(secondary_wid, 20, -40,
|
|
COMMODITY_WIDTH-BUTTON_WIDTH-60,
|
|
COMMODITY_HEIGHT-80-BUTTON_HEIGHT, "lstGoods",
|
|
goods, land_planet->ncommodities, 0, commodity_update);
|
|
|
|
commodity_update(NULL);
|
|
|
|
if(!has_visited(VISITED_COMMODITY)) {
|
|
/* TODO: mission check. */
|
|
visited(VISITED_COMMODITY);
|
|
}
|
|
}
|
|
|
|
static void commodity_exchange_close(char* str) {
|
|
if(strcmp(str, "btnCommodityClose")==0)
|
|
window_destroy(secondary_wid);
|
|
secondary_wid = 0;
|
|
}
|
|
|
|
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 tons\n"
|
|
"%d Scred\n"
|
|
"\n"
|
|
"%d tons\n",
|
|
player_cargoOwned(comname),
|
|
com->medium,
|
|
pilot_cargoFree(player));
|
|
|
|
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) {
|
|
dialogue_alert("Not enough Scred!");
|
|
return;
|
|
}
|
|
else if(pilot_cargoFree(player) <= 0) {
|
|
dialogue_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];
|
|
|
|
/* Create window. */
|
|
snprintf(buf, 128, "%s - Outfits", land_planet->name);
|
|
secondary_wid = window_create(buf, -1, -1,
|
|
OUTFITS_WIDTH, OUTFITS_HEIGHT);
|
|
/* Will allow buying from keyboard. */
|
|
window_setFptr(secondary_wid, outfits_buy);
|
|
|
|
/* Buttons. */
|
|
window_addButton(secondary_wid, -20, 20,
|
|
BUTTON_WIDTH, BUTTON_HEIGHT, "btnCloseOutfits",
|
|
"Close", outfits_close);
|
|
|
|
window_addButton(secondary_wid, -40-BUTTON_WIDTH, 40+BUTTON_HEIGHT,
|
|
BUTTON_WIDTH, BUTTON_HEIGHT, "btnBuyOutfit",
|
|
"Buy", outfits_buy);
|
|
|
|
window_addButton(secondary_wid, -40-BUTTON_WIDTH, 20,
|
|
BUTTON_WIDTH, BUTTON_HEIGHT, "btnSellOutfit",
|
|
"Sell", outfits_sell);
|
|
|
|
/* Fancy 128x128 image. */
|
|
window_addRect(secondary_wid, -20, -50, 128, 128, "rctImage", &cBlack, 0);
|
|
window_addImage(secondary_wid, -20-128, -50-128, "imgOutfit", NULL, 1);
|
|
|
|
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-300, 200, 0, "txtDescription",
|
|
&gl_smallFont, NULL, NULL);
|
|
|
|
/* Set up the outfits to buy/sell. */
|
|
outfits = outfit_getTech(&noutfits, land_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);
|
|
|
|
if(!has_visited(VISITED_OUTFITS)) {
|
|
/* TODO: mission check. */
|
|
visited(VISITED_OUTFITS);
|
|
}
|
|
}
|
|
|
|
static void outfits_close(char* str) {
|
|
if(strcmp(str, "btnCloseOutfits")==0)
|
|
window_destroy(secondary_wid);
|
|
secondary_wid = 0;
|
|
}
|
|
|
|
static void outfits_update(char* str) {
|
|
(void)str;
|
|
char* outfitname;
|
|
Outfit* outfit;
|
|
char buf[128], buf2[16], buf3[16];
|
|
|
|
outfitname = toolkit_getList(secondary_wid, "lstOutfits");
|
|
outfit = outfit_get(outfitname);
|
|
|
|
window_modifyImage(secondary_wid, "imgOutfit", outfit->gfx_store);
|
|
|
|
if(outfit_canBuy(outfit, 1, 0) > 0)
|
|
window_enableButton(secondary_wid, "btnBuyOutfit");
|
|
else
|
|
window_disableButton(secondary_wid, "btnBuyOutfit");
|
|
|
|
/* Gray out sell button. */
|
|
if(outfit_canSell(outfit, 1, 0) > 0)
|
|
window_enableButton(secondary_wid, "btnSellOutfit");
|
|
else
|
|
window_disableButton(secondary_wid, "btnSellOutfit");
|
|
|
|
/* New text. */
|
|
window_modifyText(secondary_wid, "txtDescription", outfit->description);
|
|
credits2str(buf2, outfit->price, 2);
|
|
credits2str(buf3, player->credits, 2);
|
|
snprintf(buf, 128,
|
|
"%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,
|
|
pilot_freeSpace(player),
|
|
buf2,
|
|
buf3);
|
|
|
|
window_modifyText(secondary_wid, "txtDDesc", buf);
|
|
}
|
|
|
|
static int outfit_canBuy(Outfit* outfit, int q, int errmsg) {
|
|
char buf[16];
|
|
|
|
/* Can player actually fit the outfit? */
|
|
if((pilot_freeSpace(player) - outfit->mass) < 0) {
|
|
if(errmsg != 0)
|
|
dialogue_alert("No enough free space (you need %d more slots).",
|
|
outfit->mass - pilot_freeSpace(player));
|
|
return 0;
|
|
}
|
|
else if(player_outfitOwned(outfit->name) >= outfit->max) {
|
|
/* Already has too many. */
|
|
if(errmsg != 0)
|
|
dialogue_alert("You can only carry %d of this outfit.", outfit->max);
|
|
return 0;
|
|
}
|
|
else if(outfit_isAfterburner(outfit) && (player->afterburner != NULL)) {
|
|
if(errmsg != 0)
|
|
dialogue_alert("You can only have one afterburner.");
|
|
return 0;
|
|
}
|
|
/* Takes away cargo space but you don't have any. */
|
|
else if(outfit_isMod(outfit) && (outfit->u.mod.cargo < 0)
|
|
&& (pilot_cargoFree(player) < -outfit->u.mod.cargo)) {
|
|
if(errmsg != 0)
|
|
dialogue_alert("You need to empty your cargo first.");
|
|
return 0;
|
|
}
|
|
/* Not enough $$. */
|
|
else if(q*(int)outfit->price >= player->credits) {
|
|
if(errmsg != 0) {
|
|
credits2str(buf, q*outfit->price - player->credits, 2);
|
|
dialogue_alert("You need %s more SCred.", buf);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static void outfits_buy(char* str) {
|
|
(void)str;
|
|
char* outfitname;
|
|
Outfit* outfit;
|
|
int q;
|
|
|
|
outfitname = toolkit_getList(secondary_wid, "lstOutfits");
|
|
outfit = outfit_get(outfitname);
|
|
|
|
q = outfits_getMod();
|
|
|
|
/* Can buy the outfit? */
|
|
if(outfit_canBuy(outfit, q, 1) == 0) return;
|
|
|
|
player->credits -= outfit->price * pilot_addOutfit(player, outfit,
|
|
MIN(q, outfit->max));
|
|
outfits_update(NULL);
|
|
}
|
|
|
|
static int outfit_canSell(Outfit* outfit, int q, int errmsg) {
|
|
/* No outfits to sell. */
|
|
if(player_outfitOwned(outfit->name) <= 0) {
|
|
if(errmsg != 0)
|
|
dialogue_alert("You can't sell something you don't have!");
|
|
return 0;
|
|
}
|
|
/* Can't sell when you are using it. */
|
|
else if(outfit_isMod(outfit) && (pilot_cargoFree(player) < outfit->u.mod.cargo * q)) {
|
|
if(errmsg != 0)
|
|
dialogue_alert("You currently have cargo in this modification.");
|
|
return 0;
|
|
}
|
|
else if((outfit->mass < 0) && (pilot_freeSpace(player) < -outfit->mass)) {
|
|
if(errmsg != 0)
|
|
dialogue_alert("Get rid of other outfits first.");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
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();
|
|
|
|
/* Has no outfits to sell. */
|
|
if(outfit_canSell(outfit, q, 1) == 0) 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)SCREEN_W/2.,
|
|
by + (double)SCREEN_H/2.,
|
|
&cBlack, buf);
|
|
}
|
|
|
|
static void shipyard(void) {
|
|
char** ships;
|
|
int nships;
|
|
char buf[128];
|
|
|
|
snprintf(buf, 128, "%s - Shipyard", land_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, -20, 40+BUTTON_HEIGHT,
|
|
BUTTON_WIDTH, BUTTON_HEIGHT, "btnYourShips",
|
|
"Your Ships", shipyard_yours);
|
|
|
|
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, 1);
|
|
|
|
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-300, 200, 0, "txtDescription",
|
|
&gl_smallFont, NULL, NULL);
|
|
|
|
/* Setup the ships to buy/sell. */
|
|
ships = ship_getTech(&nships, land_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);
|
|
|
|
if(!has_visited(VISITED_SHIPYARD)) {
|
|
/* TODO: mission check. */
|
|
visited(VISITED_SHIPYARD);
|
|
}
|
|
}
|
|
|
|
static void shipyard_close(char* str) {
|
|
if(strcmp(str, "btnCloseShipyard")==0)
|
|
window_destroy(secondary_wid);
|
|
secondary_wid = 0;
|
|
}
|
|
|
|
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);
|
|
|
|
if(player_nships()==0) window_disableButton(secondary_wid, "btnYourShips");
|
|
else window_enableButton(secondary_wid, "btnYourShips");
|
|
|
|
window_modifyImage(secondary_wid, "imgTarget", ship->gfx_target);
|
|
window_modifyText(secondary_wid, "txtDescription", ship->description);
|
|
|
|
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);
|
|
|
|
if(ship->price > player->credits)
|
|
window_disableButton(secondary_wid, "btnBuyShip");
|
|
else window_enableButton(secondary_wid, "btnBuyShip");
|
|
|
|
}
|
|
|
|
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, buf[16];
|
|
Ship* ship;
|
|
|
|
shipname = toolkit_getList(secondary_wid, "lstShipyard");
|
|
ship = ship_get(shipname);
|
|
|
|
if(pilot_cargoUsed(player) > ship->cap_cargo) {
|
|
dialogue_alert("You won't have space to move your current cargo onto the new ship.");
|
|
return;
|
|
}
|
|
|
|
credits2str(buf, ship->price, 2);
|
|
if(dialogue_YesNo("Are you sure?",
|
|
"Do you really want to spend %s on a new ship?", buf)==0)
|
|
return;
|
|
|
|
player_newShip(ship, player->solid->pos.x, player->solid->pos.y,
|
|
0., 0., player->solid->dir);
|
|
|
|
player->credits -= ship->price; /* Auch! Paying is hard! */
|
|
|
|
shipyard_update(NULL);
|
|
}
|
|
|
|
static void shipyard_yours(char* str) {
|
|
(void)str;
|
|
char** ships;
|
|
int nships;
|
|
|
|
terciary_wid = window_create("Your Ships",
|
|
-1, -1, SHIPYARD_WIDTH, SHIPYARD_HEIGHT);
|
|
|
|
window_addButton(terciary_wid, -20, 20,
|
|
BUTTON_WIDTH, BUTTON_HEIGHT, "btnCloseYourShips",
|
|
"Shipyard", shipyard_yoursClose);
|
|
|
|
window_addButton(terciary_wid, -40-BUTTON_WIDTH, 20,
|
|
BUTTON_WIDTH, BUTTON_HEIGHT, "btnChangeShip",
|
|
"Change Ship", shipyard_yoursChange);
|
|
|
|
window_addButton(terciary_wid, -40-BUTTON_WIDTH, 40+BUTTON_HEIGHT,
|
|
BUTTON_WIDTH, BUTTON_HEIGHT, "btnTransportShip",
|
|
"Transport Ship", shipyard_yoursTransport);
|
|
|
|
window_addRect(terciary_wid, -40, -50,
|
|
128, 96, "rctTarget", &cBlack, 0);
|
|
|
|
window_addImage(terciary_wid, -40-128, -50-96,
|
|
"imgTarget", NULL, 1);
|
|
|
|
window_addText(terciary_wid, 40+200+40, -55,
|
|
100, 96, 0, "txtSDesc", &gl_smallFont, &cDConsole,
|
|
"Name:\n"
|
|
"Ship:\n"
|
|
"Class:\n"
|
|
"Location:\n"
|
|
"\n"
|
|
"Cargo free:\n"
|
|
"Weapons free\n"
|
|
"\n"
|
|
"Transportation\n"
|
|
"Sell price\n");
|
|
|
|
window_addText(terciary_wid, 40+200+40+100, -55,
|
|
130, 96, 0, "txtDDesc", &gl_smallFont, &cBlack, NULL);
|
|
|
|
window_addText(terciary_wid, 40+200+40, -215,
|
|
100, 20, 0, "txtSOutfits", &gl_smallFont, &cDConsole,
|
|
"Outfits:\n");
|
|
|
|
window_addText(terciary_wid, 40+200+40, -215-gl_smallFont.h-5,
|
|
SHIPYARD_WIDTH-40-200-40-20, 200, 0, "txtDOutfits",
|
|
&gl_smallFont, &cBlack, NULL);
|
|
|
|
ships = player_ships(&nships);
|
|
window_addList(terciary_wid, 20, 40,
|
|
200, SHIPYARD_HEIGHT-80, "lstYourShips",
|
|
ships, nships, 0, shipyard_yoursUpdate);
|
|
|
|
shipyard_yoursUpdate(NULL);
|
|
}
|
|
|
|
static void shipyard_yoursClose(char* str) {
|
|
(void)str;
|
|
window_destroy(terciary_wid);
|
|
terciary_wid = 0;
|
|
}
|
|
|
|
static void shipyard_yoursUpdate(char* str) {
|
|
(void)str;
|
|
char buf[256], buf2[16], buf3[16], *buf4;
|
|
char* shipname;
|
|
Pilot* ship;
|
|
char* loc;
|
|
int price;
|
|
|
|
shipname = toolkit_getList(terciary_wid, "lstYourShips");
|
|
if(strcmp(shipname, "None")==0) {
|
|
/* No ships. */
|
|
window_disableButton(terciary_wid, "btnChangeShip");
|
|
window_disableButton(terciary_wid, "btnTransportShip");
|
|
return;
|
|
}
|
|
ship = player_getShip(shipname);
|
|
loc = player_getLoc(ship->name);
|
|
price = shipyard_yoursTransportPrice(shipname);
|
|
|
|
/* Update the image. */
|
|
window_modifyImage(terciary_wid, "imgTarget", ship->ship->gfx_target);
|
|
|
|
/* Update text. */
|
|
credits2str(buf2, price, 2); /* Transport. */
|
|
|
|
credits2str(buf3, 0, 2); /* Sell price. */
|
|
snprintf(buf, 256,
|
|
"%s\n"
|
|
"%s\n"
|
|
"%s\n"
|
|
"%s\n"
|
|
"\n"
|
|
"%d tons\n"
|
|
"%d tons\n"
|
|
"\n"
|
|
"%s scred\n"
|
|
"%s scred\n",
|
|
ship->name,
|
|
ship->ship->name,
|
|
ship_class(ship->ship),
|
|
loc,
|
|
pilot_cargoFree(ship),
|
|
pilot_freeSpace(ship),
|
|
buf2,
|
|
buf3);
|
|
|
|
window_modifyText(terciary_wid, "txtDDesc", buf);
|
|
|
|
buf4 = pilot_getOutfits(ship);
|
|
window_modifyText(terciary_wid, "txtDOutfits", buf4);
|
|
free(buf4);
|
|
|
|
/* Button disabling. */
|
|
if(strcmp(land_planet->name, loc)) {
|
|
/* Ship not here. */
|
|
window_disableButton(terciary_wid, "btnChangeShip");
|
|
if(price > player->credits)
|
|
window_disableButton(terciary_wid, "btnTransportShip");
|
|
else window_enableButton(terciary_wid, "btnTransportShip");
|
|
} else {
|
|
window_enableButton(terciary_wid, "btnChangeShip");
|
|
window_disableButton(terciary_wid, "btnTransportShip");
|
|
}
|
|
}
|
|
|
|
static void shipyard_yoursChange(char* str) {
|
|
(void)str;
|
|
char* shipname, *loc;
|
|
Pilot* newship;
|
|
|
|
shipname = toolkit_getList(terciary_wid, "lstYourShips");
|
|
newship = player_getShip(shipname);
|
|
if(strcmp(shipname, "None")==0) {
|
|
/* No ships. */
|
|
dialogue_alert("You need another ship to change to!");
|
|
return;
|
|
}
|
|
|
|
loc = player_getLoc(shipname);
|
|
|
|
if(strcmp(loc, land_planet->name)) {
|
|
dialogue_alert("You must transport the ship to %s to be able to get in.",
|
|
land_planet->name);
|
|
return;
|
|
}
|
|
else if(pilot_cargoUsed(player) > pilot_cargoFree(newship)) {
|
|
dialogue_alert("You won't be able to fit your current cago in the new ship.");
|
|
return;
|
|
}
|
|
|
|
player_swapShip(shipname);
|
|
|
|
/* Recreate the window. */
|
|
shipyard_yoursClose(NULL);
|
|
shipyard_yours(NULL);
|
|
}
|
|
|
|
static void shipyard_yoursTransport(char* str) {
|
|
(void)str;
|
|
int price;
|
|
char* shipname, buf[16];
|
|
|
|
shipname = toolkit_getList(terciary_wid, "lstYourShips");
|
|
if(strcmp(shipname, "None")==0) { /* No ships. */
|
|
dialogue_alert("You can't transport nothing here!");
|
|
return;
|
|
}
|
|
|
|
price = shipyard_yoursTransportPrice(shipname);
|
|
if(price == 0) {
|
|
/* Already here. */
|
|
dialogue_alert("Your ship '%s' is already here.", shipname);
|
|
return;
|
|
}
|
|
else if(player->credits < price) {
|
|
/* You are broke. */
|
|
credits2str(buf, price-player->credits, 2);
|
|
dialogue_alert("You need %d more credits to transport '%s' here.",
|
|
buf, shipname);
|
|
return;
|
|
}
|
|
|
|
/* Success. */
|
|
player->credits -= price;
|
|
player_setLoc(shipname, land_planet->name);
|
|
|
|
/* Update the window to reflect the change. */
|
|
shipyard_yoursUpdate(NULL);
|
|
}
|
|
|
|
static int shipyard_yoursTransportPrice(char* shipname) {
|
|
char* loc;
|
|
Pilot* ship;
|
|
int price;
|
|
|
|
ship = player_getShip(shipname);
|
|
loc = player_getLoc(shipname);
|
|
if(strcmp(loc, land_planet->name)==0) /* Already here. */
|
|
return 0;
|
|
|
|
price = (int)ship->solid->mass*500;
|
|
|
|
return price;
|
|
}
|
|
|
|
/* Spaceport bar. */
|
|
static void spaceport_bar(void) {
|
|
secondary_wid = window_create("SpacePort Bar", -1, -1, BAR_WIDTH, BAR_HEIGHT);
|
|
|
|
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);
|
|
|
|
window_addText(secondary_wid, 20, -30,
|
|
BAR_WIDTH-40, BAR_HEIGHT - 40 - BUTTON_HEIGHT, 0,
|
|
"txtDescription", &gl_smallFont, &cBlack,
|
|
land_planet->bar_description);
|
|
|
|
if(!has_visited(VISITED_BAR)) {
|
|
missions_bar(land_planet->faction, land_planet->name, cur_system->name);
|
|
visited(VISITED_BAR);
|
|
}
|
|
}
|
|
|
|
static void spaceport_bar_close(char* str) {
|
|
if(strcmp(str, "btnCloseBar")==0)
|
|
window_destroy(secondary_wid);
|
|
secondary_wid = 0;
|
|
}
|
|
|
|
/* Planet news reports. */
|
|
static void news(void) {
|
|
terciary_wid = window_create("News Reports",
|
|
-1, -1, NEWS_WIDTH, NEWS_HEIGHT);
|
|
|
|
window_addButton(terciary_wid, -20, 20,
|
|
BUTTON_WIDTH, BUTTON_HEIGHT,
|
|
"btnCloseNews", "Close", news_close);
|
|
|
|
window_addText(terciary_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:");
|
|
}
|
|
|
|
static void news_close(char* str) {
|
|
if(strcmp(str, "btnCloseNews")==0)
|
|
window_destroy(terciary_wid);
|
|
terciary_wid = 0;
|
|
}
|
|
|
|
/* Mission computer, cos' missions rule! */
|
|
static void misn(void) {
|
|
secondary_wid = window_create("Mission Computer",
|
|
-1, -1, MISSION_WIDTH, MISSION_HEIGHT);
|
|
|
|
/* Buttons. */
|
|
window_addButton(secondary_wid, -20, 20,
|
|
BUTTON_WIDTH, BUTTON_HEIGHT, "btnCloseMission",
|
|
"Close", misn_close);
|
|
|
|
window_addButton(secondary_wid, -20, 40+BUTTON_HEIGHT,
|
|
BUTTON_WIDTH, BUTTON_HEIGHT, "btnAcceptMission",
|
|
"Accept", misn_accept);
|
|
|
|
/* Text. */
|
|
window_addText(secondary_wid, 300+40, -60,
|
|
300, 40, 0, "txtSReward",
|
|
&gl_smallFont, &cDConsole, "Reward:");
|
|
|
|
window_addText(secondary_wid, 300+100, -60,
|
|
240, 40, 0, "txtReward", &gl_smallFont, &cBlack, NULL);
|
|
|
|
window_addText(secondary_wid, 300+40, -100,
|
|
300, MISSION_HEIGHT - BUTTON_WIDTH - 120, 0,
|
|
"txtDesc", &gl_smallFont, &cBlack, NULL);
|
|
|
|
misn_genList(1);
|
|
}
|
|
|
|
static void misn_close(char* str) {
|
|
if(strcmp(str, "btnCloseMission")==0)
|
|
window_destroy(secondary_wid);
|
|
secondary_wid = 0;
|
|
}
|
|
|
|
static void misn_accept(char* str) {
|
|
char* misn_name;
|
|
Mission* misn;
|
|
int pos;
|
|
(void)str;
|
|
|
|
misn_name = toolkit_getList(secondary_wid, "lstMission");
|
|
|
|
if(strcmp(misn_name, "No Missions")==0) return;
|
|
|
|
if(dialogue_YesNo("Accept Mission",
|
|
"Are you sure you want to accept this mission?")) {
|
|
pos = toolkit_getListPos(secondary_wid, "lstMission");
|
|
misn = &mission_computer[pos];
|
|
if(mission_accept(misn)) {
|
|
/* Success is accepting the mission. */
|
|
memmove(misn, &mission_computer[pos+1],
|
|
sizeof(Mission) * (mission_ncomputer-pos-1));
|
|
mission_ncomputer--;
|
|
misn_genList(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void misn_genList(int first) {
|
|
int i, j;
|
|
char** misn_names;
|
|
|
|
if(!first)
|
|
window_destroyWidget(secondary_wid, "lstMission");
|
|
|
|
/* List. */
|
|
if(mission_ncomputer != 0) {
|
|
/* there are missions. */
|
|
misn_names = malloc(sizeof(char*) * mission_ncomputer);
|
|
j = 0;
|
|
for(i = 0; i < mission_ncomputer; i++)
|
|
if(mission_computer[i].title)
|
|
misn_names[j++] = strdup(mission_computer[i].title);
|
|
}
|
|
if((mission_ncomputer == 0) || (j == 0)) {
|
|
/* No missions. */
|
|
if(j == 0) free(misn_names);
|
|
misn_names = malloc(sizeof(char*));
|
|
misn_names[0] = strdup("No Missions");
|
|
}
|
|
|
|
window_addList(secondary_wid, 20, -40,
|
|
300, MISSION_HEIGHT-60,
|
|
"lstMission", misn_names, j, 0, misn_update);
|
|
|
|
misn_update(NULL);
|
|
}
|
|
|
|
static void misn_update(char* str) {
|
|
char* active_misn;
|
|
Mission* misn;
|
|
|
|
(void)str;
|
|
|
|
active_misn = toolkit_getList(secondary_wid, "lstMission");
|
|
if(strcmp(active_misn, "No Missions")==0) {
|
|
window_modifyText(secondary_wid, "txtReward", "None");
|
|
window_modifyText(secondary_wid, "txtDesc",
|
|
"There are no missions available here.");
|
|
|
|
window_disableButton(secondary_wid, "btnAcceptMission");
|
|
return;
|
|
}
|
|
misn = &mission_computer[toolkit_getListPos(secondary_wid, "lstMission")];
|
|
window_modifyText(secondary_wid, "txtReward", misn->reward);
|
|
window_modifyText(secondary_wid, "txtDesc", misn->desc);
|
|
window_enableButton(secondary_wid, "btnAcceptMission");
|
|
}
|
|
|
|
/* Return how much it will cost to refuel the player. */
|
|
static int refuel_price(void) {
|
|
return (player->fuel_max - player->fuel)*3;
|
|
}
|
|
|
|
/* Refuel the player. */
|
|
static void spaceport_refuel(char* str) {
|
|
(void)str;
|
|
|
|
if(player->credits < refuel_price()) {
|
|
/* Player is out of moniez after landing D: */
|
|
dialogue_alert("You seem to not have enough scred to refuel your ship.");
|
|
return;
|
|
}
|
|
|
|
player->credits -= refuel_price();
|
|
player->fuel = player->fuel_max;
|
|
window_destroyWidget(land_wid, "btnRefuel");
|
|
}
|
|
|
|
/* Land the player. */
|
|
void land(Planet* p) {
|
|
char buf[32], cred[16];
|
|
|
|
if(landed) return;
|
|
|
|
/* Change music. */
|
|
music_choose("land");
|
|
|
|
land_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, 1);
|
|
window_addText(land_wid, 440, 80, LAND_WIDTH-460, 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(land_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(land_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(land_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);
|
|
|
|
/* Third column. */
|
|
if(planet_hasService(land_planet, PLANET_SERVICE_BASIC)) {
|
|
window_addButton(land_wid, 20, 20,
|
|
BUTTON_WIDTH, BUTTON_HEIGHT, "btnNews",
|
|
"Mission Terminal", (void(*)(char*))misn);
|
|
|
|
window_addButton(land_wid, 20, 20 + BUTTON_HEIGHT + 20,
|
|
BUTTON_WIDTH, BUTTON_HEIGHT, "btnBar",
|
|
"Spaceport Bar", (void(*)(char*))spaceport_bar);
|
|
|
|
if(player->fuel < player->fuel_max) {
|
|
credits2str(cred, refuel_price(), 2);
|
|
snprintf(buf, 32, "Refuel %s", cred);
|
|
window_addButton(land_wid, -20, 20+2*(BUTTON_HEIGHT+20),
|
|
BUTTON_WIDTH, BUTTON_HEIGHT, "btnRefuel",
|
|
buf, spaceport_refuel);
|
|
if(player->credits < refuel_price()) /* Not enough memory. */
|
|
window_disableButton(land_wid, "btnRefuel");
|
|
}
|
|
}
|
|
|
|
|
|
landed = 1;
|
|
hooks_run("land");
|
|
|
|
/* Generate mission computer stuff. */
|
|
mission_computer = missions_computer(&mission_ncomputer,
|
|
land_planet->faction, land_planet->name, cur_system->name);
|
|
|
|
if(!has_visited(VISITED_LAND)) {
|
|
/* TODO: mission check. */
|
|
visited(VISITED_LAND);
|
|
}
|
|
}
|
|
|
|
/* Takeoff from the planet. */
|
|
void takeoff(void) {
|
|
int sw, sh, i, h;
|
|
char* lt;
|
|
|
|
if(!landed) return;
|
|
|
|
/* The music. */
|
|
music_choose("takeoff");
|
|
|
|
sw = land_planet->gfx_space->w;
|
|
sh = land_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(land_planet->pos.x + RNG(-sw/2, sw/2),
|
|
land_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;
|
|
|
|
/* Time goes by, triggers hook before takeoff. */
|
|
ltime_inc(RNG(2*LTIME_UNIT_LENGTH, 3*LTIME_UNIT_LENGTH));
|
|
lt = ltime_pretty(0);
|
|
player_message("taking off from %s on %s", land_planet->name, lt);
|
|
free(lt);
|
|
|
|
/* Initialize the new space. */
|
|
h = hyperspace_target;
|
|
space_init(NULL);
|
|
hyperspace_target = h;
|
|
|
|
/* Cleanup. */
|
|
save_all(); /* Must be before cleaning up planet. Duh! */
|
|
land_planet = NULL;
|
|
window_destroy(land_wid);
|
|
landed = 0;
|
|
land_visited = 0;
|
|
hooks_run("takeoff");
|
|
hooks_run("enter");
|
|
|
|
/* Cleanup mission computer. */
|
|
for(i = 0; i < mission_ncomputer; i++)
|
|
mission_cleanup(&mission_computer[i]);
|
|
free(mission_computer);
|
|
mission_computer = NULL;
|
|
mission_ncomputer = 0;
|
|
}
|
|
|