From 8ba68e30f313fa5f9fac0540e62670d1c3f7c2cc Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 1 Apr 2023 01:25:35 +0100 Subject: [PATCH] Merchants no longer buy/sell things they don't know the price of --- common/src/trade.rs | 23 ++-- .../sys/agent/behavior_tree/interaction.rs | 121 +++++++++++------- 2 files changed, 86 insertions(+), 58 deletions(-) diff --git a/common/src/trade.rs b/common/src/trade.rs index 496c05358e..a3408d09a2 100644 --- a/common/src/trade.rs +++ b/common/src/trade.rs @@ -381,15 +381,16 @@ impl SitePrices { inventories: &[Option; 2], who: usize, reduce: bool, - ) -> f32 { + ) -> Option { offers[who] .iter() .map(|(slot, amount)| { inventories[who] .as_ref() - .and_then(|ri| { - ri.inventory.get(slot).map(|item| { - if let Some(vec) = TradePricing::get_materials(&item.name.as_ref()) { + .map(|ri| { + let item = ri.inventory.get(slot)?; + if let Some(vec) = TradePricing::get_materials(&item.name.as_ref()) { + Some( vec.iter() .map(|(amount2, material)| { self.values.get(material).copied().unwrap_or_default() @@ -397,15 +398,15 @@ impl SitePrices { * (if reduce { material.trade_margin() } else { 1.0 }) }) .sum::() - * (*amount as f32) - } else { - 0.0 - } - }) + * (*amount as f32), + ) + } else { + None + } }) - .unwrap_or_default() + .unwrap_or(Some(0.0)) }) - .sum() + .try_fold(0.0, |a, p| Some(a + p?)) } } diff --git a/server/src/sys/agent/behavior_tree/interaction.rs b/server/src/sys/agent/behavior_tree/interaction.rs index f477037ff0..a64ff80afa 100644 --- a/server/src/sys/agent/behavior_tree/interaction.rs +++ b/server/src/sys/agent/behavior_tree/interaction.rs @@ -524,57 +524,84 @@ pub fn handle_inbox_update_pending_trade(bdata: &mut BehaviorData) -> bool { let who = usize::from(!agent.behavior.is(BehaviorState::TRADING_ISSUER)); match agent.behavior.trading_behavior { TradingBehavior::RequireBalanced { .. } => { - let balance0: f32 = - prices.balance(&pending.offers, &inventories, 1 - who, true); - let balance1: f32 = prices.balance(&pending.offers, &inventories, who, false); - if balance0 >= balance1 { - // If the trade is favourable to us, only send an accept message if we're - // not already accepting (since otherwise, spam-clicking the accept button - // results in lagging and moving to the review phase of an unfavorable trade - // (although since the phase is included in the message, this shouldn't - // result in fully accepting an unfavourable trade)) - if !pending.accept_flags[who] && !pending.is_empty_trade() { - event_emitter.emit(ServerEvent::ProcessTradeAction( - *agent_data.entity, - tradeid, - TradeAction::Accept(pending.phase), - )); - tracing::trace!(?tradeid, ?balance0, ?balance1, "Accept Pending Trade"); - } - } else { - if balance1 > 0.0 { - let msg = format!( - "That only covers {:.0}% of my costs!", - (balance0 / balance1 * 100.0).floor() - ); - if let Some(tgt_data) = &agent.target { - // If talking with someone in particular, "tell" it only to them - if let Some(with) = read_data.uids.get(tgt_data.target) { - event_emitter.emit(ServerEvent::Chat( - UnresolvedChatMsg::npc_tell(*agent_data.uid, *with, msg), - )); - } else { - event_emitter.emit(ServerEvent::Chat( - UnresolvedChatMsg::npc_say(*agent_data.uid, msg), + let balance0 = prices.balance(&pending.offers, &inventories, 1 - who, true); + let balance1 = prices.balance(&pending.offers, &inventories, who, false); + match (balance0, balance1) { + (_, None) => { + event_emitter.emit(ServerEvent::Chat(UnresolvedChatMsg::npc_say( + *agent_data.uid, + format!("I'm not willing to sell that item"), + ))) + }, + (None, _) => { + event_emitter.emit(ServerEvent::Chat(UnresolvedChatMsg::npc_say( + *agent_data.uid, + format!("I'm not willing to buy that item"), + ))) + }, + (Some(balance0), Some(balance1)) => { + if balance0 >= balance1 { + // If the trade is favourable to us, only send an accept message if + // we're not already accepting + // (since otherwise, spam-clicking the accept button + // results in lagging and moving to the review phase of an + // unfavorable trade (although since + // the phase is included in the message, this shouldn't + // result in fully accepting an unfavourable trade)) + if !pending.accept_flags[who] && !pending.is_empty_trade() { + event_emitter.emit(ServerEvent::ProcessTradeAction( + *agent_data.entity, + tradeid, + TradeAction::Accept(pending.phase), )); + tracing::trace!( + ?tradeid, + ?balance0, + ?balance1, + "Accept Pending Trade" + ); } } else { - event_emitter.emit(ServerEvent::Chat(UnresolvedChatMsg::npc_say( - *agent_data.uid, - msg, - ))); + if balance1 > 0.0 { + let msg = format!( + "That only covers {:.0}% of my costs!", + (balance0 / balance1 * 100.0).floor() + ); + if let Some(tgt_data) = &agent.target { + // If talking with someone in particular, "tell" it only to + // them + if let Some(with) = read_data.uids.get(tgt_data.target) { + event_emitter.emit(ServerEvent::Chat( + UnresolvedChatMsg::npc_tell( + *agent_data.uid, + *with, + msg, + ), + )); + } else { + event_emitter.emit(ServerEvent::Chat( + UnresolvedChatMsg::npc_say(*agent_data.uid, msg), + )); + } + } else { + event_emitter.emit(ServerEvent::Chat( + UnresolvedChatMsg::npc_say(*agent_data.uid, msg), + )); + } + } + if pending.phase != TradePhase::Mutate { + // we got into the review phase but without balanced goods, + // decline + agent.behavior.unset(BehaviorState::TRADING); + agent.target = None; + event_emitter.emit(ServerEvent::ProcessTradeAction( + *agent_data.entity, + tradeid, + TradeAction::Decline, + )); + } } - } - if pending.phase != TradePhase::Mutate { - // we got into the review phase but without balanced goods, decline - agent.behavior.unset(BehaviorState::TRADING); - agent.target = None; - event_emitter.emit(ServerEvent::ProcessTradeAction( - *agent_data.entity, - tradeid, - TradeAction::Decline, - )); - } + }, } }, TradingBehavior::AcceptFood => {