diff --git a/src/item.cpp b/src/item.cpp index 7c2d5fb4016a9..829ff2995d206 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -6398,31 +6398,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; } ); @@ -6436,8 +6412,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.5; } if( count_by_charges() || made_of( phase_id::LIQUID ) ) { @@ -6453,7 +6433,6 @@ int item::price_no_contents( bool practical ) const price *= ammo_remaining() / static_cast< double >( std::max( type->charges_default(), 1 ) ); } - return price; } diff --git a/src/npc.cpp b/src/npc.cpp index 290133be9fa9b..5cecb01f4b599 100644 --- a/src/npc.cpp +++ b/src/npc.cpp @@ -1937,6 +1937,7 @@ bool npc::wants_to_sell( const item &it, int at_price, int /*market_price*/ ) co } // TODO: Base on inventory + // why should he sell things for free? return at_price >= 0; } @@ -1956,8 +1957,9 @@ bool npc::wants_to_buy( const item &it, int at_price, int /*market_price*/ ) con return false; } + // Item sale refusal if worthless // TODO: Base on inventory - return at_price > 0; + return at_price > 1; } // Will the NPC freely exchange items with the player? @@ -2143,12 +2145,7 @@ int npc::value( const item &it, int market_price ) const { if( it.is_dangerous() || ( it.has_flag( flag_BOMB ) && it.active ) ) { // NPCs won't be interested in buying active explosives - return -1000; - } - if( mission == NPC_MISSION_SHOPKEEP || - // faction currency trades at market price - ( my_fac != nullptr && my_fac->currency == it.typeId() ) ) { - return market_price; + return -1; } const item weapon = get_wielded_item(); diff --git a/src/npctrade.cpp b/src/npctrade.cpp index 515a67799ead0..28bf638a06966 100644 --- a/src/npctrade.cpp +++ b/src/npctrade.cpp @@ -26,6 +26,7 @@ static const flag_id json_flag_NO_UNWIELD( "NO_UNWIELD" ); static const skill_id skill_speech( "speech" ); +static const item_category_id item_category_currency( "currency" ); std::list npc_trading::transfer_items( trade_selector::select_t &stuff, Character &giver, Character &receiver, std::list &from_map, bool use_escrow ) @@ -135,18 +136,20 @@ std::vector npc_trading::init_selling( npc &np ) double npc_trading::net_price_adjustment( const Character &buyer, const Character &seller ) { // Adjust the prices based on your social skill. - // cap adjustment so nothing is ever sold below value - ///\EFFECT_INT_NPC slightly increases bartering price changes, relative to your INT + // cap adjustment so npc/player pricing never matches + // Boost the NPC selling/buying power - ///\EFFECT_BARTER_NPC increases bartering price changes, relative to your BARTER - - ///\EFFECT_INT slightly increases bartering price changes, relative to NPC INT - - ///\EFFECT_BARTER increases bartering price changes, relative to NPC BARTER - 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 ); + double selladjust = 0.05; + if( seller.is_npc() ) { + selladjust = 0.15; + } + double adjust = ( ( selladjust * seller.int_cur ) - ( 0.05 * buyer.int_cur ) ) + + price_adjustment( seller.get_skill_level( skill_speech ) - buyer.get_skill_level( skill_speech ) ); + if( seller.is_npc() ) { + return clamp( adjust, 1.6, 2.2 ); + } else { + return clamp( adjust, 0.5, 1.4 ); + } } int npc_trading::bionic_install_price( Character &installer, Character &patient, @@ -175,11 +178,16 @@ int npc_trading::adjusted_price( item const *it, int amount, Character const &bu price = seller.as_npc()->value( *it, price ); } - if( fac == nullptr || fac->currency != it->typeId() ) { + if( fac == nullptr ) { return static_cast( price * adjust ); + // check currency id matches faction currency + } else if( it->get_category_shallow().get_id() == item_category_currency ) { + std::string itemid_str = it->typeId().str(); + if( itemid_str.find( fac->currency.str() ) != std::string::npos ) { + return price; + } } - - return price; + return static_cast( price * adjust ); } int npc_trading::trading_price( Character const &buyer, Character const &seller, @@ -202,6 +210,14 @@ int npc_trading::trading_price( Character const &buyer, Character const &seller, return VisitResponse::SKIP; } } + // Prevent free items + if( price < 1 ) { + if( e->count_by_charges() ) { + ret = 1 * amount; + } else { + ret = 1; + } + } ret += price; return VisitResponse::NEXT; } );