Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/development'
Browse files Browse the repository at this point in the history
* origin/development:
  Control laptop activity enhancement (#28465)
  • Loading branch information
kevingranade committed Mar 14, 2019
2 parents 39f8fda + 15b9287 commit 7d7eaf6
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 48 deletions.
2 changes: 1 addition & 1 deletion data/json/player_activities.json
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@
"type": "activity_type",
"stop_phrase": "Stop programming override?",
"suspendable": false,
"based_on": "speed",
"based_on": "time",
"no_resume": true
},
{
Expand Down
67 changes: 33 additions & 34 deletions src/activity_handlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ activity_handlers::do_turn_functions = {
{ activity_id( "ACT_HARVEST_PLOT" ), harvest_plot_do_turn },
{ activity_id( "ACT_PLANT_PLOT" ), plant_plot_do_turn },
{ activity_id( "ACT_FERTILIZE_PLOT" ), fertilize_plot_do_turn },
{ activity_id( "ACT_TRY_SLEEP" ), try_sleep_do_turn }
{ activity_id( "ACT_TRY_SLEEP" ), try_sleep_do_turn },
{ activity_id( "ACT_ROBOT_CONTROL" ), robot_control_do_turn }
};

const std::map< activity_id, std::function<void( player_activity *, player * )> >
Expand Down Expand Up @@ -3173,44 +3174,44 @@ void activity_handlers::plant_plot_do_turn( player_activity *, player *p )
_( "You planted all seeds you could." ) );
}

