Skip to content

Commit

Permalink
basecamps: add an emergency recall option
Browse files Browse the repository at this point in the history
Fixes CleverRaven#31872

Add the option to recall any NPC that has been on a mission for
more than 24 hours.  This cancels the mission without refunding
any resources, but can be used to recover NPCs that are otherwise
stuck.
  • Loading branch information
mlangsdorf committed Oct 8, 2019
1 parent 4feecd9 commit 37a4f53
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 11 deletions.
5 changes: 4 additions & 1 deletion src/basecamp.h
Original file line number Diff line number Diff line change
Expand Up @@ -283,11 +283,14 @@ class basecamp
/// called with a companion @ref comp who is not the camp manager, finishes updating their
/// skills, consuming food, and returning them to the base.
void finish_return( npc &comp, bool fixed_time, const std::string &return_msg,
const std::string &skill, int difficulty );
const std::string &skill, int difficulty, bool cancel = false );
/// a wrapper function for @ref companion_choose_return and @ref finish_return
npc_ptr mission_return( const std::string &miss_id, time_duration min_duration,
bool fixed_time, const std::string &return_msg,
const std::string &skill, int difficulty );
/// select a companion for any mission to return to base
npc_ptr emergency_recall();

/// Called to close upgrade missions, @ref miss is the name of the mission id
/// and @ref dir is the direction of the location to be upgraded
bool upgrade_return( const point &dir, const std::string &miss );
Expand Down
57 changes: 50 additions & 7 deletions src/faction_camp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,13 @@ std::map<std::string, miss_data> miss_info = {{
"Recover Ally from Upgrading", to_translation( "Recover Ally from Upgrading" )
}
},
{
"_faction_camp_recall", {
"Emergency Recall", to_translation( "Emergency Recall" ),
to_translation( "Lost in the ether!\n" ),
"Emergency Recall", to_translation( "Emergency Recall" )
}
},
{
"_faction_camp_crafting_", {
"Craft Item", to_translation( "Craft Item" ),
Expand Down Expand Up @@ -1265,6 +1272,22 @@ void basecamp::get_available_missions( mission_data &mission_key, bool by_radio
}
}
}

if( !camp_workers.empty() ) {
const base_camps::miss_data &miss_info = base_camps::miss_info[ "_faction_camp_recall" ];
entry = string_format( _( "Notes: \n"
"Cancel a current mission and force the immediate return of a "
"companion. No work will be done on the mission and all "
"resources used on the mission will be lost.\n\n"
"WARNING: All resources used on the mission will be lost and "
"no work will be done. Only use this mission to recover a "
"companion who cannot otherwise be recovered.\n\n"
"Companions must be on missions for at least 24 hours before "
"emergency recall becomes available." ) );
bool avail = update_time_fixed( entry, camp_workers, 24_hours );
mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(),
cata::nullopt, entry, avail );
}
}

bool basecamp::handle_mission( const std::string &miss_id, const cata::optional<point> miss_dir,
Expand Down Expand Up @@ -1480,6 +1503,10 @@ bool basecamp::handle_mission( const std::string &miss_id, const cata::optional<
}
}

if( miss_id == "Emergency Recall" ) {
emergency_recall();
}

g->draw_ter();
wrefresh( g->w_terrain );
g->draw_panels( true );
Expand Down Expand Up @@ -2156,8 +2183,8 @@ npc_ptr basecamp::companion_choose_return( const std::string &miss_id,
return talk_function::companion_choose_return( omt_pos, base_camps::id, miss_id,
calendar::turn - min_duration );
}
void basecamp::finish_return( npc &comp, bool fixed_time, const std::string &return_msg,
const std::string &skill, int difficulty )
void basecamp::finish_return( npc &comp, const bool fixed_time, const std::string &return_msg,
const std::string &skill, int difficulty, const bool cancel )
{
popup( "%s %s", comp.name, return_msg );
// this is the time the mission was expected to take, or did take for fixed time missions
Expand All @@ -2166,7 +2193,9 @@ void basecamp::finish_return( npc &comp, bool fixed_time, const std::string &ret
if( !fixed_time ) {
mission_time = calendar::turn - comp.companion_mission_time;
}
talk_function::companion_skill_trainer( comp, skill, mission_time, difficulty );
if( !cancel ) {
talk_function::companion_skill_trainer( comp, skill, mission_time, difficulty );
}

// companions subtracted food when they started the mission, but didn't mod their hunger for
// that food. so add it back in.
Expand All @@ -2181,10 +2210,12 @@ void basecamp::finish_return( npc &comp, bool fixed_time, const std::string &ret
comp.companion_mission_time = calendar::before_time_starts;
comp.companion_mission_time_ret = calendar::before_time_starts;
bool by_radio = g->u.global_omt_location() != comp.global_omt_location();
for( size_t i = 0; i < comp.companion_mission_inv.size(); i++ ) {
for( const auto &it : comp.companion_mission_inv.const_stack( i ) ) {
if( !it.count_by_charges() || it.charges > 0 ) {
place_results( it, by_radio );
if( !cancel ) {
for( size_t i = 0; i < comp.companion_mission_inv.size(); i++ ) {
for( const auto &it : comp.companion_mission_inv.const_stack( i ) ) {
if( !it.count_by_charges() || it.charges > 0 ) {
place_results( it, by_radio );
}
}
}
}
Expand Down Expand Up @@ -2215,6 +2246,18 @@ npc_ptr basecamp::mission_return( const std::string &miss_id, time_duration min_
return comp;
}

npc_ptr basecamp::emergency_recall()
{
npc_ptr comp = talk_function::companion_choose_return( omt_pos, base_camps::id, "",
calendar::turn - 24_hours, false );
if( comp != nullptr ) {
const std::string return_msg = _( "responds to the emergency recall..." );
finish_return( *comp, false, return_msg, "menial", 0, true );
}
return comp;

}

bool basecamp::upgrade_return( const point &dir, const std::string &miss )
{
const std::string bldg = next_upgrade( dir, 1 );
Expand Down
5 changes: 3 additions & 2 deletions src/mission_companion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1998,13 +1998,14 @@ npc_ptr talk_function::companion_choose_return( const npc &p, const std::string
npc_ptr talk_function::companion_choose_return( const tripoint &omt_pos,
const std::string &role_id,
const std::string &mission_id,
const time_point &deadline )
const time_point &deadline,
const bool by_mission )
{
std::vector<npc_ptr> available;
for( npc_ptr &guy : overmap_buffer.get_companion_mission_npcs() ) {
npc_companion_mission c_mission = guy->get_companion_mission();
if( c_mission.position != omt_pos ||
c_mission.mission_id != mission_id || c_mission.role_id != role_id ) {
( by_mission && c_mission.mission_id != mission_id ) || c_mission.role_id != role_id ) {
continue;
}
if( g->u.has_trait( trait_id( "DEBUG_HS" ) ) ) {
Expand Down
3 changes: 2 additions & 1 deletion src/mission_companion.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ npc_ptr companion_choose( const std::string &skill_tested = "", int skill_level
npc_ptr companion_choose_return( const npc &p, const std::string &mission_id,
const time_point &deadline );
npc_ptr companion_choose_return( const tripoint &omt_pos, const std::string &role_id,
const std::string &mission_id, const time_point &deadline );
const std::string &mission_id, const time_point &deadline,
bool by_mission = true );

//Return NPC to your party
void companion_return( npc &comp );
Expand Down

0 comments on commit 37a4f53

Please sign in to comment.