Merge branch 'crabman/loot-protection-fix' into 'master'

Fix loot protection bugs

See merge request veloren/veloren!4437
This commit is contained in:
crabman 2024-04-20 09:52:06 +00:00
commit 52a9cac813
4 changed files with 19 additions and 8 deletions

View File

@ -27,9 +27,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Removed ### Removed
### Fixed ### Fixed
- NPC path-finding, especially for merchants and travellers is now less dumb.
- NPC path-finding, especially for merchants and travellers is now less dumb.
- Moderate buff to wild large bipeds, to bring in line with other balancing - Moderate buff to wild large bipeds, to bring in line with other balancing
- Loot protection for solo players and NPCs works again
## [0.16.0] - 2024-03-30 ## [0.16.0] - 2024-03-30

View File

@ -532,3 +532,9 @@ impl GroupManager {
}); });
} }
} }
impl Group {
/// Returns whether this is one of the special npc or enemy groups
// FIXME: These groups are a HACK
pub fn is_special(&self) -> bool { *self == NPC || *self == ENEMY }
}

View File

@ -592,13 +592,11 @@ impl ServerEvent for DestroyEvent {
false false
} else { } else {
if let Some((_agent, uid, pos, alignment, vel, body)) = ( if let Some((_agent, pos, alignment, vel)) = (
&data.agents, &data.agents,
&data.uids,
&data.positions, &data.positions,
data.alignments.maybe(), data.alignments.maybe(),
data.velocities.maybe(), data.velocities.maybe(),
data.bodies.maybe(),
) )
.lend_join() .lend_join()
.get(ev.entity, &data.entities) .get(ev.entity, &data.entities)
@ -614,16 +612,16 @@ impl ServerEvent for DestroyEvent {
// Remove entries where zero exp was awarded - this happens because some // Remove entries where zero exp was awarded - this happens because some
// entities like Object bodies don't give EXP. // entities like Object bodies don't give EXP.
let mut item_receivers = HashMap::new(); let mut item_receivers = HashMap::new();
for (_entity, exp, group) in exp_awards { for (entity, exp, group) in exp_awards {
if exp >= f32::EPSILON { if exp >= f32::EPSILON {
let loot_owner = if let Some(group) = group { let loot_owner = if let Some(group) = group {
Some(LootOwnerKind::Group(group)) Some(LootOwnerKind::Group(group))
} else { } else {
let uid = body.and_then(|body| { let uid = data.bodies.get(entity).and_then(|body| {
// Only humanoids are awarded loot ownership - if the winner // Only humanoids are awarded loot ownership - if the winner
// was a non-humanoid NPC the loot will be free-for-all // was a non-humanoid NPC the loot will be free-for-all
if matches!(body, Body::Humanoid(_)) { if matches!(body, Body::Humanoid(_)) {
Some(*uid) data.uids.get(entity).copied()
} else { } else {
None None
} }
@ -655,12 +653,14 @@ impl ServerEvent for DestroyEvent {
); );
Some(LootOwner::new(loot_owner, false)) Some(LootOwner::new(loot_owner, false))
} else { } else {
debug!("No loot owner");
None None
}, },
}) })
}; };
if item_receivers.is_empty() { if item_receivers.is_empty() {
debug!("No item receivers");
for item in flatten_counted_items(&items, &data.ability_map, &data.msm) for item in flatten_counted_items(&items, &data.ability_map, &data.msm)
{ {
spawn_item(item, None) spawn_item(item, None)

View File

@ -35,7 +35,11 @@ impl<'a> System<'a> for Sys {
LootOwnerKind::Player(uid) => id_maps LootOwnerKind::Player(uid) => id_maps
.uid_entity(uid) .uid_entity(uid)
.map_or(true, |entity| !entities.is_alive(entity)), .map_or(true, |entity| !entities.is_alive(entity)),
LootOwnerKind::Group(group) => group_manager.group_info(group).is_none(), LootOwnerKind::Group(group) => {
// Special alignment groups (NPC and ENEMY) aren't tracked by the group
// manager, check them separately here
!group.is_special() && group_manager.group_info(group).is_none()
},
} }
}) })
.map(|(entity, _)| entity) .map(|(entity, _)| entity)