#include #include #include #include #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_open(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_open(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_open(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_open(char* str); static void shipyard_yours_close(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_open(void); static void spaceport_bar_close(char* str); /* News. */ static void news_open(void); static void news_close(char* str); /* Mission computer. */ static void misn_open(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_open(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_open(void) { char** soutfits; 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, -220, OUTFITS_WIDTH-300, 180, 0, "txtDescription", &gl_smallFont, NULL, NULL); /* Set up the outfits to buy/sell. */ soutfits = outfit_getTech(&noutfits, land_planet->tech, PLANET_TECH_MAX); window_addList(secondary_wid, 20, 40, 200, OUTFITS_HEIGHT-80, "lstOutfits", soutfits, 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_open(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_open); 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_open(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_yours_close); 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_yours_close(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_yours_close(NULL); shipyard_yours_open(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_open(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_open); 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_open(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_open(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_open); 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_open); 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_open); /* 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_open); window_addButton(land_wid, 20, 20 + BUTTON_HEIGHT + 20, BUTTON_WIDTH, BUTTON_HEIGHT, "btnBar", "Spaceport Bar", (void(*)(char*))spaceport_bar_open); 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; }