diff --git a/doc/NPCs.md b/doc/NPCs.md index ff17b5b284605..1fa531150e209 100644 --- a/doc/NPCs.md +++ b/doc/NPCs.md @@ -593,6 +593,7 @@ Effect | Description `set_npc_engagement_rule: rule_string` | Sets the NPC follower AI rule for engagement distance to the value of `rule_string`. `set_npc_aim_rule: rule_string` | Sets the NPC follower AI rule for aiming speed to the value of `rule_string`. `npc_die` | The NPC will die at the end of the conversation. +`npc_set_goal:assign_mission_target_object` | The NPC will walk to `assign_mission_target_object`. See [the missions docs](MISSIONS_JSON.md) for `assign_mission_target` parameters. #### Map Updates Effect | Description diff --git a/src/dialogue.h b/src/dialogue.h index 789bea512bcaa..c6d6ad8ceefc3 100644 --- a/src/dialogue.h +++ b/src/dialogue.h @@ -136,6 +136,7 @@ struct talk_effect_fun_t { void set_npc_cbm_reserve_rule( const std::string &setting ); void set_npc_cbm_recharge_rule( const std::string &setting ); void set_mapgen_update( const JsonObject &jo, const std::string &member ); + void set_npc_goal( const JsonObject &jo, const std::string &member ); void set_bulk_trade_accept( bool is_trade, int quantity, bool is_npc = false ); void set_npc_gets_item( bool to_use ); void set_add_mission( const std::string &mission_id ); diff --git a/src/npctalk.cpp b/src/npctalk.cpp index 2186000e7b9e5..d2c2cbf60441c 100644 --- a/src/npctalk.cpp +++ b/src/npctalk.cpp @@ -54,6 +54,7 @@ #include "npctalk.h" #include "npctrade.h" #include "output.h" +#include "overmapbuffer.h" #include "pimpl.h" #include "player_activity.h" #include "point.h" @@ -2052,6 +2053,30 @@ void talk_effect_fun_t::set_mapgen_update( const JsonObject &jo, const std::stri }; } +void talk_effect_fun_t::set_npc_goal( const JsonObject &jo, const std::string &member ) +{ + mission_target_params dest_params = mission_util::parse_mission_om_target( jo.get_object( + member ) ); + function = [dest_params]( const dialogue & d ) { + npc *guy = d.actor( true )->get_npc(); + if( guy ) { + tripoint_abs_omt destination = mission_util::get_om_terrain_pos( dest_params ); + guy->goal = destination; + guy->omt_path = overmap_buffer.get_travel_path( guy->global_omt_location(), guy->goal, + overmap_path_params::for_npc() ); + if( destination == tripoint_abs_omt() || destination == overmap::invalid_tripoint || + guy->omt_path.empty() ) { + guy->goal = npc::no_goal_point; + guy->omt_path.clear(); + return; + } + guy->set_mission( NPC_MISSION_TRAVELLING ); + guy->guard_pos = cata::nullopt; + guy->set_attitude( NPCATT_NULL ); + } + }; +} + void talk_effect_fun_t::set_bulk_trade_accept( bool is_trade, int quantity, bool is_npc ) { function = [is_trade, is_npc, quantity]( const dialogue & d ) { @@ -3255,6 +3280,8 @@ void talk_effect_t::parse_sub_effect( const JsonObject &jo ) } else if( jo.has_string( "set_npc_cbm_recharge_rule" ) ) { const std::string setting = jo.get_string( "set_npc_cbm_recharge_rule" ); subeffect_fun.set_npc_cbm_recharge_rule( setting ); + } else if( jo.has_member( "npc_set_goal" ) ) { + subeffect_fun.set_npc_goal( jo, "npc_set_goal" ); } else if( jo.has_member( "mapgen_update" ) ) { subeffect_fun.set_mapgen_update( jo, "mapgen_update" ); } else if( jo.has_string( "u_buy_monster" ) ) {