void activity_handlers::robot_control_finish( player_activity *act, player *p )
void activity_handlers::robot_control_do_turn( player_activity *act, player *p )
{
uilist pick_robot;
pick_robot.text = _( "Override ready, choose an endpoint to hack." );
// Build a list of all unfriendly robots in range.
std::vector< monster * > mons; // @todo: change into vector<Creature*>
std::vector< tripoint > locations;
int entry_num = 0;
for( monster &candidate : g->all_monsters() ) {
if( candidate.type->in_species( species_id( "ROBOT" ) ) && candidate.friendly == 0 &&
rl_dist( p->pos(), candidate.pos() ) <= 10 ) {
mons.push_back( &candidate );
pick_robot.addentry( entry_num++, true, MENU_AUTOASSIGN, candidate.name() );
tripoint seen_loc;
// Show locations of seen robots, center on player if robot is not seen
if( p->sees( candidate ) ) {
seen_loc = candidate.pos();
} else {
seen_loc = p->pos();
}
locations.push_back( seen_loc );
}
}
if( mons.empty() ) {
p->add_msg_if_player( m_info, _( "No enemy robots in range." ) );
if( act->monsters.empty() ) {
debugmsg( "No monster assigned in ACT_ROBOT_CONTROL" );
act->set_to_null();
return;
}
pointmenu_cb callback( locations );
pick_robot.callback = &callback;
pick_robot.query();
if( pick_robot.ret < 0 || static_cast<size_t>( pick_robot.ret ) >= mons.size() ) {
p->add_msg_if_player( m_info, _( "Never mind" ) );
std::shared_ptr<monster> z = act->monsters[0].lock();

if( !z || !iuse::robotcontrol_can_target( p, *z ) ) {
p->add_msg_if_player( _( "Target lost. IFF override failed." ) );
act->set_to_null();
return;
}
const size_t mondex = pick_robot.ret;
monster *z = mons[mondex];

// @todo Add some kind of chance of getting the target's attention

// Allow time to pass
p->pause();
}

void activity_handlers::robot_control_finish( player_activity *act, player *p )
{
act->set_to_null();

if( act->monsters.empty() ) {
debugmsg( "No monster assigned in ACT_ROBOT_CONTROL" );
return;
}

std::shared_ptr<monster> z = act->monsters[0].lock();
act->monsters.clear();

if( !z || !iuse::robotcontrol_can_target( p, *z ) ) {
p->add_msg_if_player( _( "Target lost. IFF override failed." ) );
return;
}

p->add_msg_if_player( _( "You unleash your override attack on the %s." ), z->name().c_str() );

/** @EFFECT_INT increases chance of successful robot reprogramming, vs difficulty */
Expand All @@ -3227,7 +3228,6 @@ void activity_handlers::robot_control_finish( player_activity *act, player *p )
z->apply_damage( p, bp_torso, rng( 1, 10 ) ); //damage it a little
if( z->is_dead() ) {
p->practice( skill_id( "computer" ), 10 );
act->set_to_null();
return; // Do not do the other effects if the robot died
}
if( one_in( 3 ) ) {
Expand All @@ -3242,5 +3242,4 @@ void activity_handlers::robot_control_finish( player_activity *act, player *p )
p->add_msg_if_player( _( "...but the robot refuses to acknowledge you as an ally!" ) );
}
p->practice( skill_id( "computer" ), 10 );
act->set_to_null();
}
1 change: 1 addition & 0 deletions src/activity_handlers.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ void plant_plot_do_turn( player_activity *act, player *p );
void fertilize_plot_do_turn( player_activity *act, player *p );
void harvest_plot_do_turn( player_activity *act, player *p );
void try_sleep_do_turn( player_activity *act, player *p );
void robot_control_do_turn( player_activity *act, player *p );

// defined in activity_handlers.cpp
extern const std::map< activity_id, std::function<void( player_activity *, player * )> >
Expand Down
52 changes: 40 additions & 12 deletions src/iuse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5382,6 +5382,14 @@ int iuse::seed( player *p, item *it, bool, const tripoint & )
return 0;
}

bool iuse::robotcontrol_can_target( player *p, const monster &m )
{
return !m.is_dead()
&& m.type->in_species( ROBOT )
&& m.friendly == 0
&& rl_dist( p->pos(), m.pos() ) <= 10;
}

int iuse::robotcontrol( player *p, item *it, bool, const tripoint & )
{
if( !it->ammo_sufficient() ) {
Expand All @@ -5401,27 +5409,47 @@ int iuse::robotcontrol( player *p, item *it, bool, const tripoint & )
} );
switch( choice ) {
case 0: { // attempt to make a robot friendly

bool enemy_robot_in_range = false;
for( monster &candidate : g->all_monsters() ) {
if( candidate.type->in_species( ROBOT ) && candidate.friendly == 0 &&
rl_dist( p->pos(), candidate.pos() ) <= 10 ) {
enemy_robot_in_range = true;
break;
uilist pick_robot;
pick_robot.text = _( "Choose an endpoint to hack." );
// Build a list of all unfriendly robots in range.
std::vector< std::shared_ptr< monster> > mons; // @todo: change into vector<Creature*>
std::vector< tripoint > locations;
int entry_num = 0;
for( const monster &candidate : g->all_monsters() ) {
if( robotcontrol_can_target( p, candidate ) ) {
mons.push_back( g->shared_from( candidate ) );
pick_robot.addentry( entry_num++, true, MENU_AUTOASSIGN, candidate.name() );
tripoint seen_loc;
// Show locations of seen robots, center on player if robot is not seen
if( p->sees( candidate ) ) {
seen_loc = candidate.pos();
} else {
seen_loc = p->pos();
}
locations.push_back( seen_loc );
}
}
if( !enemy_robot_in_range ) {
if( mons.empty() ) {
p->add_msg_if_player( m_info, _( "No enemy robots in range." ) );
return 0;
return it->type->charges_to_use();
}

p->add_msg_if_player( _( "You start preparing your override." ) );
pointmenu_cb callback( locations );
pick_robot.callback = &callback;
pick_robot.query();
if( pick_robot.ret < 0 || static_cast<size_t>( pick_robot.ret ) >= mons.size() ) {
p->add_msg_if_player( m_info, _( "Never mind" ) );
return it->type->charges_to_use();
}
const size_t mondex = pick_robot.ret;
std::shared_ptr< monster > z = mons[mondex];
p->add_msg_if_player( _( "You start reprogramming the %s into an ally." ), z->name().c_str() );

/** @EFFECT_INT speeds up hacking preperation */
/** @EFFECT_COMPUTER speeds up hacking preperation */
int move_cost = std::max( 100, 1000 - p->int_cur * 10 - p->get_skill_level( skill_computer ) * 10 );

player_activity act( activity_id( "ACT_ROBOT_CONTROL" ), move_cost );
act.monsters.emplace_back( z );

p->assign_activity( act );

return it->type->charges_to_use();
Expand Down
3 changes: 3 additions & 0 deletions src/iuse.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class item;
class player;
class JsonObject;
class MonsterGenerator;
class monster;

template<typename T> class ret_val;

Expand Down Expand Up @@ -177,6 +178,8 @@ class iuse
int pack_item( player *, item *, bool, const tripoint & );
int radglove( player *, item *, bool, const tripoint & );
int robotcontrol( player *, item *, bool, const tripoint & );
// Helper for validating a potential taget of robot control
static bool robotcontrol_can_target( player *, const monster & );
int einktabletpc( player *, item *, bool, const tripoint & );
int camera( player *, item *, bool, const tripoint & );
int ehandcuffs( player *, item *, bool, const tripoint & );
Expand Down
3 changes: 2 additions & 1 deletion src/player_activity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ player_activity::player_activity( const player_activity &rhs )
moves_total( rhs.moves_total ), moves_left( rhs.moves_left ),
index( rhs.index ), position( rhs.position ), name( rhs.name ),
values( rhs.values ), str_values( rhs.str_values ),
coords( rhs.coords ), placement( rhs.placement ),
coords( rhs.coords ), monsters( rhs.monsters ), placement( rhs.placement ),
auto_resume( rhs.auto_resume )
{
targets.clear();
Expand All @@ -45,6 +45,7 @@ player_activity &player_activity::operator=( const player_activity &rhs )
ignored_distractions = rhs.ignored_distractions;
values = rhs.values;
str_values = rhs.str_values;
monsters = rhs.monsters;
coords = rhs.coords;
placement = rhs.placement;
auto_resume = rhs.auto_resume;
Expand Down
2 changes: 2 additions & 0 deletions src/player_activity.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class JsonIn;
class JsonOut;
class player_activity;
class activity_type;
class monster;

using activity_id = string_id<activity_type>;

Expand All @@ -39,6 +40,7 @@ class player_activity
std::vector<int> values;
std::vector<std::string> str_values;
std::vector<tripoint> coords;
std::vector<std::weak_ptr<monster>> monsters;
tripoint placement;
/** If true, the activity will be auto-resumed next time the player attempts
* an identical activity. This value is set dynamically.
Expand Down
44 changes: 44 additions & 0 deletions src/savegame_json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,47 @@ static const std::array<std::string, NUM_OBJECTS> obj_type_name = { { "OBJECT_NO
}
};

// @todo: investigate serializing other members of the Creature class hierarchy
void serialize( const std::weak_ptr<monster> &obj, JsonOut &jsout )
{
if( const auto monster_ptr = obj.lock() ) {
jsout.start_object();

jsout.member( "monster_at", monster_ptr->pos() );
// @todo: if monsters/Creatures ever get unique ids,
// create a differently named member, e.g.
// jsout.member("unique_id", monster_ptr->getID());
jsout.end_object();
} else {
// Monster went away. It's up the activity handler to detect this.
jsout.write_null();
}
}

void deserialize( std::weak_ptr<monster> &obj, JsonIn &jsin )
{
JsonObject data = jsin.get_object();
tripoint temp_pos;

obj.reset();
if( data.read( "monster_at", temp_pos ) ) {
auto monp = g->critter_tracker->find( temp_pos );

if( monp == nullptr ) {
debugmsg( "no monster found at %d,%d,%d", temp_pos.x, temp_pos.y, temp_pos.z );
return;
}

obj = monp;
}

// @todo: if monsters/Creatures ever get unique ids,
// look for a differently named member, e.g.
// data.read( "unique_id", unique_id );
// obj = g->id_registry->from_id( unique_id)
// }
}

template<typename T>
void serialize( const cata::optional<T> &obj, JsonOut &jsout )
{
Expand Down Expand Up @@ -184,6 +225,7 @@ void player_activity::serialize( JsonOut &json ) const
json.member( "values", values );
json.member( "str_values", str_values );
json.member( "auto_resume", auto_resume );
json.member( "monsters", monsters );
}
json.end_object();
}
Expand Down Expand Up @@ -220,6 +262,8 @@ void player_activity::deserialize( JsonIn &jsin )
values = data.get_int_array( "values" );
str_values = data.get_string_array( "str_values" );
data.read( "auto_resume", auto_resume );
data.read( "monsters", monsters );

}

////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down

0 comments on commit 7d7eaf6

Please sign in to comment.