/** * @brief Attempt to steal the boarded ship's 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 let player 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 Aborts autonav. * * @param reason Human-readable string describing abort condition. */ void player_autonavAbort( const char *reason ) { /* No point if player is beyond aborting. */ if ((player.p==NULL) || pilot_isFlag(player.p, PILOT_HYPERSPACE)) return; /* Cooldown (handled later) may be script-initiated and we don't * want to make it player-abortable while under manual control. */ if (pilot_isFlag( player.p, PILOT_MANUAL_CONTROL )) return; if (player_isFlag(PLAYER_AUTONAV)) { if (reason != NULL) player_message(_("\arAutonav aborted: %s!"), reason); else player_message(_("\arAutonav aborted!")); player_rmFlag(PLAYER_AUTONAV); /* Get rid of acceleration. */ player_accelOver(); /* Break possible hyperspacing. */ if (pilot_isFlag(player.p, PILOT_HYP_PREP)) { pilot_hyperspaceAbort(player.p); player_message(_("\apAborting hyperspace sequence.")); } /* Reset time compression. */ player_autonavEnd(); } }
/** * @brief Attempt to steal the boarded ship's fuel. * * @param wdw Window triggering the function. * @param str Unused. */ static void board_stealFuel( unsigned int wdw, char* str ) { (void)str; Pilot* p; p = pilot_get(player->target); if (p->fuel <= 0.) { /* no 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; p->fuel = 0.; /* 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 ship's fuel."); }
/** * @brief Starts autonav. */ void player_autonavStart (void) { /* Not under manual control or disabled. */ if (pilot_isFlag( player.p, PILOT_MANUAL_CONTROL ) || pilot_isDisabled(player.p)) return; if ((player.p->nav_hyperspace == -1) && (player.p->nav_planet== -1)) return; else if ((player.p->nav_planet != -1) && !player_getHypPreempt()) { player_autonavPnt( cur_system->planets[ player.p->nav_planet ]->name ); return; } if (player.p->fuel < player.p->fuel_consumption) { player_message(_("\arNot enough fuel to jump for autonav.")); return; } if (pilot_isFlag( player.p, PILOT_NOJUMP)) { player_message(_("\arHyperspace drive is offline.")); return; } if (!player_autonavSetup()) return; player.autonav = AUTONAV_JUMP_APPROACH; }
/** * @brief Toggles the player's weapon safety. */ void weapon_toggleSafety (void) { weapon_safety = !weapon_safety; if (weapon_safety) player_message( "Enabling weapon safety." ); else player_message( "Disabling weapon safety." ); }
/** * @brief Opens the communication dialogue with a pilot. * * @param pilot Pilot to communicate with. * @return 0 on success. */ int comm_openPilot( unsigned int pilot ) { const char *msg; unsigned int wid; /* Get the pilot. */ comm_pilot = pilot_get( pilot ); if (comm_pilot == NULL) return -1; /* Must not be disabled. */ if (pilot_isFlag(comm_pilot, PILOT_DISABLED)) { player_message("%s does not respond.", comm_pilot->name); return 0; } /* Check to see if pilot wants to communicate. */ msg = comm_getString( "comm_no" ); if (msg != NULL) { player_message( msg ); return 0; } /* Set up for the comm_get* functions. */ ai_setPilot( comm_pilot ); /* Create the generic comm window. */ wid = comm_open( ship_loadCommGFX( comm_pilot->ship ), comm_pilot->faction, pilot_isHostile(comm_pilot) ? -1 : pilot_isFriendly(comm_pilot) ? 1 : 0, pilot_isFlag(comm_pilot, PILOT_BRIBED), comm_pilot->name ); /* Add special buttons. */ window_addButton( wid, -20, 20 + BUTTON_HEIGHT + 20, BUTTON_WIDTH, BUTTON_HEIGHT, "btnGreet", "Greet", NULL ); if (!pilot_isFlag(comm_pilot, PILOT_BRIBED) && /* Not already bribed. */ ((faction_getPlayer( comm_pilot->faction ) < 0) || /* Hostile. */ pilot_isHostile(comm_pilot))) window_addButton( wid, -20, 20 + 2*BUTTON_HEIGHT + 40, BUTTON_WIDTH, BUTTON_HEIGHT, "btnBribe", "Bribe", comm_bribePilot ); else window_addButton( wid, -20, 20 + 2*BUTTON_HEIGHT + 40, BUTTON_WIDTH, BUTTON_HEIGHT, "btnRequest", "Refuel", comm_requestFuel ); /* Run hooks if needed. */ pilot_runHook( comm_pilot, PILOT_HOOK_HAIL ); return 0; }
/** * @brief Checks to see if the hijack attempt failed. * * @return 1 on failure to board, otherwise 0. */ static int board_fail( unsigned int wdw ) { int ret; ret = board_trySteal( player ); if (ret == 0) return 0; else if (ret < 0) /* killed ship. */ 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 Have a pilot order its escorts to hold position. * * @param parent Pilot giving the order. */ int escorts_hold( Pilot *parent ) { int ret; ret = escort_command( parent, "e_hold", 0 ); if ((ret == 0) && (parent == player.p)) player_message(_("\agEscorts: \a0Holding position.")); return ret; }
/** * @brief Have a pilot order it's escorts to dock. * * @param parent Pilot giving the order. */ int escorts_return( Pilot *parent ) { int ret; ret = escort_command( parent, ESCORT_RETURN, -1 ); if ((ret == 0) && (parent == player)) player_message("Escorts: Returning to ship."); return ret; }
/** * @brief Have a pilot order it's escorts to clear orders. * * @param parent Pilot giving the order. */ int escorts_clear( Pilot *parent ) { int ret; ret = escort_command( parent, ESCORT_CLEAR, -1); if ((ret == 0) && (parent == player)) player_message("Escorts: Clearing orders."); return ret; }
/** * @brief Have a pilot order its escorts to clear orders. * * @param parent Pilot giving the order. */ int escorts_clear( Pilot *parent ) { int ret; ret = escort_command( parent, "e_clear", 0 ); if ((ret == 0) && (parent == player.p)) player_message(_("\agEscorts: \a0Clearing orders.")); return ret; }
/** * @brief Have a pilot order it's escorts to hold position. * * @param parent Pilot giving the order. */ int escorts_hold( Pilot *parent ) { int ret; ret = escort_command( parent, ESCORT_HOLD, -1 ); if ((ret == 0) && (parent == player)) player_message("Escorts: Holding position."); return ret; }
/** * @brief Have a pilot order its escorts to dock. * * @param parent Pilot giving the order. */ int escorts_return( Pilot *parent ) { int ret; ret = escort_command( parent, "e_return", 0 ); if ((ret == 0) && (parent == player.p)) player_message(_("\agEscorts: \a0Returning to ship.")); return ret; }
/** * @brief Attempt to steal the boarded ship's credits. * * @param wdw Window triggering 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) { /* you can't steal from the poor */ player_message("The ship has no credits."); 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 credits."); }
/** * @brief Have a pilot order it's escorts to attack it's target. * * @param parent Pilot giving the order. */ int escorts_attack( Pilot *parent ) { int ret; Pilot *t; ret = 1; if (parent->target != parent->id) ret = escort_command( parent, ESCORT_ATTACK, parent->target ); if ((ret == 0) && (parent == player)) { t = pilot_get(parent->target); if (t != NULL) player_message("Escorts: Attacking %s.", t->name); } return ret; }
/** * @brief Have a pilot order its escorts to jump. * * @param parent Pilot giving the order. */ int escorts_jump( Pilot *parent, JumpPoint *jp ) { int ret; LuaJump lj; lj.destid = jp->targetid; lj.srcid = cur_system->id; lua_pushjump( naevL, lj ); ret = escort_command( parent, "hyperspace", -1 ); lua_pop(naevL, 1); if ((ret == 0) && (parent == player.p)) player_message(_("\agEscorts: \a0Jumping.")); return ret; }
/** * @brief Prepares the player to enter autonav. * * @return 1 on success, 0 on failure (disabled, etc.) */ static int player_autonavSetup (void) { /* Not under manual control or disabled. */ if (pilot_isFlag( player.p, PILOT_MANUAL_CONTROL ) || pilot_isDisabled(player.p)) return 0; /* Autonav is mutually-exclusive with other autopilot methods. */ player_restoreControl( PINPUT_AUTONAV, NULL ); player_message(_("\apAutonav initialized.")); if (!player_isFlag(PLAYER_AUTONAV)) { tc_base = player_isFlag(PLAYER_DOUBLESPEED) ? 2. : 1.; tc_mod = tc_base; if (conf.compression_mult >= 1.) player.tc_max = MIN( conf.compression_velocity / solid_maxspeed(player.p->solid, player.p->speed, player.p->thrust), conf.compression_mult ); else player.tc_max = conf.compression_velocity / solid_maxspeed(player.p->solid, player.p->speed, player.p->thrust); /* Safe cap. */ player.tc_max = MAX( 1., player.tc_max ); } /* Sane values. */ tc_rampdown = 0; tc_down = 0.; lasts = player.p->shield / player.p->shield_max; lasta = player.p->armour / player.p->armour_max; /* Set flag and tc_mod just in case. */ player_setFlag(PLAYER_AUTONAV); pause_setSpeed( tc_mod ); /* Make sure time acceleration starts immediately. */ player.autonav_timer = 0.; return 1; }
/** * @brief Have a pilot order its escorts to attack its target. * * @param parent Pilot giving the order. */ int escorts_attack( Pilot *parent ) { int ret; Pilot *t; /* Avoid killing self. */ t = pilot_get(parent->target); if (t == NULL) return 1; if (t->faction == parent->faction) return 1; /* Send command. */ ret = 1; if (parent->target != parent->id) { lua_pushpilot(naevL, parent->target); ret = escort_command( parent, "e_attack", -1 ); lua_pop(naevL, 1); } if ((ret == 0) && (parent == player.p)) player_message(_("\agEscorts: \a0Attacking %s."), t->name); return ret; }
/** * @brief Opens a communication dialogue with a planet. * * @param planet Planet to communicate with. * @return 0 on success. */ int comm_openPlanet( Planet *planet ) { unsigned int wid; /* Must not be disabled. */ if (!planet_hasService(planet, PLANET_SERVICE_BASIC)) { player_message("%s does not respond.", planet->name); return 0; } comm_planet = planet; /* Create the generic comm window. */ wid = comm_open( gl_dupTexture( comm_planet->gfx_space ), comm_planet->faction, 0, 0, comm_planet->name ); /* Add special buttons. */ if (areEnemies(player->faction, planet->faction) && !planet->bribed) window_addButton( wid, -20, 20 + BUTTON_HEIGHT + 20, BUTTON_WIDTH, BUTTON_HEIGHT, "btnBribe", "Bribe", comm_bribePlanet ); return 0; }
/** * @fn void player_board (void) * * @brief Attempt to board the player's 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 isn't 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); /* * 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, "Credits:\n" "Cargo:\n" "Fuel:\n" ); window_addText( wdw, 80, -30, 120, 60, 0, "txtData", &gl_smallFont, &cBlack, NULL ); 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 Makes the player take off if landed. * * @param delay Whether or not to have time pass as if the player landed normally. */ void takeoff( int delay ) { int h; char *nt; double a, r; if (!landed) return; /* Player's ship is not able to fly. */ if (!player_canTakeoff()) { char message[512]; pilot_reportSpaceworthy( player.p, message, sizeof(message) ); dialogue_msg( _("Ship not fit for flight"), message ); /* Check whether the player needs rescuing. */ land_stranded(); return; } /* Clear queued takeoff. */ land_takeoff = 0; /* Refuel if needed. */ land_refuel(); /* In case we had paused messy sounds. */ sound_stopAll(); /* ze music */ music_choose("takeoff"); /* to randomize the takeoff a bit */ a = RNGF() * 2. * M_PI; r = RNGF() * land_planet->radius; /* no longer authorized to land */ player_rmFlag(PLAYER_LANDACK); pilot_rmFlag(player.p,PILOT_LANDING); /* No longer landing. */ /* set player to another position with random facing direction and no vel */ player_warp( land_planet->pos.x + r * cos(a), land_planet->pos.y + r * sin(a) ); vect_pset( &player.p->solid->vel, 0., 0. ); player.p->solid->dir = RNGF() * 2. * M_PI; cam_setTargetPilot( player.p->id, 0 ); /* heal the player */ pilot_healLanded( player.p ); /* Clear planet target. Allows for easier autonav out of the system. */ player_targetPlanetSet( -1 ); /* initialize the new space */ h = player.p->nav_hyperspace; space_init(NULL); player.p->nav_hyperspace = h; /* cleanup */ if (save_all() < 0) /* must be before cleaning up planet */ dialogue_alert( _("Failed to save game! You should exit and check the log to see what happened and then file a bug report!") ); /* time goes by, triggers hook before takeoff */ if (delay) ntime_inc( ntime_create( 0, 1, 0 ) ); /* 1 STP */ nt = ntime_pretty( 0, 2 ); player_message( _("\apTaking off from %s on %s."), land_planet->name, nt); free(nt); /* Hooks and stuff. */ land_cleanup(); /* Cleanup stuff */ hooks_run("takeoff"); /* Must be run after cleanup since we don't want the missions to think we are landed. */ if (menu_isOpen(MENU_MAIN)) return; player_addEscorts(); hooks_run("enter"); if (menu_isOpen(MENU_MAIN)) return; events_trigger( EVENT_TRIGGER_ENTER ); missions_run( MIS_AVAIL_SPACE, -1, NULL, NULL ); if (menu_isOpen(MENU_MAIN)) return; player.p->ptimer = PILOT_TAKEOFF_DELAY; pilot_setFlag( player.p, PILOT_TAKEOFF ); pilot_setThrust( player.p, 0. ); pilot_setTurn( player.p, 0. ); /* Reset speed */ player_autonavResetSpeed(); }
/** * @brief Handles the autonavigation process for the player. */ static void player_autonav (void) { JumpPoint *jp; int ret; double d, t, tint; double vel; switch (player.autonav) { case AUTONAV_JUMP_APPROACH: /* Target jump. */ jp = &cur_system->jumps[ player.p->nav_hyperspace ]; ret = player_autonavApproach( &jp->pos, &d, 0 ); if (ret) player.autonav = AUTONAV_JUMP_BRAKE; else if (!tc_rampdown && (map_npath<=1)) { vel = MIN( 1.5*player.p->speed, VMOD(player.p->solid->vel) ); t = d / vel * (1.2 - .1 * tc_base); /* tint is the integral of the time in per time units. * * tc_mod * ^ * | * |\ * | \ * | \___ * | * +------> time * 0 3 * * We decompose integral in a rectangle (3*1) and a triangle (3*(tc_mod-1.))/2. * This is the "elapsed time" when linearly decreasing the tc_mod. Which we can * use to calculate the actual "game time" that'll pass when decreasing the * tc_mod to 1 during 3 seconds. This can be used then to compare when we want to * start decrementing. */ tint = 3. + 0.5*(3.*(tc_mod-tc_base)); if (t < tint) { tc_rampdown = 1; tc_down = (tc_mod-tc_base) / 3.; } } break; case AUTONAV_JUMP_BRAKE: /* Target jump. */ jp = &cur_system->jumps[ player.p->nav_hyperspace ]; if (player.p->stats.misc_instant_jump) { ret = pilot_interceptPos( player.p, jp->pos.x, jp->pos.y ); if (!ret && space_canHyperspace(player.p)) ret = 1; player_acc = player.p->solid->thrust / player.p->thrust; } else ret = player_autonavBrake(); /* Try to jump or see if braked. */ if (ret) { if (space_canHyperspace(player.p)) player_jump(); player.autonav = AUTONAV_JUMP_APPROACH; } /* See if should ramp down. */ if (!tc_rampdown && (map_npath<=1)) { tc_rampdown = 1; tc_down = (tc_mod-tc_base) / 3.; } break; case AUTONAV_POS_APPROACH: ret = player_autonavApproach( &player.autonav_pos, &d, 1 ); if (ret) { player_message( _("\apAutonav arrived at position.") ); player_autonavEnd(); } else if (!tc_rampdown) player_autonavRampdown(d); break; case AUTONAV_PNT_APPROACH: ret = player_autonavApproach( &player.autonav_pos, &d, 1 ); if (ret) { player_message( _("\apAutonav arrived at \a%c%s\a\0."), planet_getColourChar( planet_get(player.autonavmsg) ), player.autonavmsg ); player_autonavEnd(); } else if (!tc_rampdown) player_autonavRampdown(d); break; } }