#include "lephisto.h" #include "log.h" #include "pilot.h" #include "player.h" #include "toolkit.h" #include "space.h" #include "rng.h" #include "economy.h" #include "hook.h" #include "board.h" #define BOARDING_WIDTH 300 /**< Boarding window width. */ #define BOARDING_HEIGHT 200 /**< Boarding window height. */ #define BUTTON_WIDTH 50 /**< Boarding button width. */ #define BUTTON_HEIGHT 30 /**< Boarding button height. */ static void board_exit(unsigned int wdw, char* str); static void board_stealCreds(unsigned int wdw, char* str); static void board_stealCargo(unsigned int wdw, char* str); static void board_stealFuel(unsigned int wdw, char* str); static int board_fail(unsigned int wdw); static void board_update(unsigned int wdw); /** * @fn void player_board(void) * * @brief Attempt to board the players target. * * Creates the window on success. */ void player_board(void) { Pilot* p; unsigned int wdw; if(player->target == PLAYER_ID) { player_message("You need a target to board first!"); return; } p = pilot_get(player->target); if(!pilot_isDisabled(p)) { player_message("You cannot board a ship that is not disabled!"); return; } else if(vect_dist(&player->solid->pos, &p->solid->pos) > p->ship->gfx_space->sw * PILOT_SIZE_APROX) { player_message("You are too far away to board your target."); return; } else if((pow2(VX(player->solid->vel)-VX(p->solid->vel)) + pow2(VY(player->solid->vel)-VY(p->solid->vel))) > (double)pow2(MAX_HYPERSPACE_VEL)) { player_message("You are going too fast to board the ship."); return; } else if(pilot_isFlag(p, PILOT_BOARDED)) { player_message("Your target cannot be boarded again."); return; } /* Pilot will be boarded. */ pilot_setFlag(p, PILOT_BOARDED); player_message("Boarding ship %s.", p->name); /* Tweak some values. */ p->fuel = (double)RNG(100, p->fuel_max); /* Create the boarding window. */ wdw = window_create("Boarding", -1, -1, BOARDING_WIDTH, BOARDING_HEIGHT); window_addText(wdw, 20, -30, 120, 60, 0, "txtCargo", &gl_smallFont, &cDConsole, "SCreds:\n" "Cargo:\n" "Fuel:"); window_addButton(wdw, 20, 20, BUTTON_WIDTH, BUTTON_HEIGHT, "btnStealCredits", "Credits", board_stealCreds); window_addButton(wdw, 20+BUTTON_WIDTH+20, 20, BUTTON_WIDTH, BUTTON_HEIGHT, "btnStealCargo", "Cargo", board_stealCargo); window_addButton(wdw, 20+2*(BUTTON_WIDTH+20), 20, BUTTON_WIDTH, BUTTON_HEIGHT, "btnStealCargo", "Fuel", board_stealFuel); window_addButton(wdw, -20, 20, BUTTON_WIDTH, BUTTON_HEIGHT, "btnBoardingClose", "Leave", board_exit); board_update(wdw); /* Run hook if needed. */ pilot_runHook(p, PILOT_HOOK_BOARD); } /** * @brief Closes the boarding window. * @param wdw Window triggered the function. * @param str Unused. */ static void board_exit(unsigned int wdw, char* str) { (void) str; window_destroy(wdw); } /** * @brief Attempt to steal the boarding ships credits. * @param wdw Window triggered the function. * @param str Unused. */ static void board_stealCreds(unsigned int wdw, char* str) { (void)str; Pilot* p; p = pilot_get(player->target); if(p->credits == 0) { /* Can't steal from the poor. ;) */ player_message("The ship has no SCreds."); return; } if(board_fail(wdw)) return; player->credits += p->credits; p->credits = 0; board_update(wdw); /* Update the lack of credits. */ player_message("You manage to steal the ship's Scred."); } /** * @brief Attempt to steal the boarded ships cargo. * @param wdw Window triggering the function. * @param str Unused. */ static void board_stealCargo(unsigned int wdw, char* str) { (void)str; int q; Pilot* p; p = pilot_get(player->target); if(p->ncommodities==0) { /* No cargo. */ player_message("The ship has no cargo."); return; } else if(pilot_cargoFree(player) <= 0) { player_message("You have no room for cargo."); return; } if(board_fail(wdw)) return; /** Steal as much as possible until full - @todo: Allow the player to choose. */ q = 1; while((p->ncommodities > 0) && (q != 0)) { q = pilot_addCargo(player, p->commodities[0].commodity, p->commodities[0].quantity); pilot_rmCargo(p, p->commodities[0].commodity, q); } board_update(wdw); player_message("You manage to steal the ship's cargo."); } /** * @brief */ static void board_stealFuel(unsigned int wdw, char* str) { (void)str; Pilot* p; p = pilot_get(player->target); if(player->fuel <= 0.) { /* Urgh.. They don't have any fuel. */ player_message("The ship has no fuel."); return; } else if(player->fuel == player->fuel_max) { player_message("Your ship is at maximum fuel capacity."); return; } if(board_fail(wdw)) return; /* Steal fuel. */ player->fuel += p->fuel; /* Make sure doesn't overflow. */ if(player->fuel > player->fuel_max) { p->fuel = player->fuel_max - player->fuel; player->fuel = player->fuel_max; } board_update(wdw); player_message("You manage to steal the ships fuel."); } /** * @brief Check to see if the hijack attempt failed. * @return 1 on failure to board. Otherwise 0. */ static int board_fail(unsigned int wdw) { Pilot* p; p = pilot_get(player->target); /* Fail chance. */ if(RNGF() > (0.5 * (10. + (double)p->ship->crew/10.+(double)player->ship->crew))) return 0; if(RNGF() < 0.4) { /* 40% of instadeath! */ /* 33% of instant death. */ p->armour = -1; player_message("You have tripped the ship's self destruct mechanism!"); } else /* You just got locked out!! */ player_message("The ship's security system locks %s out!", (player->ship->crew > 0) ? "your crew" : "you"); board_exit(wdw, NULL); return 1; } /** * @brief Updates the boarding window. */ static void board_update(unsigned int wdw) { int i, j; char str[PATH_MAX]; char cred[10]; Pilot* p; p = pilot_get(player->target); j = 0; /* Credits. */ credits2str(cred, p->credits, 2); j += snprintf(&str[j], PATH_MAX-j, "%s\n", cred); /* Commodities. */ if(p->ncommodities == 0) j += snprintf(&str[j], PATH_MAX-j, "none\n"); else { for(i = 0; i < p->ncommodities; i++) j += snprintf(&str[j], PATH_MAX-j, "%d %s\n", p->commodities[i].quantity, p->commodities[i].commodity->name); } /* Fuel. */ if(p->fuel <= 0.) j += snprintf(&str[j], PATH_MAX-j, "none\n"); else j += snprintf(&str[j], PATH_MAX-j, "%.0f Units\n", p->fuel); window_modifyText(wdw, "txtData", str); }