mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Made NPCs prefer food when idle
This commit is contained in:
@ -153,6 +153,19 @@ pub fn make_potion_bag(quantity: u32) -> Item {
|
|||||||
bag
|
bag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn make_food_bag(quantity: u32) -> Item {
|
||||||
|
let mut bag = Item::new_from_asset_expect("common.items.armor.misc.bag.tiny_leather_pouch");
|
||||||
|
if let Some(i) = bag.slots_mut().iter_mut().next() {
|
||||||
|
let mut food = Item::new_from_asset_expect("common.items.food.apple_stick");
|
||||||
|
if let Err(e) = food.set_amount(quantity) {
|
||||||
|
warn!("Failed to set food quantity: {:?}", e);
|
||||||
|
}
|
||||||
|
*i = Some(food);
|
||||||
|
}
|
||||||
|
bag
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
// We have many species so this function is long
|
// We have many species so this function is long
|
||||||
// Also we are using default tools for un-specified species so
|
// Also we are using default tools for un-specified species so
|
||||||
|
@ -116,7 +116,7 @@ impl Link for Mounting {
|
|||||||
.map(|p| p.0.map(|e| e.floor()))
|
.map(|p| p.0.map(|e| e.floor()))
|
||||||
.unwrap_or_else(|| terrain.find_space(old_pos).map(|e| e as f32))
|
.unwrap_or_else(|| terrain.find_space(old_pos).map(|e| e as f32))
|
||||||
+ Vec3::new(0.5, 0.5, 0.0);
|
+ Vec3::new(0.5, 0.5, 0.0);
|
||||||
force_update.insert(rider, comp::ForceUpdate);
|
let _ = force_update.insert(rider, comp::ForceUpdate);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1874,7 +1874,7 @@ fn resolve_e2e_collision(
|
|||||||
|
|
||||||
let diff = diff.normalized();
|
let diff = diff.normalized();
|
||||||
|
|
||||||
*vel_delta += Vec3::from(diff) * force * step_delta * vel.0.xy().try_normalized().map_or(1.0, |dir| diff.dot(-dir).max(0.0));
|
*vel_delta += Vec3::from(diff) * force * step_delta * vel.0.xy().try_normalized().map_or(1.0, |dir| diff.dot(-dir).max(0.025));
|
||||||
}
|
}
|
||||||
|
|
||||||
*collision_registered = true;
|
*collision_registered = true;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use common::{
|
use common::{
|
||||||
comp::inventory::{loadout_builder::make_potion_bag, slot::ArmorSlot},
|
comp::inventory::{loadout_builder::{make_potion_bag, make_food_bag}, slot::ArmorSlot},
|
||||||
resources::Time,
|
resources::Time,
|
||||||
rtsim::{Memory, MemoryItem},
|
rtsim::{Memory, MemoryItem},
|
||||||
store::Id,
|
store::Id,
|
||||||
@ -143,7 +143,9 @@ impl Entity {
|
|||||||
// give potions to traveler humanoids or return loadout as is otherwise
|
// give potions to traveler humanoids or return loadout as is otherwise
|
||||||
match (body, kind) {
|
match (body, kind) {
|
||||||
(comp::Body::Humanoid(_), RtSimEntityKind::Random) => {
|
(comp::Body::Humanoid(_), RtSimEntityKind::Random) => {
|
||||||
|l, _| l.bag(ArmorSlot::Bag1, Some(make_potion_bag(100)))
|
|l, _| l
|
||||||
|
.bag(ArmorSlot::Bag1, Some(make_potion_bag(100)))
|
||||||
|
.bag(ArmorSlot::Bag2, Some(make_food_bag(100)))
|
||||||
},
|
},
|
||||||
(_, RtSimEntityKind::Merchant) => {
|
(_, RtSimEntityKind::Merchant) => {
|
||||||
|l, trade| l.with_creator(world::site::settlement::merchant_loadout, trade)
|
|l, trade| l.with_creator(world::site::settlement::merchant_loadout, trade)
|
||||||
|
@ -176,6 +176,7 @@ const MAX_FLEE_DIST: f32 = 20.0;
|
|||||||
const AVG_FOLLOW_DIST: f32 = 6.0;
|
const AVG_FOLLOW_DIST: f32 = 6.0;
|
||||||
const RETARGETING_THRESHOLD_SECONDS: f64 = 10.0;
|
const RETARGETING_THRESHOLD_SECONDS: f64 = 10.0;
|
||||||
const HEALING_ITEM_THRESHOLD: f32 = 0.5;
|
const HEALING_ITEM_THRESHOLD: f32 = 0.5;
|
||||||
|
const IDLE_HEALING_ITEM_THRESHOLD: f32 = 0.999;
|
||||||
const DEFAULT_ATTACK_RANGE: f32 = 2.0;
|
const DEFAULT_ATTACK_RANGE: f32 = 2.0;
|
||||||
const AWARENESS_INVESTIGATE_THRESHOLD: f32 = 1.0;
|
const AWARENESS_INVESTIGATE_THRESHOLD: f32 = 1.0;
|
||||||
const AWARENESS_DECREMENT_CONSTANT: f32 = 0.07;
|
const AWARENESS_DECREMENT_CONSTANT: f32 = 0.07;
|
||||||
@ -671,7 +672,7 @@ impl<'a> AgentData<'a> {
|
|||||||
read_data: &ReadData,
|
read_data: &ReadData,
|
||||||
event_emitter: &mut Emitter<'_, ServerEvent>,
|
event_emitter: &mut Emitter<'_, ServerEvent>,
|
||||||
) {
|
) {
|
||||||
if self.damage < HEALING_ITEM_THRESHOLD && self.heal_self(agent, controller) {
|
if self.damage < HEALING_ITEM_THRESHOLD && self.heal_self(agent, controller, false) {
|
||||||
agent.action_state.timer = 0.01;
|
agent.action_state.timer = 0.01;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -809,7 +810,7 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.damage < HEALING_ITEM_THRESHOLD && self.heal_self(agent, controller) {
|
if self.damage < IDLE_HEALING_ITEM_THRESHOLD && self.heal_self(agent, controller, true) {
|
||||||
agent.action_state.timer = 0.01;
|
agent.action_state.timer = 0.01;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1427,30 +1428,32 @@ impl<'a> AgentData<'a> {
|
|||||||
|
|
||||||
/// Attempt to consume a healing item, and return whether any healing items
|
/// Attempt to consume a healing item, and return whether any healing items
|
||||||
/// were queued. Callers should use this to implement a delay so that
|
/// were queued. Callers should use this to implement a delay so that
|
||||||
/// the healing isn't interrupted.
|
/// the healing isn't interrupted. If `relaxed` is `true`, we allow eating food and prioritise healing.
|
||||||
fn heal_self(&self, _agent: &mut Agent, controller: &mut Controller) -> bool {
|
fn heal_self(&self, _agent: &mut Agent, controller: &mut Controller, relaxed: bool) -> bool {
|
||||||
let healing_value = |item: &Item| {
|
let healing_value = |item: &Item| {
|
||||||
let mut value = 0.0;
|
let mut value = 0.0;
|
||||||
|
|
||||||
if let ItemKind::Consumable {
|
if let ItemKind::Consumable {
|
||||||
kind: ConsumableKind::Drink,
|
kind,
|
||||||
effects,
|
effects,
|
||||||
..
|
..
|
||||||
} = &item.kind
|
} = &item.kind
|
||||||
{
|
{
|
||||||
for effect in effects.iter() {
|
if matches!(kind, ConsumableKind::Drink) || (relaxed && matches!(kind, ConsumableKind::Food)) {
|
||||||
use BuffKind::*;
|
for effect in effects.iter() {
|
||||||
match effect {
|
use BuffKind::*;
|
||||||
Effect::Health(HealthChange { amount, .. }) => {
|
match effect {
|
||||||
value += *amount;
|
Effect::Health(HealthChange { amount, .. }) => {
|
||||||
},
|
value += *amount;
|
||||||
Effect::Buff(BuffEffect { kind, data, .. })
|
},
|
||||||
if matches!(kind, Regeneration | Saturation | Potion) =>
|
Effect::Buff(BuffEffect { kind, data, .. })
|
||||||
{
|
if matches!(kind, Regeneration | Saturation | Potion) =>
|
||||||
value +=
|
{
|
||||||
data.strength * data.duration.map_or(0.0, |d| d.as_secs() as f32);
|
value +=
|
||||||
},
|
data.strength * data.duration.map_or(0.0, |d| d.as_secs() as f32);
|
||||||
_ => {},
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1466,7 +1469,11 @@ impl<'a> AgentData<'a> {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
consumables.sort_by_key(|(_, item)| healing_value(item));
|
consumables.sort_by_key(|(_, item)| if relaxed {
|
||||||
|
-healing_value(item)
|
||||||
|
} else {
|
||||||
|
healing_value(item)
|
||||||
|
});
|
||||||
|
|
||||||
if let Some((id, _)) = consumables.last() {
|
if let Some((id, _)) = consumables.last() {
|
||||||
use comp::inventory::slot::Slot;
|
use comp::inventory::slot::Slot;
|
||||||
|
Reference in New Issue
Block a user