#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, BUTTON_WIDTH, 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); // Fancy 128x128 image. window_addRect(secondary_wid, -20, -50, 128, 128, "rctImage", &cBlack, 0); window_addImage(secondary_wid, -20-128, -50-128, "imgOutfit", NULL); 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, 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_modifyImage(secondary_wid, "imgOutfit", outfit->gfx_store); 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; } else if(outfit_isAfterburner(outfit) && (player->afterburner != NULL)) { toolkit_alert("You can only have one afterburner."); 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-300, 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-40, 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, 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(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; }