mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Make entity targeting easier, add EXP sharing
This commit is contained in:
parent
0a8f148559
commit
ef4b221706
@ -2,8 +2,8 @@ use crate::{client::Client, Server, SpawnPoint, StateExt};
|
||||
use common::{
|
||||
assets,
|
||||
comp::{
|
||||
self, item::lottery::Lottery, object, Body, Damage, DamageSource, HealthChange,
|
||||
HealthSource, Player, Stats,
|
||||
self, item::lottery::Lottery, object, Body, Damage, DamageSource, Group, HealthChange,
|
||||
HealthSource, Player, Pos, Stats,
|
||||
},
|
||||
msg::{PlayerListUpdate, ServerMsg},
|
||||
state::BlockChange,
|
||||
@ -62,16 +62,44 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
|
||||
if let HealthSource::Attack { by } | HealthSource::Projectile { owner: Some(by) } =
|
||||
cause
|
||||
{
|
||||
const MAX_EXP_DIST: f32 = 150.0;
|
||||
// Attacker gets double exp of everyone else
|
||||
const ATTACKER_EXP_WEIGHT: f32 = 2.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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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(
|
||||
(entity_stats.body_type.base_exp()
|
||||
+ entity_stats.level.level()
|
||||
* entity_stats.body_type.base_exp_increase())
|
||||
as i64,
|
||||
);
|
||||
attacker_stats.exp.change_by(exp_reward.ceil() as i64);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1082,7 +1082,7 @@ impl Hud {
|
||||
client.group_members.contains(uid),
|
||||
)
|
||||
})
|
||||
.filter(|(entity, pos, _, stats, _, _, _, _, hpfl, uid, in_group)| {
|
||||
.filter(|(entity, pos, _, stats, _, _, _, _, hpfl, _, in_group)| {
|
||||
*entity != me && !stats.is_dead
|
||||
&& (stats.health.current() != stats.health.maximum()
|
||||
|| info.target_entity.map_or(false, |e| e == *entity)
|
||||
|
@ -1123,7 +1123,7 @@ fn under_cursor(
|
||||
.join()
|
||||
.filter(|(e, _, _, _)| *e != player_entity)
|
||||
.map(|(e, p, s, b)| {
|
||||
const RADIUS_SCALE: f32 = 1.2;
|
||||
const RADIUS_SCALE: f32 = 1.6;
|
||||
let radius = s.map_or(1.0, |s| s.0) * b.radius() * RADIUS_SCALE;
|
||||
// Move position up from the feet
|
||||
let pos = Vec3::new(p.0.x, p.0.y, p.0.z + radius);
|
||||
|
Loading…
Reference in New Issue
Block a user