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));
|
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>();
|
let mut stats = state.ecs().write_storage::<Stats>();
|
||||||
if let Some(entity_stats) = stats.get(entity).cloned() {
|
let by = if let HealthSource::Attack { by } | HealthSource::Projectile { owner: Some(by) } =
|
||||||
if let HealthSource::Attack { by } | HealthSource::Projectile { owner: Some(by) } =
|
cause
|
||||||
cause
|
{
|
||||||
{
|
by
|
||||||
const MAX_EXP_DIST: f32 = 150.0;
|
} else {
|
||||||
// Attacker gets same as exp of everyone else
|
return;
|
||||||
const ATTACKER_EXP_WEIGHT: f32 = 1.0;
|
};
|
||||||
let mut exp_reward = (entity_stats.body_type.base_exp()
|
let attacker = if let Some(attacker) = state.ecs().entity_from_uid(by.into()) {
|
||||||
+ entity_stats.level.level() * entity_stats.body_type.base_exp_increase())
|
attacker
|
||||||
as f32;
|
} else {
|
||||||
state.ecs().entity_from_uid(by.into()).map(|attacker| {
|
return;
|
||||||
// Distribute EXP to group
|
};
|
||||||
let groups = state.ecs().read_storage::<Group>();
|
let entity_stats = if let Some(entity_stats) = stats.get(entity) {
|
||||||
let positions = state.ecs().read_storage::<Pos>();
|
entity_stats
|
||||||
// TODO: rework if change to groups makes it easier to iterate entities in a
|
} else {
|
||||||
// group
|
return;
|
||||||
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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(attacker_stats) = stats.get_mut(attacker) {
|
let groups = state.ecs().read_storage::<Group>();
|
||||||
// TODO: Discuss whether we should give EXP by Player
|
let attacker_group = groups.get(attacker);
|
||||||
// Killing or not.
|
let destroyed_group = groups.get(entity);
|
||||||
attacker_stats.exp.change_by(exp_reward.ceil() as i64);
|
// 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
|
if state
|
||||||
.ecs()
|
.ecs()
|
||||||
|
Loading…
Reference in New Issue
Block a user