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
- 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
- NPC's wont pick up recently dropped items (if not hostile towards you)
## [0.15.0] - 2023-07-01

View File

@ -15,16 +15,21 @@ pub struct LootOwner {
#[serde(skip, default = "Instant::now")]
expiry: Instant,
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
const OWNERSHIP_SECS: u64 = 45;
impl LootOwner {
pub fn new(kind: LootOwnerKind) -> Self {
pub fn new(kind: LootOwnerKind, soft: bool) -> Self {
Self {
expiry: Instant::now().add(Duration::from_secs(OWNERSHIP_SECS)),
owner: kind,
soft,
}
}
@ -43,6 +48,8 @@ impl LootOwner {
pub fn default_instant() -> Instant { Instant::now() }
pub fn is_soft(&self) -> bool { self.soft }
pub fn can_pickup(
&self,
uid: Uid,
@ -66,7 +73,7 @@ impl LootOwner {
// Pet's can't pick up owned loot
// Humanoids must own the loot
// 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) {
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.
let wants_pickup = matches!(self.body, Some(Body::Humanoid(_)))
|| matches!(item, item_drop::Body::Consumable);
let wants_pickup = is_humanoid || matches!(item, item_drop::Body::Consumable);
// The agent will attempt to pickup the item if it wants to pick it up and
// is allowed to
@ -834,13 +834,20 @@ impl<'a> AgentData<'a> {
.loot_owners
.get(entity)
.map_or(true, |loot_owner| {
loot_owner.can_pickup(
*self.uid,
read_data.groups.get(entity),
self.alignment,
self.body,
None,
)
!(is_humanoid
&& loot_owner.is_soft()
// If we are hostile towards the owner, ignore their wish to not pick up the loot
&& loot_owner
.uid()
.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 {

View File

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

View File

@ -356,7 +356,9 @@ pub fn handle_mine_block(
}
}
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(
Pos(pos.map(|e| e as f32) + Vec3::new(0.5, 0.5, 0.0)),
comp::Vel(Vec3::zero()),

View File

@ -9,8 +9,9 @@ use common::{
self,
group::members,
item::{self, flatten_counted_items, tool::AbilityMap, MaterialStatManifest},
loot_owner::LootOwnerKind,
slot::{self, Slot},
InventoryUpdate,
InventoryUpdate, LootOwner,
},
consts::MAX_PICKUP_RANGE,
mounting::VolumePos,
@ -387,7 +388,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
),
comp::Vel(Vec3::zero()),
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::Vel(Vec3::zero()),
item,
None,
Some(LootOwner::new(LootOwnerKind::Player(uid), true)),
);
}