mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Don't give exp when killing self or group members
This commit is contained in:
parent
1d69e85a50
commit
ecf6a84b2f
@ -55,56 +55,72 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
|
||||
state.notify_registered_clients(comp::ChatType::Kill.server_msg(msg));
|
||||
}
|
||||
|
||||
{
|
||||
// Give EXP to the killer if entity had stats
|
||||
// Give EXP to the killer if entity had stats
|
||||
(|| {
|
||||
let mut stats = state.ecs().write_storage::<Stats>();
|
||||
if let Some(entity_stats) = stats.get(entity).cloned() {
|
||||
if let HealthSource::Attack { by } | HealthSource::Projectile { owner: Some(by) } =
|
||||
cause
|
||||
{
|
||||
const MAX_EXP_DIST: f32 = 150.0;
|
||||
// Attacker gets same as exp of everyone else
|
||||
const ATTACKER_EXP_WEIGHT: f32 = 1.0;
|
||||
let mut exp_reward = (entity_stats.body_type.base_exp()
|
||||
+ entity_stats.level.level() * entity_stats.body_type.base_exp_increase())
|
||||
as f32;
|
||||
state.ecs().entity_from_uid(by.into()).map(|attacker| {
|
||||
// Distribute EXP to group
|
||||
let groups = state.ecs().read_storage::<Group>();
|
||||
let positions = state.ecs().read_storage::<Pos>();
|
||||
// TODO: rework if change to groups makes it easier to iterate entities in a
|
||||
// group
|
||||
if let (Some(attacker_group), Some(pos)) =
|
||||
(groups.get(attacker), positions.get(entity))
|
||||
{
|
||||
let members_in_range = (&state.ecs().entities(), &groups, &positions)
|
||||
.join()
|
||||
.filter(|(entity, group, member_pos)| {
|
||||
*group == attacker_group
|
||||
&& *entity != attacker
|
||||
&& pos.0.distance_squared(member_pos.0) < MAX_EXP_DIST.powi(2)
|
||||
})
|
||||
.map(|(entity, _, _)| entity)
|
||||
.collect::<Vec<_>>();
|
||||
let exp =
|
||||
exp_reward / (members_in_range.len() as f32 + ATTACKER_EXP_WEIGHT);
|
||||
exp_reward = exp * ATTACKER_EXP_WEIGHT;
|
||||
members_in_range.into_iter().for_each(|e| {
|
||||
if let Some(stats) = stats.get_mut(e) {
|
||||
stats.exp.change_by(exp.ceil() as i64);
|
||||
}
|
||||
});
|
||||
}
|
||||
let by = if let HealthSource::Attack { by } | HealthSource::Projectile { owner: Some(by) } =
|
||||
cause
|
||||
{
|
||||
by
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
let attacker = if let Some(attacker) = state.ecs().entity_from_uid(by.into()) {
|
||||
attacker
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
let entity_stats = if let Some(entity_stats) = stats.get(entity) {
|
||||
entity_stats
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
|
||||
if let Some(attacker_stats) = stats.get_mut(attacker) {
|
||||
// TODO: Discuss whether we should give EXP by Player
|
||||
// Killing or not.
|
||||
attacker_stats.exp.change_by(exp_reward.ceil() as i64);
|
||||
}
|
||||
});
|
||||
}
|
||||
let groups = state.ecs().read_storage::<Group>();
|
||||
let attacker_group = groups.get(attacker);
|
||||
let destroyed_group = groups.get(entity);
|
||||
// Don't give exp if attacker destroyed themselves or one of their group members
|
||||
if (attacker_group.is_some() && attacker_group == destroyed_group) || attacker == entity {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Maximum distance for other group members to receive exp
|
||||
const MAX_EXP_DIST: f32 = 150.0;
|
||||
// Attacker gets same as exp of everyone else
|
||||
const ATTACKER_EXP_WEIGHT: f32 = 1.0;
|
||||
let mut exp_reward = (entity_stats.body_type.base_exp()
|
||||
+ entity_stats.level.level() * entity_stats.body_type.base_exp_increase())
|
||||
as f32;
|
||||
|
||||
// Distribute EXP to group
|
||||
let positions = state.ecs().read_storage::<Pos>();
|
||||
if let (Some(attacker_group), Some(pos)) = (attacker_group, positions.get(entity)) {
|
||||
// TODO: rework if change to groups makes it easier to iterate entities in a
|
||||
// group
|
||||
let members_in_range = (&state.ecs().entities(), &groups, &positions)
|
||||
.join()
|
||||
.filter(|(entity, group, member_pos)| {
|
||||
*group == attacker_group
|
||||
&& *entity != attacker
|
||||
&& pos.0.distance_squared(member_pos.0) < MAX_EXP_DIST.powi(2)
|
||||
})
|
||||
.map(|(entity, _, _)| entity)
|
||||
.collect::<Vec<_>>();
|
||||
let exp = exp_reward / (members_in_range.len() as f32 + ATTACKER_EXP_WEIGHT);
|
||||
exp_reward = exp * ATTACKER_EXP_WEIGHT;
|
||||
members_in_range.into_iter().for_each(|e| {
|
||||
if let Some(stats) = stats.get_mut(e) {
|
||||
stats.exp.change_by(exp.ceil() as i64);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(attacker_stats) = stats.get_mut(attacker) {
|
||||
// TODO: Discuss whether we should give EXP by Player
|
||||
// Killing or not.
|
||||
attacker_stats.exp.change_by(exp_reward.ceil() as i64);
|
||||
}
|
||||
})();
|
||||
|
||||
if state
|
||||
.ecs()
|
||||
|
Loading…
Reference in New Issue
Block a user