Made NPC sentiment slightly more forgiving

This commit is contained in:
Joshua Barretto 2023-05-01 12:16:40 +01:00
parent 7643147dc2
commit ba8984e1a7
2 changed files with 36 additions and 10 deletions

View File

@ -56,15 +56,13 @@ pub struct Sentiments {
impl Sentiments {
/// Return the sentiment that is felt toward the given target.
pub fn toward(&self, target: impl Into<Target>) -> Sentiment {
self.map.get(&target.into()).copied().unwrap_or_default()
pub fn toward(&self, target: impl Into<Target>) -> &Sentiment {
self.map.get(&target.into()).unwrap_or(&Sentiment::DEFAULT)
}
/// Change the sentiment toward the given target by the given amount,
/// capping out at the given value.
pub fn change_by(&mut self, target: impl Into<Target>, change: f32, cap: f32) {
let target = target.into();
self.map.entry(target).or_default().change_by(change, cap);
/// Return the sentiment that is felt toward the given target.
pub fn toward_mut(&mut self, target: impl Into<Target>) -> &mut Sentiment {
self.map.entry(target.into()).or_default()
}
/// Progressively decay the sentiment back to a neutral sentiment.
@ -134,6 +132,7 @@ impl Sentiment {
/// Substantial positive sentiments: NPC may go out of their way to help
/// actors associated with the target, greet them, etc.
pub const ALLY: f32 = 0.3;
const DEFAULT: Self = Self { positivity: 0 };
/// Very negative sentiments: NPC may confront the actor, get aggressive
/// with them, or even use force against them.
pub const ENEMY: f32 = -0.6;
@ -150,7 +149,7 @@ impl Sentiment {
/// Minor positive sentiments: NPC might be more willing to provide
/// information, give better trade deals, etc.
pub const POSITIVE: f32 = 0.1;
/// Substantial positive sentiments: NPC may reject attempts to trade or
/// Substantial negative sentiments: NPC may reject attempts to trade or
/// avoid actors associated with the target, insult them, but will not
/// use physical force.
pub const RIVAL: f32 = -0.3;
@ -161,7 +160,9 @@ impl Sentiment {
fn value(&self) -> f32 { self.positivity as f32 * (1.0 / 126.0) }
fn change_by(&mut self, change: f32, cap: f32) {
/// Change the sentiment toward the given target by the given amount,
/// capping out at the given value.
pub fn change_by(&mut self, change: f32, cap: f32) {
// There's a bit of ceremony here for two reasons:
// 1) Very small changes should not be rounded to 0
// 2) Sentiment should never (over/under)flow
@ -176,6 +177,21 @@ impl Sentiment {
}
}
/// Limit the sentiment to the given value, either positive or negative. The
/// resulting sentiment is guaranteed to be less than the cap (at least,
/// as judged by [`Sentiment::is`]).
pub fn limit_below(&mut self, cap: f32) {
if cap > 0.0 {
self.positivity = self
.positivity
.min(((cap.min(1.0) * 126.0) as i8 - 1).max(0));
} else {
self.positivity = self
.positivity
.max(((-cap.max(-1.0) * 126.0) as i8 + 1).min(0));
}
}
fn decay(&mut self, rng: &mut impl Rng, dt: f32) {
if self.positivity != 0 {
// TODO: Find a slightly nicer way to have sentiment decay, perhaps even by

View File

@ -972,7 +972,17 @@ fn check_inbox(ctx: &mut NpcCtx) -> Option<impl Action> {
// killed.
change *= -1.0;
}
ctx.sentiments.change_by(killer, change, Sentiment::VILLAIN);
ctx.sentiments
.toward_mut(killer)
.change_by(change, Sentiment::VILLAIN);
}
// This is a murder of a player. Feel bad for the player and stop
// attacking them.
if let Actor::Character(_) = actor {
ctx.sentiments
.toward_mut(actor)
.limit_below(Sentiment::ENEMY)
}
if ctx.sentiments.toward(actor).is(Sentiment::ENEMY) {