Soft loot protection

This commit is contained in:
Maxicarlos08 2023-08-22 14:41:09 +02:00
parent 256b3d1e16
commit dccbfc4595
No known key found for this signature in database
6 changed files with 35 additions and 17 deletions

View File

@ -61,6 +61,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Location names are displayed in character selection dialog - Location names are displayed in character selection dialog
- You can no longer write messages to old groups after being kicked and not having updated your chat mode. - You can no longer write messages to old groups after being kicked and not having updated your chat mode.
- Location names are now also correct after editing and creating characters - Location names are now also correct after editing and creating characters
- NPC's wont pick up recently dropped items (if not hostile towards you)
## [0.15.0] - 2023-07-01 ## [0.15.0] - 2023-07-01

View File

@ -15,16 +15,21 @@ pub struct LootOwner {
#[serde(skip, default = "Instant::now")] #[serde(skip, default = "Instant::now")]
expiry: Instant, expiry: Instant,
owner: LootOwnerKind, owner: LootOwnerKind,
/// This field stands as a wish for NPC's to not pick the loot up, they will
/// however be able to decide whether they want to follow your wishes or not
/// (players will be able to picke the item up)
soft: bool,
} }
// Loot becomes free-for-all after the initial ownership period // Loot becomes free-for-all after the initial ownership period
const OWNERSHIP_SECS: u64 = 45; const OWNERSHIP_SECS: u64 = 45;
impl LootOwner { impl LootOwner {
pub fn new(kind: LootOwnerKind) -> Self { pub fn new(kind: LootOwnerKind, soft: bool) -> Self {
Self { Self {
expiry: Instant::now().add(Duration::from_secs(OWNERSHIP_SECS)), expiry: Instant::now().add(Duration::from_secs(OWNERSHIP_SECS)),
owner: kind, owner: kind,
soft,
} }
} }
@ -43,6 +48,8 @@ impl LootOwner {
pub fn default_instant() -> Instant { Instant::now() } pub fn default_instant() -> Instant { Instant::now() }
pub fn is_soft(&self) -> bool { self.soft }
pub fn can_pickup( pub fn can_pickup(
&self, &self,
uid: Uid, uid: Uid,
@ -66,7 +73,7 @@ impl LootOwner {
// Pet's can't pick up owned loot // Pet's can't pick up owned loot
// Humanoids must own the loot // Humanoids must own the loot
// Non-humanoids ignore loot ownership // Non-humanoids ignore loot ownership
!is_pet && (owns_loot || !is_humanoid) !is_pet && (self.soft || owns_loot || !is_humanoid)
} }
} }

View File

@ -822,10 +822,10 @@ impl<'a> AgentData<'a> {
}; };
let is_valid_target = |entity: EcsEntity| match read_data.bodies.get(entity) { let is_valid_target = |entity: EcsEntity| match read_data.bodies.get(entity) {
Some(Body::ItemDrop(item)) => { Some(Body::ItemDrop(item)) => {
//If the agent is humanoid, it will pick up all kinds of item drops. If the let is_humanoid = matches!(self.body, Some(Body::Humanoid(_)));
// If the agent is humanoid, it will pick up all kinds of item drops. If the
// agent isn't humanoid, it will pick up only consumable item drops. // agent isn't humanoid, it will pick up only consumable item drops.
let wants_pickup = matches!(self.body, Some(Body::Humanoid(_))) let wants_pickup = is_humanoid || matches!(item, item_drop::Body::Consumable);
|| matches!(item, item_drop::Body::Consumable);
// The agent will attempt to pickup the item if it wants to pick it up and // The agent will attempt to pickup the item if it wants to pick it up and
// is allowed to // is allowed to
@ -834,13 +834,20 @@ impl<'a> AgentData<'a> {
.loot_owners .loot_owners
.get(entity) .get(entity)
.map_or(true, |loot_owner| { .map_or(true, |loot_owner| {
loot_owner.can_pickup( !(is_humanoid
*self.uid, && loot_owner.is_soft()
read_data.groups.get(entity), // If we are hostile towards the owner, ignore their wish to not pick up the loot
self.alignment, && loot_owner
self.body, .uid()
None, .and_then(|uid| read_data.id_maps.uid_entity(uid))
) .map_or(true, |entity| !is_enemy(self, entity, read_data)))
&& loot_owner.can_pickup(
*self.uid,
read_data.groups.get(entity),
self.alignment,
self.body,
None,
)
}); });
if attempt_pickup { if attempt_pickup {

View File

@ -482,7 +482,7 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, last_change: Healt
item, item,
if let Some(loot_owner) = loot_owner { if let Some(loot_owner) = loot_owner {
debug!("Assigned UID {loot_owner:?} as the winner for the loot drop"); debug!("Assigned UID {loot_owner:?} as the winner for the loot drop");
Some(LootOwner::new(loot_owner)) Some(LootOwner::new(loot_owner, false))
} else { } else {
None None
}, },

View File

@ -356,7 +356,9 @@ pub fn handle_mine_block(
} }
} }
for item in items { for item in items {
let loot_owner = maybe_uid.map(LootOwnerKind::Player).map(LootOwner::new); let loot_owner = maybe_uid
.map(LootOwnerKind::Player)
.map(|owner| LootOwner::new(owner, false));
state.create_item_drop( state.create_item_drop(
Pos(pos.map(|e| e as f32) + Vec3::new(0.5, 0.5, 0.0)), Pos(pos.map(|e| e as f32) + Vec3::new(0.5, 0.5, 0.0)),
comp::Vel(Vec3::zero()), comp::Vel(Vec3::zero()),

View File

@ -9,8 +9,9 @@ use common::{
self, self,
group::members, group::members,
item::{self, flatten_counted_items, tool::AbilityMap, MaterialStatManifest}, item::{self, flatten_counted_items, tool::AbilityMap, MaterialStatManifest},
loot_owner::LootOwnerKind,
slot::{self, Slot}, slot::{self, Slot},
InventoryUpdate, InventoryUpdate, LootOwner,
}, },
consts::MAX_PICKUP_RANGE, consts::MAX_PICKUP_RANGE,
mounting::VolumePos, mounting::VolumePos,
@ -387,7 +388,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
), ),
comp::Vel(Vec3::zero()), comp::Vel(Vec3::zero()),
item, item,
None, Some(LootOwner::new(LootOwnerKind::Player(uid), false)),
); );
} }
}, },
@ -959,7 +960,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
comp::Pos(pos.0 + *ori.look_dir() + Vec3::unit_z()), comp::Pos(pos.0 + *ori.look_dir() + Vec3::unit_z()),
comp::Vel(Vec3::zero()), comp::Vel(Vec3::zero()),
item, item,
None, Some(LootOwner::new(LootOwnerKind::Player(uid), true)),
); );
} }