diff --git a/src/item.cpp b/src/item.cpp index 608908db99e1f..113c79b5ab9a1 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -6352,31 +6352,7 @@ int item::price( bool practical ) const int res = 0; visit_items( [&res, practical]( const item * e, item * ) { - if( e->rotten() ) { - // TODO: Special case things that stay useful when rotten - return VisitResponse::NEXT; - } - - int child = units::to_cent( practical ? e->type->price_post : e->type->price ); - if( e->damage() > 0 ) { - // maximal damage level is 4, maximal reduction is 40% of the value. - child -= child * static_cast( e->damage_level() ) / 10; - } - - if( e->count_by_charges() || e->made_of( phase_id::LIQUID ) ) { - // price from json data is for default-sized stack - child *= e->charges / static_cast( e->type->stack_size ); - - } else if( e->magazine_integral() && e->ammo_remaining() && e->ammo_data() ) { - // items with integral magazines may contain ammunition which can affect the price - child += item( e->ammo_data(), calendar::turn, e->ammo_remaining() ).price( practical ); - - } else if( e->is_tool() && e->type->tool->max_charges != 0 ) { - // if tool has no ammo (e.g. spray can) reduce price proportional to remaining charges - child *= e->ammo_remaining() / static_cast( std::max( e->type->charges_default(), 1 ) ); - } - - res += child; + res += e->price_no_contents( practical ); return VisitResponse::NEXT; } ); @@ -6390,8 +6366,12 @@ int item::price_no_contents( bool practical ) const } int price = units::to_cent( practical ? type->price_post : type->price ); if( damage() > 0 ) { - // maximal damage level is 4, maximal reduction is 40% of the value. - price -= price * static_cast< double >( damage_level() ) / 10; + // maximal damage level is 4, maximal reduction is 80% of the value. + price -= price * static_cast< double >( damage_level() ) / 5; + } + + if( is_filthy() ) { + price *= 0.8; } if( count_by_charges() || made_of( phase_id::LIQUID ) ) { diff --git a/src/npc.cpp b/src/npc.cpp index 290133be9fa9b..6968a65dcc8b1 100644 --- a/src/npc.cpp +++ b/src/npc.cpp @@ -54,6 +54,7 @@ #include "mtype.h" #include "mutation.h" #include "npc_class.h" +#include "npctrade.h" #include "npctrade_utils.h" #include "npctalk.h" #include "options.h" @@ -148,6 +149,7 @@ static const trait_id trait_MUTE( "MUTE" ); static const trait_id trait_PROF_DICEMASTER( "PROF_DICEMASTER" ); static const trait_id trait_PSYCHOPATH( "PSYCHOPATH" ); static const trait_id trait_SAPIOVORE( "SAPIOVORE" ); +static const trait_id trait_SQUEAMISH( "SQUEAMISH" ); static const trait_id trait_TERRIFYING( "TERRIFYING" ); class monfaction; @@ -1952,12 +1954,13 @@ bool npc::wants_to_buy( const item &it, int at_price, int /*market_price*/ ) con return true; } - if( it.has_flag( flag_TRADER_AVOID ) ) { + if( it.has_flag( flag_TRADER_AVOID ) or it.has_var( VAR_TRADE_IGNORE ) or + ( my_fac == nullptr and has_trait( trait_SQUEAMISH ) and it.is_filthy() ) ) { return false; } // TODO: Base on inventory - return at_price > 0; + return at_price >= 0; } // Will the NPC freely exchange items with the player? diff --git a/src/npctrade.cpp b/src/npctrade.cpp index 515a67799ead0..0d6e1defc2ed5 100644 --- a/src/npctrade.cpp +++ b/src/npctrade.cpp @@ -146,7 +146,7 @@ double npc_trading::net_price_adjustment( const Character &buyer, const Characte double adjust = 0.05 * ( seller.int_cur - buyer.int_cur ) + price_adjustment( seller.get_skill_level( skill_speech ) - buyer.get_skill_level( skill_speech ) ); - return std::max( adjust, 1.0 ); + return seller.is_npc() ? adjust : -1 / adjust; } int npc_trading::bionic_install_price( Character &installer, Character &patient, @@ -166,8 +166,7 @@ int npc_trading::adjusted_price( item const *it, int amount, Character const &bu int price = it->price_no_contents( true ); if( it->count_by_charges() and amount >= 0 ) { - price /= it->charges; - price *= amount; + price *= static_cast( amount ) / it->charges; } if( buyer.is_npc() ) { price = buyer.as_npc()->value( *it, price ); @@ -176,7 +175,7 @@ int npc_trading::adjusted_price( item const *it, int amount, Character const &bu } if( fac == nullptr || fac->currency != it->typeId() ) { - return static_cast( price * adjust ); + return static_cast( price * ( 1 + 0.25 * adjust ) ); } return price; diff --git a/src/skill.cpp b/src/skill.cpp index ec4d79fbbf220..43e397ec76945 100644 --- a/src/skill.cpp +++ b/src/skill.cpp @@ -585,23 +585,7 @@ bool SkillLevelMap::has_same_levels_as( const SkillLevelMap &other ) const // Caps at 200% when you are 5 levels ahead, int comparison is handled in npctalk.cpp double price_adjustment( int barter_skill ) { - if( barter_skill <= 0 ) { - return 1.0; - } - if( barter_skill >= 5 ) { - return 2.0; - } - switch( barter_skill ) { - case 1: - return 1.05; - case 2: - return 1.15; - case 3: - return 1.30; - case 4: - return 1.65; - default: - // Should never occur - return 1.0; - } + int const skill = std::min( 5, std::abs( barter_skill ) ); + double const val = 0.045 * std::pow( skill, 2 ) - 0.025 * skill + 1; + return barter_skill >= 0 ? val : 1 / val; }