From 7a4f8ca24c51fc647525f34f467682908f2cd12b Mon Sep 17 00:00:00 2001 From: Jason Jones Date: Wed, 21 Aug 2019 14:31:20 -0800 Subject: [PATCH 1/2] Add u_buy_monster talk effect --- doc/NPCs.md | 2 ++ src/dialogue.h | 2 ++ src/npctalk.cpp | 57 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) diff --git a/doc/NPCs.md b/doc/NPCs.md index e43a706671349..12d389e6dda2c 100644 --- a/doc/NPCs.md +++ b/doc/NPCs.md @@ -449,6 +449,8 @@ Effect | Description `add_debt: mod_list` | Increases the NPC's debt to the player by the values in the `mod_list`.
The following would increase the NPC's debt to the player by 1500x the NPC's altruism and 1000x the NPC's opinion of the player's value: `{ "effect": { "add_debt": [ [ "ALTRUISM", 3 ], [ "VALUE", 2 ], [ "TOTAL", 500 ] ] } }` `u_consume_item`, `npc_consume_item: item_string`, (*optional* `count: count_num`) | You or the NPC will delete the item or `count_num` copies of the item from their inventory.
This effect will fail if the you or NPC does not have at least `count_num` copies of the item, so it should be checked with `u_has_items` or `npc_has_items`. `u_remove_item_with`, `npc_remove_item_with: item_string` | You or the NPC will delete any instances of item in inventory.
This is an unconditional remove and will not fail if you or the NPC does not have the item. +`u_buy_monster: monster_type_string`, (*optional* `cost: cost_num`, *optional* `count: count_num`, *optional* `name: name_string`, *optional* `pacified: pacified_bool`) | The NPC will give your character `count_num` (default 1) instances of the monster as pets and will subtract `cost_num` from `op_of_u.owed` if specified. If the `op_o_u.owed` is less than `cost_num`, the trade window will open and the player will have to trade to make up the difference; the NPC will not give the player the item unless `cost_num` is satisfied.
If cost isn't present, the NPC gives your character the item at no charge.
If `name_string` is specified the monster(s) will have the specified name. If `pacified_bool` is set to true, the monster will have the pacified effect applied. + #### Behaviour / AI diff --git a/src/dialogue.h b/src/dialogue.h index 057a2f4a4b72b..82d860c709c13 100644 --- a/src/dialogue.h +++ b/src/dialogue.h @@ -121,6 +121,8 @@ struct talk_effect_fun_t { void set_bulk_trade_accept( bool is_trade, bool is_npc = false ); void set_npc_gets_item( bool to_use ); void set_add_mission( std::string mission_id ); + void set_u_buy_monster( const std::string &monster_id, int cost, int count, bool pacified, + const std::string &name ); void operator()( const dialogue &d ) const { if( !function ) { diff --git a/src/npctalk.cpp b/src/npctalk.cpp index 6c93075b3a788..c5b872c66c6bf 100644 --- a/src/npctalk.cpp +++ b/src/npctalk.cpp @@ -32,6 +32,7 @@ #include "json.h" #include "line.h" #include "map.h" +#include "map_iterator.h" #include "mapgen_functions.h" #include "martialarts.h" #include "messages.h" @@ -2097,6 +2098,55 @@ void talk_effect_fun_t::set_add_mission( const std::string mission_id ) }; } +void talk_effect_fun_t::set_u_buy_monster( const std::string &monster_type_id, int cost, int count, + bool pacified, const std::string &name ) +{ + function = [monster_type_id, cost, count, pacified, name]( const dialogue & d ) { + npc &p = *d.beta; + player &u = *d.alpha; + if( !npc_trading::pay_npc( p, cost ) ) { + popup( _( "You can't afford it!" ) ); + return; + } + + const mtype_id mtype( monster_type_id ); + const efftype_id effect_pet( "pet" ); + const efftype_id effect_pacified( "pacified" ); + const tripoint_range points = g->m.points_in_radius( u.pos(), 3 ); + + for( int i = 0; i < count; i++ ) { + monster tmp( mtype ); + + // Our monster is always a pet. + tmp.friendly = -1; + tmp.add_effect( effect_pet, 1_turns, num_bp, true ); + + if( pacified ) { + tmp.add_effect( effect_pacified, 1_turns, num_bp, true ); + } + + if( !name.empty() ) { + tmp.unique_name = name; + } + + if( const cata::optional pos = random_point( points, [&]( const tripoint & p ) { + return g->is_empty( p ) && tmp.can_move_to( p ); + } ) ) { + tmp.spawn( *pos ); + g->add_zombie( tmp ); + } else { + add_msg( m_debug, "Cannot place u_buy_monster, no valid placement locations." ); + } + } + + if( name.empty() ) { + popup( _( "%1$s gives you %2$d %3$s." ), p.name, count, mtype.obj().nname( count ) ); + } else { + popup( _( "%1$s gives you %2$s." ), p.name, name ); + } + }; +} + void talk_effect_t::set_effect_consequence( const talk_effect_fun_t &fun, dialogue_consequence con ) { effects.push_back( fun ); @@ -2293,6 +2343,13 @@ void talk_effect_t::parse_sub_effect( JsonObject jo ) subeffect_fun.set_npc_cbm_recharge_rule( setting ); } else if( jo.has_member( "mapgen_update" ) ) { subeffect_fun.set_mapgen_update( jo, "mapgen_update" ); + } else if( jo.has_string( "u_buy_monster" ) ) { + const std::string &monster_type_id = jo.get_string( "u_buy_monster" ); + const int cost = jo.get_int( "cost", 0 ); + const int count = jo.get_int( "count", 1 ); + const bool pacified = jo.get_bool( "pacified", false ); + const std::string &name = jo.get_string( "name", "" ); + subeffect_fun.set_u_buy_monster( monster_type_id, cost, count, pacified, name ); } else { jo.throw_error( "invalid sub effect syntax :" + jo.str() ); } From 26806ba2fb03e93bc5fc46b35e8fba0a7dd10f08 Mon Sep 17 00:00:00 2001 From: Jason Jones Date: Thu, 22 Aug 2019 21:53:48 -0800 Subject: [PATCH 2/2] Update u_buy_monster name to be translatable --- src/dialogue.h | 2 +- src/npctalk.cpp | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/dialogue.h b/src/dialogue.h index 82d860c709c13..f27e65cda9050 100644 --- a/src/dialogue.h +++ b/src/dialogue.h @@ -122,7 +122,7 @@ struct talk_effect_fun_t { void set_npc_gets_item( bool to_use ); void set_add_mission( std::string mission_id ); void set_u_buy_monster( const std::string &monster_id, int cost, int count, bool pacified, - const std::string &name ); + const translation &name ); void operator()( const dialogue &d ) const { if( !function ) { diff --git a/src/npctalk.cpp b/src/npctalk.cpp index c5b872c66c6bf..d7e15146d5048 100644 --- a/src/npctalk.cpp +++ b/src/npctalk.cpp @@ -2099,7 +2099,7 @@ void talk_effect_fun_t::set_add_mission( const std::string mission_id ) } void talk_effect_fun_t::set_u_buy_monster( const std::string &monster_type_id, int cost, int count, - bool pacified, const std::string &name ) + bool pacified, const translation &name ) { function = [monster_type_id, cost, count, pacified, name]( const dialogue & d ) { npc &p = *d.beta; @@ -2126,7 +2126,7 @@ void talk_effect_fun_t::set_u_buy_monster( const std::string &monster_type_id, i } if( !name.empty() ) { - tmp.unique_name = name; + tmp.unique_name = name.translated(); } if( const cata::optional pos = random_point( points, [&]( const tripoint & p ) { @@ -2348,7 +2348,8 @@ void talk_effect_t::parse_sub_effect( JsonObject jo ) const int cost = jo.get_int( "cost", 0 ); const int count = jo.get_int( "count", 1 ); const bool pacified = jo.get_bool( "pacified", false ); - const std::string &name = jo.get_string( "name", "" ); + translation name; + jo.read( "name", name ); subeffect_fun.set_u_buy_monster( monster_type_id, cost, count, pacified, name ); } else { jo.throw_error( "invalid sub effect syntax :" + jo.str() );