mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Soft loot protection
This commit is contained in:
parent
256b3d1e16
commit
dccbfc4595
@ -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
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
},
|
||||
|
@ -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()),
|
||||
|
@ -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)),
|
||||
);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user