Make entity targeting easier, add EXP sharing

This commit is contained in:
Imbris 2020-07-12 00:04:13 -04:00 committed by Monty Marz
parent 0a8f148559
commit ef4b221706
3 changed files with 38 additions and 10 deletions

View File

@ -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);
}
});
}

View File

@ -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)

View File

@ -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);