Various tweaks: moved radius determination to function on , comments, simplified server Destroy event code, debug assert modified components aren't removed in change tracking, etc

This commit is contained in:
Imbris 2019-12-19 22:31:41 -05:00
parent b2752d2419
commit 934c5d6846
7 changed files with 54 additions and 29 deletions

View File

@ -33,6 +33,23 @@ impl Body {
_ => false,
}
}
// Note: this might need to be refined to something more complex for realistic
// behavior with less cylindrical bodies (e.g. wolfs)
pub fn radius(&self) -> f32 {
// TODO: Improve these values (some might be reliant on more info in inner type)
match self {
Body::Humanoid(_) => 0.5,
Body::QuadrupedSmall(_) => 0.6,
Body::QuadrupedMedium(_) => 0.9,
Body::BirdMedium(_) => 0.5,
Body::FishMedium(_) => 0.5,
Body::Dragon(_) => 2.5,
Body::BirdSmall(_) => 0.2,
Body::FishSmall(_) => 0.2,
Body::BipedLarge(_) => 1.0,
Body::Object(_) => 0.3,
}
}
}
impl Component for Body {

View File

@ -8,6 +8,9 @@ use std::{
marker::PhantomData,
};
/// Implemented by type that carries component data for insertion and modification
/// The assocatied `Phantom` type only carries information about which component type is of
/// interest and is used to transmit deletion events
pub trait CompPacket: Clone + Debug + Send + 'static {
type Phantom: Clone + Debug + Serialize + DeserializeOwned;

View File

@ -51,10 +51,9 @@ where
self.inserted.add(*id);
}
specs::storage::ComponentEvent::Modified(id) => {
// We don't care about modification if the component was just added or was
// removed
// Could potentially remove since this should theoretically never occur...
if !self.removed.contains(*id) && !self.inserted.contains(*id) {
// We don't care about modification if the component was just added
if !self.inserted.contains(*id) {
debug_assert!(!self.removed.contains(*id)); // Theoretically impossible
self.modified.add(*id);
}
}

View File

@ -147,8 +147,11 @@ impl<'a> System<'a> for Sys {
if target_stats.is_dead {
choose_new = true;
} else if dist < 0.001 {
// TODO: move back? (probably can only happen when entities are at a
// different z-level due to repulsion)
// Probably can only happen when entities are at a different z-level
// since at the same level repulsion would keep them apart.
// Distinct from the first if block since we may want to change the
// behavior for this case.
choose_new = true;
} else if dist < MIN_ATTACK_DIST {
// Fight (and slowly move closer)
inputs.move_dir =

View File

@ -1,7 +1,7 @@
use crate::{
comp::{
ActionState::*, CharacterState, Controller, HealthChange, HealthSource, Item, ItemKind,
Ori, Pos, Scale, Stats,
ActionState::*, Body, CharacterState, Controller, HealthChange, HealthSource, Item,
ItemKind, Ori, Pos, Scale, Stats,
},
event::{EventBus, LocalEvent, ServerEvent},
state::DeltaTime,
@ -30,8 +30,9 @@ impl<'a> System<'a> for Sys {
ReadStorage<'a, Ori>,
ReadStorage<'a, Scale>,
ReadStorage<'a, Controller>,
ReadStorage<'a, Body>,
ReadStorage<'a, Stats>,
WriteStorage<'a, CharacterState>,
WriteStorage<'a, Stats>,
);
fn run(
@ -46,15 +47,16 @@ impl<'a> System<'a> for Sys {
orientations,
scales,
controllers,
mut character_states,
bodies,
stats,
mut character_states,
): Self::SystemData,
) {
let mut server_emitter = server_bus.emitter();
let mut _local_emitter = local_bus.emitter();
// Attacks
for (entity, uid, pos, ori, scale_maybe, _, stat) in (
for (entity, uid, pos, ori, scale_maybe, _, attacker_stats) in (
&entities,
&uids,
&positions,
@ -68,7 +70,7 @@ impl<'a> System<'a> for Sys {
let recover_duration = if let Some(Item {
kind: ItemKind::Tool { kind, .. },
..
}) = stat.equipment.main
}) = attacker_stats.equipment.main
{
kind.attack_recover_duration()
} else {
@ -96,7 +98,7 @@ impl<'a> System<'a> for Sys {
if deal_damage {
if let Some(Attack { .. }) = &character_states.get(entity).map(|c| c.action) {
// Go through all other entities
for (b, uid_b, pos_b, ori_b, scale_b_maybe, character_b, stat_b) in (
for (b, uid_b, pos_b, ori_b, scale_b_maybe, character_b, stats_b, body_b) in (
&entities,
&uids,
&positions,
@ -104,6 +106,7 @@ impl<'a> System<'a> for Sys {
scales.maybe(),
&character_states,
&stats,
&bodies,
)
.join()
{
@ -115,19 +118,18 @@ impl<'a> System<'a> for Sys {
// Scales
let scale = scale_maybe.map_or(1.0, |s| s.0);
let scale_b = scale_b_maybe.map_or(1.0, |s| s.0);
// TODO: don't do this here
let rad_b = 0.5 * scale_b;
let rad_b = body_b.radius() * scale_b;
// Check if it is a hit
if entity != b
&& !stat_b.is_dead
&& !stats_b.is_dead
// Spherical wedge shaped attack field
&& pos.0.distance_squared(pos_b.0) < (rad_b + scale * ATTACK_RANGE).powi(2)
&& ori2.angle_between(pos_b2 - pos2) < ATTACK_ANGLE.to_radians() / 2.0 + (rad_b / pos2.distance(pos_b2)).atan()
{
// Weapon gives base damage
let mut dmg = if let Some(ItemKind::Tool { power, .. }) =
stat.equipment.main.as_ref().map(|i| &i.kind)
attacker_stats.equipment.main.as_ref().map(|i| &i.kind)
{
*power as i32
} else {

View File

@ -413,21 +413,25 @@ impl Server {
}
}
// This sucks
let mut remove = false;
let mut remove = true;
if let Some(client) = state.ecs().write_storage::<Client>().get_mut(entity) {
let _ = state
remove = false;
state
.ecs()
.write_storage()
.insert(entity, comp::Vel(Vec3::zero()));
let _ = state
.insert(entity, comp::Vel(Vec3::zero()))
.err()
.map(|err| error!("Failed to set zero vel on dead client: {:?}", err));
state
.ecs()
.write_storage()
.insert(entity, comp::ForceUpdate);
.insert(entity, comp::ForceUpdate)
.err()
.map(|err| {
error!("Failed to insert ForceUpdate on dead client: {:?}", err)
});
client.force_state(ClientState::Dead);
} else {
remove = true;
}
if remove {

View File

@ -756,10 +756,7 @@ impl Ui {
}
fn default_scissor(renderer: &Renderer) -> Aabr<u16> {
let (screen_w, screen_h) = renderer
.get_resolution()
.map(|e| (e as u16).max(1))
.into_tuple();
let (screen_w, screen_h) = renderer.get_resolution().into_tuple();
Aabr {
min: Vec2 { x: 0, y: 0 },
max: Vec2 {