mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Prevented pet damage
This commit is contained in:
parent
f77d2f06c6
commit
e626f6255f
@ -1,9 +1,9 @@
|
||||
use crate::path::Chaser;
|
||||
use specs::{Component, Entity as EcsEntity};
|
||||
use crate::{path::Chaser, sync::Uid};
|
||||
use specs::{Component, Entity as EcsEntity, FlaggedStorage};
|
||||
use specs_idvs::IdvStorage;
|
||||
use vek::*;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum Alignment {
|
||||
/// Wild animals and gentle giants
|
||||
Wild,
|
||||
@ -14,7 +14,7 @@ pub enum Alignment {
|
||||
/// Farm animals and pets of villagers
|
||||
Tame,
|
||||
/// Pets you've tamed with a collar
|
||||
Owned(EcsEntity),
|
||||
Owned(Uid),
|
||||
}
|
||||
|
||||
impl Alignment {
|
||||
@ -51,7 +51,7 @@ impl Alignment {
|
||||
}
|
||||
|
||||
impl Component for Alignment {
|
||||
type Storage = IdvStorage<Self>;
|
||||
type Storage = FlaggedStorage<Self, IdvStorage<Self>>;
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
|
@ -7,7 +7,8 @@
|
||||
bool_to_option,
|
||||
label_break_value,
|
||||
trait_alias,
|
||||
type_alias_impl_trait
|
||||
type_alias_impl_trait,
|
||||
option_zip,
|
||||
)]
|
||||
|
||||
#[macro_use] extern crate serde_derive;
|
||||
|
@ -17,6 +17,7 @@ sum_type! {
|
||||
LightEmitter(comp::LightEmitter),
|
||||
Item(comp::Item),
|
||||
Scale(comp::Scale),
|
||||
Alignment(comp::Alignment),
|
||||
MountState(comp::MountState),
|
||||
Mounting(comp::Mounting),
|
||||
Mass(comp::Mass),
|
||||
@ -43,6 +44,7 @@ sum_type! {
|
||||
LightEmitter(PhantomData<comp::LightEmitter>),
|
||||
Item(PhantomData<comp::Item>),
|
||||
Scale(PhantomData<comp::Scale>),
|
||||
Alignment(PhantomData<comp::Alignment>),
|
||||
MountState(PhantomData<comp::MountState>),
|
||||
Mounting(PhantomData<comp::Mounting>),
|
||||
Mass(PhantomData<comp::Mass>),
|
||||
@ -69,6 +71,7 @@ impl sync::CompPacket for EcsCompPacket {
|
||||
EcsCompPacket::LightEmitter(comp) => sync::handle_insert(comp, entity, world),
|
||||
EcsCompPacket::Item(comp) => sync::handle_insert(comp, entity, world),
|
||||
EcsCompPacket::Scale(comp) => sync::handle_insert(comp, entity, world),
|
||||
EcsCompPacket::Alignment(comp) => sync::handle_insert(comp, entity, world),
|
||||
EcsCompPacket::MountState(comp) => sync::handle_insert(comp, entity, world),
|
||||
EcsCompPacket::Mounting(comp) => sync::handle_insert(comp, entity, world),
|
||||
EcsCompPacket::Mass(comp) => sync::handle_insert(comp, entity, world),
|
||||
@ -93,6 +96,7 @@ impl sync::CompPacket for EcsCompPacket {
|
||||
EcsCompPacket::LightEmitter(comp) => sync::handle_modify(comp, entity, world),
|
||||
EcsCompPacket::Item(comp) => sync::handle_modify(comp, entity, world),
|
||||
EcsCompPacket::Scale(comp) => sync::handle_modify(comp, entity, world),
|
||||
EcsCompPacket::Alignment(comp) => sync::handle_modify(comp, entity, world),
|
||||
EcsCompPacket::MountState(comp) => sync::handle_modify(comp, entity, world),
|
||||
EcsCompPacket::Mounting(comp) => sync::handle_modify(comp, entity, world),
|
||||
EcsCompPacket::Mass(comp) => sync::handle_modify(comp, entity, world),
|
||||
@ -119,6 +123,7 @@ impl sync::CompPacket for EcsCompPacket {
|
||||
},
|
||||
EcsCompPhantom::Item(_) => sync::handle_remove::<comp::Item>(entity, world),
|
||||
EcsCompPhantom::Scale(_) => sync::handle_remove::<comp::Scale>(entity, world),
|
||||
EcsCompPhantom::Alignment(_) => sync::handle_remove::<comp::Alignment>(entity, world),
|
||||
EcsCompPhantom::MountState(_) => sync::handle_remove::<comp::MountState>(entity, world),
|
||||
EcsCompPhantom::Mounting(_) => sync::handle_remove::<comp::Mounting>(entity, world),
|
||||
EcsCompPhantom::Mass(_) => sync::handle_remove::<comp::Mass>(entity, world),
|
||||
|
@ -123,6 +123,7 @@ impl State {
|
||||
ecs.register::<comp::Gravity>();
|
||||
ecs.register::<comp::CharacterState>();
|
||||
ecs.register::<comp::Object>();
|
||||
ecs.register::<comp::Alignment>();
|
||||
|
||||
// Register components send from clients -> server
|
||||
ecs.register::<comp::Controller>();
|
||||
@ -146,7 +147,6 @@ impl State {
|
||||
ecs.register::<comp::Last<comp::Vel>>();
|
||||
ecs.register::<comp::Last<comp::Ori>>();
|
||||
ecs.register::<comp::Agent>();
|
||||
ecs.register::<comp::Alignment>();
|
||||
ecs.register::<comp::WaypointArea>();
|
||||
ecs.register::<comp::ForceUpdate>();
|
||||
ecs.register::<comp::InventoryUpdate>();
|
||||
|
@ -31,11 +31,13 @@ impl CharacterBehavior for Data {
|
||||
handle_move(data, &mut update, 0.3);
|
||||
handle_jump(data, &mut update);
|
||||
|
||||
if !self.exhausted && if self.holdable {
|
||||
data.inputs.holding_ability_key() || self.prepare_timer < self.prepare_duration
|
||||
} else {
|
||||
self.prepare_timer < self.prepare_duration
|
||||
} {
|
||||
if !self.exhausted
|
||||
&& if self.holdable {
|
||||
data.inputs.holding_ability_key() || self.prepare_timer < self.prepare_duration
|
||||
} else {
|
||||
self.prepare_timer < self.prepare_duration
|
||||
}
|
||||
{
|
||||
// Prepare (draw the bow)
|
||||
update.character = CharacterState::BasicRanged(Data {
|
||||
prepare_timer: self.prepare_timer + Duration::from_secs_f32(data.dt.0),
|
||||
|
@ -45,6 +45,24 @@ impl Body {
|
||||
Body::QuadrupedLow(_) => 120.0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn base_ori_rate(&self) -> f32 {
|
||||
match self {
|
||||
Body::Humanoid(_) => 20.0,
|
||||
Body::QuadrupedSmall(_) => 15.0,
|
||||
Body::QuadrupedMedium(_) => 10.0,
|
||||
Body::BirdMedium(_) => 30.0,
|
||||
Body::FishMedium(_) => 5.0,
|
||||
Body::Dragon(_) => 5.0,
|
||||
Body::BirdSmall(_) => 35.0,
|
||||
Body::FishSmall(_) => 10.0,
|
||||
Body::BipedLarge(_) => 12.0,
|
||||
Body::Object(_) => 5.0,
|
||||
Body::Golem(_) => 8.0,
|
||||
Body::Critter(_) => 35.0,
|
||||
Body::QuadrupedLow(_) => 12.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles updating `Components` to move player based on state of `JoinData`
|
||||
@ -68,10 +86,10 @@ fn basic_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32) {
|
||||
update.vel.0 =
|
||||
update.vel.0 + Vec2::broadcast(data.dt.0) * data.inputs.move_dir * accel * efficiency;
|
||||
|
||||
handle_orientation(data, update, 20.0);
|
||||
handle_orientation(data, update, data.body.base_ori_rate());
|
||||
}
|
||||
|
||||
pub fn handle_orientation(data: &JoinData, update: &mut StateUpdate, strength: f32) {
|
||||
pub fn handle_orientation(data: &JoinData, update: &mut StateUpdate, rate: f32) {
|
||||
// Set direction based on move direction
|
||||
let ori_dir = if update.character.is_attack() || update.character.is_block() {
|
||||
data.inputs.look_dir.xy()
|
||||
@ -82,7 +100,7 @@ pub fn handle_orientation(data: &JoinData, update: &mut StateUpdate, strength: f
|
||||
};
|
||||
|
||||
// Smooth orientation
|
||||
update.ori.0 = Dir::slerp_to_vec3(update.ori.0, ori_dir.into(), strength * data.dt.0);
|
||||
update.ori.0 = Dir::slerp_to_vec3(update.ori.0, ori_dir.into(), rate * data.dt.0);
|
||||
}
|
||||
|
||||
/// Updates components to move player as if theyre swimming
|
||||
|
@ -245,7 +245,11 @@ impl<'a> System<'a> for Sys {
|
||||
alignments
|
||||
.get(*target)
|
||||
.copied()
|
||||
.unwrap_or(Alignment::Owned(*target)),
|
||||
.unwrap_or(uids
|
||||
.get(*target)
|
||||
.copied()
|
||||
.map(Alignment::Owned)
|
||||
.unwrap_or(Alignment::Wild)),
|
||||
) {
|
||||
if let Some(dir) = Dir::from_unnormalized(tgt_pos.0 - pos.0) {
|
||||
inputs.look_dir = dir;
|
||||
@ -419,7 +423,10 @@ impl<'a> System<'a> for Sys {
|
||||
|
||||
// Follow owner if we're too far, or if they're under attack
|
||||
if let Some(Alignment::Owned(owner)) = alignment.copied() {
|
||||
if let Some(owner_pos) = positions.get(owner) {
|
||||
(|| {
|
||||
let owner = uid_allocator.retrieve_entity_internal(owner.id())?;
|
||||
|
||||
let owner_pos = positions.get(owner)?;
|
||||
let dist_sqrd = pos.0.distance_squared(owner_pos.0);
|
||||
if dist_sqrd > MAX_FOLLOW_DIST.powf(2.0) && !agent.activity.is_follow() {
|
||||
agent.activity = Activity::Follow {
|
||||
@ -429,28 +436,27 @@ impl<'a> System<'a> for Sys {
|
||||
}
|
||||
|
||||
// Attack owner's attacker
|
||||
if let Some(owner_stats) = stats.get(owner) {
|
||||
if owner_stats.health.last_change.0 < 5.0 {
|
||||
if let comp::HealthSource::Attack { by } =
|
||||
owner_stats.health.last_change.1.cause
|
||||
{
|
||||
if !agent.activity.is_attack() {
|
||||
if let Some(attacker) =
|
||||
uid_allocator.retrieve_entity_internal(by.id())
|
||||
{
|
||||
agent.activity = Activity::Attack {
|
||||
target: attacker,
|
||||
chaser: Chaser::default(),
|
||||
time: time.0,
|
||||
been_close: false,
|
||||
powerup: 0.0,
|
||||
};
|
||||
}
|
||||
}
|
||||
let owner_stats = stats.get(owner)?;
|
||||
if owner_stats.health.last_change.0 < 5.0 {
|
||||
if let comp::HealthSource::Attack { by } =
|
||||
owner_stats.health.last_change.1.cause
|
||||
{
|
||||
if !agent.activity.is_attack() {
|
||||
let attacker = uid_allocator.retrieve_entity_internal(by.id())?;
|
||||
|
||||
agent.activity = Activity::Attack {
|
||||
target: attacker,
|
||||
chaser: Chaser::default(),
|
||||
time: time.0,
|
||||
been_close: false,
|
||||
powerup: 0.0,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(())
|
||||
})();
|
||||
}
|
||||
|
||||
debug_assert!(inputs.move_dir.map(|e| !e.is_nan()).reduce_and());
|
||||
|
@ -119,12 +119,15 @@ impl<'a> System<'a> for Sys {
|
||||
// healthchange = (healthchange / 1.5).min(-1.0);
|
||||
//}
|
||||
|
||||
// TODO: remove this when there is a better way to target healing
|
||||
// Don't heal npc's hp
|
||||
if alignment_b_maybe
|
||||
// TODO: remove this when there is a better way to deal with alignment
|
||||
// Don't heal NPCs
|
||||
if (healthchange > 0.0 && alignment_b_maybe
|
||||
.map(|a| !a.is_friendly_to_players())
|
||||
.unwrap_or(true)
|
||||
&& healthchange > 0.0
|
||||
.unwrap_or(true))
|
||||
// Don't hurt pets
|
||||
|| (healthchange < 0.0 && alignment_b_maybe
|
||||
.map(|b| Alignment::Owned(*uid).passive_towards(*b))
|
||||
.unwrap_or(false))
|
||||
{
|
||||
healthchange = 0.0;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::{
|
||||
comp::{
|
||||
projectile, Energy, EnergySource, HealthSource, Ori, PhysicsState, Pos, Projectile, Vel,
|
||||
Alignment,
|
||||
},
|
||||
event::{EventBus, LocalEvent, ServerEvent},
|
||||
state::DeltaTime,
|
||||
@ -27,6 +28,7 @@ impl<'a> System<'a> for Sys {
|
||||
WriteStorage<'a, Ori>,
|
||||
WriteStorage<'a, Projectile>,
|
||||
WriteStorage<'a, Energy>,
|
||||
ReadStorage<'a, Alignment>,
|
||||
);
|
||||
|
||||
fn run(
|
||||
@ -43,6 +45,7 @@ impl<'a> System<'a> for Sys {
|
||||
mut orientations,
|
||||
mut projectiles,
|
||||
mut energies,
|
||||
alignments,
|
||||
): Self::SystemData,
|
||||
) {
|
||||
let mut local_emitter = local_bus.emitter();
|
||||
@ -82,7 +85,17 @@ impl<'a> System<'a> for Sys {
|
||||
for effect in projectile.hit_entity.drain(..) {
|
||||
match effect {
|
||||
projectile::Effect::Damage(change) => {
|
||||
if other != projectile.owner.unwrap() {
|
||||
let owner_uid = projectile.owner.unwrap();
|
||||
// Hacky: remove this when groups get implemented
|
||||
let passive = uid_allocator
|
||||
.retrieve_entity_internal(other.into())
|
||||
.and_then(|other|
|
||||
alignments
|
||||
.get(other)
|
||||
.map(|a| Alignment::Owned(owner_uid)
|
||||
.passive_towards(*a)))
|
||||
.unwrap_or(false);
|
||||
if other != projectile.owner.unwrap() && !passive {
|
||||
server_emitter.emit(ServerEvent::Damage { uid: other, change });
|
||||
}
|
||||
},
|
||||
|
@ -507,7 +507,8 @@ fn handle_spawn(
|
||||
String
|
||||
) {
|
||||
(Some(opt_align), Some(npc::NpcBody(id, mut body)), opt_amount, opt_ai) => {
|
||||
if let Some(alignment) = parse_alignment(target, &opt_align) {
|
||||
let uid = server.state.read_component_cloned(target).expect("Expected player to have a UID");
|
||||
if let Some(alignment) = parse_alignment(uid, &opt_align) {
|
||||
let amount = opt_amount
|
||||
.and_then(|a| a.parse().ok())
|
||||
.filter(|x| *x > 0)
|
||||
@ -715,7 +716,7 @@ fn handle_help(
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_alignment(owner: EcsEntity, alignment: &str) -> Option<comp::Alignment> {
|
||||
fn parse_alignment(owner: Uid, alignment: &str) -> Option<comp::Alignment> {
|
||||
match alignment {
|
||||
"wild" => Some(comp::Alignment::Wild),
|
||||
"enemy" => Some(comp::Alignment::Enemy),
|
||||
|
@ -188,13 +188,15 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
||||
let reinsert = if let Some(pos) =
|
||||
state.read_storage::<comp::Pos>().get(entity)
|
||||
{
|
||||
let uid = state.read_component_cloned(entity)
|
||||
.expect("Expected player to have a UID");
|
||||
if (
|
||||
&state.read_storage::<comp::Alignment>(),
|
||||
&state.read_storage::<comp::Agent>(),
|
||||
)
|
||||
.join()
|
||||
.filter(|(alignment, _)| {
|
||||
alignment == &&comp::Alignment::Owned(entity)
|
||||
alignment == &&comp::Alignment::Owned(uid)
|
||||
})
|
||||
.count()
|
||||
>= 3
|
||||
@ -222,7 +224,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
||||
} {
|
||||
let _ = state.ecs().write_storage().insert(
|
||||
tameable_entity,
|
||||
comp::Alignment::Owned(entity),
|
||||
comp::Alignment::Owned(uid),
|
||||
);
|
||||
let _ = state
|
||||
.ecs()
|
||||
|
@ -171,7 +171,7 @@ impl StateExt for State {
|
||||
});
|
||||
self.write_component(entity, comp::Gravity(1.0));
|
||||
self.write_component(entity, comp::CharacterState::default());
|
||||
self.write_component(entity, comp::Alignment::Owned(entity));
|
||||
self.write_component(entity, comp::Alignment::Owned(self.read_component_cloned(entity).unwrap()));
|
||||
|
||||
// Set the character id for the player
|
||||
// TODO this results in a warning in the console: "Error modifying synced
|
||||
|
@ -2,7 +2,7 @@ use super::SysTimer;
|
||||
use common::{
|
||||
comp::{
|
||||
Body, CanBuild, CharacterState, Collider, Energy, Gravity, Item, LightEmitter, Loadout,
|
||||
Mass, MountState, Mounting, Ori, Player, Pos, Scale, Stats, Sticky, Vel,
|
||||
Mass, MountState, Mounting, Ori, Player, Pos, Scale, Stats, Sticky, Vel, Alignment,
|
||||
},
|
||||
msg::EcsCompPacket,
|
||||
sync::{CompSyncPackage, EntityPackage, EntitySyncPackage, Uid, UpdateTracker, WorldSyncExt},
|
||||
@ -48,6 +48,7 @@ pub struct TrackedComps<'a> {
|
||||
pub scale: ReadStorage<'a, Scale>,
|
||||
pub mounting: ReadStorage<'a, Mounting>,
|
||||
pub mount_state: ReadStorage<'a, MountState>,
|
||||
pub alignment: ReadStorage<'a, Alignment>,
|
||||
pub mass: ReadStorage<'a, Mass>,
|
||||
pub collider: ReadStorage<'a, Collider>,
|
||||
pub sticky: ReadStorage<'a, Sticky>,
|
||||
@ -104,6 +105,10 @@ impl<'a> TrackedComps<'a> {
|
||||
.get(entity)
|
||||
.cloned()
|
||||
.map(|c| comps.push(c.into()));
|
||||
self.alignment
|
||||
.get(entity)
|
||||
.cloned()
|
||||
.map(|c| comps.push(c.into()));
|
||||
self.mass.get(entity).copied().map(|c| comps.push(c.into()));
|
||||
self.collider
|
||||
.get(entity)
|
||||
@ -146,6 +151,7 @@ pub struct ReadTrackers<'a> {
|
||||
pub scale: ReadExpect<'a, UpdateTracker<Scale>>,
|
||||
pub mounting: ReadExpect<'a, UpdateTracker<Mounting>>,
|
||||
pub mount_state: ReadExpect<'a, UpdateTracker<MountState>>,
|
||||
pub alignment: ReadExpect<'a, UpdateTracker<Alignment>>,
|
||||
pub mass: ReadExpect<'a, UpdateTracker<Mass>>,
|
||||
pub collider: ReadExpect<'a, UpdateTracker<Collider>>,
|
||||
pub sticky: ReadExpect<'a, UpdateTracker<Sticky>>,
|
||||
@ -178,6 +184,7 @@ impl<'a> ReadTrackers<'a> {
|
||||
.with_component(&comps.uid, &*self.scale, &comps.scale, filter)
|
||||
.with_component(&comps.uid, &*self.mounting, &comps.mounting, filter)
|
||||
.with_component(&comps.uid, &*self.mount_state, &comps.mount_state, filter)
|
||||
.with_component(&comps.uid, &*self.alignment, &comps.alignment, filter)
|
||||
.with_component(&comps.uid, &*self.mass, &comps.mass, filter)
|
||||
.with_component(&comps.uid, &*self.collider, &comps.collider, filter)
|
||||
.with_component(&comps.uid, &*self.sticky, &comps.sticky, filter)
|
||||
@ -207,6 +214,7 @@ pub struct WriteTrackers<'a> {
|
||||
scale: WriteExpect<'a, UpdateTracker<Scale>>,
|
||||
mounting: WriteExpect<'a, UpdateTracker<Mounting>>,
|
||||
mount_state: WriteExpect<'a, UpdateTracker<MountState>>,
|
||||
alignment: WriteExpect<'a, UpdateTracker<Alignment>>,
|
||||
mass: WriteExpect<'a, UpdateTracker<Mass>>,
|
||||
collider: WriteExpect<'a, UpdateTracker<Collider>>,
|
||||
sticky: WriteExpect<'a, UpdateTracker<Sticky>>,
|
||||
@ -228,6 +236,7 @@ fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) {
|
||||
trackers.scale.record_changes(&comps.scale);
|
||||
trackers.mounting.record_changes(&comps.mounting);
|
||||
trackers.mount_state.record_changes(&comps.mount_state);
|
||||
trackers.alignment.record_changes(&comps.alignment);
|
||||
trackers.mass.record_changes(&comps.mass);
|
||||
trackers.collider.record_changes(&comps.collider);
|
||||
trackers.sticky.record_changes(&comps.sticky);
|
||||
@ -282,6 +291,7 @@ pub fn register_trackers(world: &mut World) {
|
||||
world.register_tracker::<Scale>();
|
||||
world.register_tracker::<Mounting>();
|
||||
world.register_tracker::<MountState>();
|
||||
world.register_tracker::<Alignment>();
|
||||
world.register_tracker::<Mass>();
|
||||
world.register_tracker::<Collider>();
|
||||
world.register_tracker::<Sticky>();
|
||||
|
@ -57,9 +57,9 @@ impl SessionState {
|
||||
.set_fov_deg(global_state.settings.graphics.fov);
|
||||
let hud = Hud::new(global_state, &client.borrow());
|
||||
{
|
||||
let my_entity = client.borrow().entity();
|
||||
let mut client = client.borrow_mut();
|
||||
let my_entity = client.entity();
|
||||
client
|
||||
.borrow_mut()
|
||||
.state_mut()
|
||||
.ecs_mut()
|
||||
.insert(MyEntity(my_entity));
|
||||
|
Loading…
Reference in New Issue
Block a user