mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'tame_and_mount_special_casing' into 'master'
Special case taming and mounting. See merge request veloren/veloren!3354
This commit is contained in:
commit
b9c324a183
@ -1,6 +1,7 @@
|
||||
use crate::{make_case_elim, make_proj_elim};
|
||||
use rand::{seq::SliceRandom, thread_rng};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use strum::{Display, EnumString};
|
||||
|
||||
make_proj_elim!(
|
||||
body,
|
||||
@ -31,7 +32,9 @@ impl From<Body> for super::Body {
|
||||
|
||||
make_case_elim!(
|
||||
species,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(
|
||||
Copy, Clone, Debug, Display, EnumString, PartialEq, Eq, Hash, Serialize, Deserialize,
|
||||
)]
|
||||
#[repr(u32)]
|
||||
pub enum Species {
|
||||
Duck = 0,
|
||||
@ -98,7 +101,9 @@ impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {
|
||||
|
||||
make_case_elim!(
|
||||
body_type,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(
|
||||
Copy, Clone, Debug, Display, EnumString, PartialEq, Eq, Hash, Serialize, Deserialize,
|
||||
)]
|
||||
#[repr(u32)]
|
||||
pub enum BodyType {
|
||||
Female = 0,
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::comp::body::Body;
|
||||
use crate::comp::{body::Body, phys::Mass, quadruped_low, quadruped_medium, quadruped_small};
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use specs::Component;
|
||||
@ -40,10 +40,62 @@ pub fn is_tameable(body: &Body) -> bool {
|
||||
// Currently only Quadruped animals can be tamed pending further work
|
||||
// on the pets feature (allowing larger animals to be tamed will
|
||||
// require balance issues to be addressed).
|
||||
matches!(
|
||||
body,
|
||||
Body::QuadrupedLow(_) | Body::QuadrupedMedium(_) | Body::QuadrupedSmall(_)
|
||||
)
|
||||
match body {
|
||||
Body::QuadrupedMedium(quad_med) =>
|
||||
// NOTE: the reason we ban mammoth from being tameable even though they're
|
||||
// agressive anyway, is that UncomfySilence is going to make them
|
||||
// peaceful after this MR gets merged. Please, remove this note in your MR,
|
||||
// UncomfySilence!
|
||||
{
|
||||
!matches!(
|
||||
quad_med.species,
|
||||
quadruped_medium::Species::Catoblepas
|
||||
| quadruped_medium::Species::Mammoth
|
||||
| quadruped_medium::Species::Hirdrasil
|
||||
)
|
||||
},
|
||||
Body::QuadrupedLow(_) | Body::QuadrupedSmall(_) | Body::BirdMedium(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_mountable(mount: &Body, rider: Option<&Body>) -> bool {
|
||||
let is_light_enough =
|
||||
|rider: Option<&Body>| -> bool { rider.map_or(false, |b| b.mass() <= Mass(500.0)) };
|
||||
|
||||
match mount {
|
||||
Body::QuadrupedMedium(body) => match body.species {
|
||||
quadruped_medium::Species::Alpaca
|
||||
| quadruped_medium::Species::Antelope
|
||||
| quadruped_medium::Species::Bear
|
||||
| quadruped_medium::Species::Camel
|
||||
| quadruped_medium::Species::Cattle
|
||||
| quadruped_medium::Species::Deer
|
||||
| quadruped_medium::Species::Donkey
|
||||
| quadruped_medium::Species::Highland
|
||||
| quadruped_medium::Species::Horse
|
||||
| quadruped_medium::Species::Kelpie
|
||||
| quadruped_medium::Species::Llama
|
||||
| quadruped_medium::Species::Moose
|
||||
| quadruped_medium::Species::Tuskram
|
||||
| quadruped_medium::Species::Yak
|
||||
| quadruped_medium::Species::Zebra => true,
|
||||
quadruped_medium::Species::Mouflon => is_light_enough(rider),
|
||||
_ => false,
|
||||
},
|
||||
Body::QuadrupedSmall(body) => match body.species {
|
||||
quadruped_small::Species::Truffler => true,
|
||||
quadruped_small::Species::Boar | quadruped_small::Species::Holladon => {
|
||||
is_light_enough(rider)
|
||||
},
|
||||
_ => false,
|
||||
},
|
||||
Body::QuadrupedLow(body) => matches!(
|
||||
body.species,
|
||||
quadruped_low::Species::Salamander | quadruped_low::Species::Tortoise
|
||||
),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for Pet {
|
||||
|
@ -81,7 +81,7 @@ impl Component for Scale {
|
||||
}
|
||||
|
||||
// Mass
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
pub struct Mass(pub f32);
|
||||
|
||||
impl Default for Mass {
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::{
|
||||
comp,
|
||||
comp::{pet::is_mountable, Body},
|
||||
link::{Is, Link, LinkHandle, Role},
|
||||
terrain::TerrainGrid,
|
||||
uid::{Uid, UidAllocator},
|
||||
@ -38,6 +39,7 @@ impl Link for Mounting {
|
||||
Read<'a, UidAllocator>,
|
||||
WriteStorage<'a, Is<Mount>>,
|
||||
WriteStorage<'a, Is<Rider>>,
|
||||
WriteStorage<'a, Body>,
|
||||
);
|
||||
type DeleteData<'a> = (
|
||||
Read<'a, UidAllocator>,
|
||||
@ -58,7 +60,7 @@ impl Link for Mounting {
|
||||
|
||||
fn create(
|
||||
this: &LinkHandle<Self>,
|
||||
(uid_allocator, mut is_mounts, mut is_riders): Self::CreateData<'_>,
|
||||
(uid_allocator, mut is_mounts, mut is_riders, body): Self::CreateData<'_>,
|
||||
) -> Result<(), Self::Error> {
|
||||
let entity = |uid: Uid| uid_allocator.retrieve_entity_internal(uid.into());
|
||||
|
||||
@ -66,15 +68,23 @@ impl Link for Mounting {
|
||||
// Forbid self-mounting
|
||||
Err(MountingError::NotMountable)
|
||||
} else if let Some((mount, rider)) = entity(this.mount).zip(entity(this.rider)) {
|
||||
let can_mount_with =
|
||||
|entity| is_mounts.get(entity).is_none() && is_riders.get(entity).is_none();
|
||||
if let Some(mount_body) = body.get(mount) {
|
||||
if is_mountable(mount_body, body.get(rider)) {
|
||||
let can_mount_with =
|
||||
|entity| is_mounts.get(entity).is_none() && is_riders.get(entity).is_none();
|
||||
|
||||
// Ensure that neither mount or rider are already part of a mounting
|
||||
// relationship
|
||||
if can_mount_with(mount) && can_mount_with(rider) {
|
||||
let _ = is_mounts.insert(mount, this.make_role());
|
||||
let _ = is_riders.insert(rider, this.make_role());
|
||||
Ok(())
|
||||
// Ensure that neither mount or rider are already part of a mounting
|
||||
// relationship
|
||||
if can_mount_with(mount) && can_mount_with(rider) {
|
||||
let _ = is_mounts.insert(mount, this.make_role());
|
||||
let _ = is_riders.insert(rider, this.make_role());
|
||||
Ok(())
|
||||
} else {
|
||||
Err(MountingError::NotMountable)
|
||||
}
|
||||
} else {
|
||||
Err(MountingError::NotMountable)
|
||||
}
|
||||
} else {
|
||||
Err(MountingError::NotMountable)
|
||||
}
|
||||
|
@ -209,6 +209,10 @@ pub fn convert_body_to_database_json(
|
||||
"quadruped_small",
|
||||
serde_json::to_string(&GenericBody::from(body))?,
|
||||
),
|
||||
common::comp::Body::BirdMedium(body) => (
|
||||
"bird_medium",
|
||||
serde_json::to_string(&GenericBody::from(body))?,
|
||||
),
|
||||
_ => {
|
||||
return Err(PersistenceError::ConversionError(format!(
|
||||
"Unsupported body type for persistence: {:?}",
|
||||
@ -577,6 +581,9 @@ pub fn convert_body_from_database(
|
||||
"quadruped_small" => {
|
||||
deserialize_body!(body_data, QuadrupedSmall, quadruped_small)
|
||||
},
|
||||
"bird_medium" => {
|
||||
deserialize_body!(body_data, BirdMedium, bird_medium)
|
||||
},
|
||||
_ => {
|
||||
return Err(PersistenceError::ConversionError(format!(
|
||||
"{} is not a supported body type for deserialization",
|
||||
|
@ -59,6 +59,7 @@ macro_rules! generic_body_from_impl {
|
||||
generic_body_from_impl!(comp::quadruped_low::Body);
|
||||
generic_body_from_impl!(comp::quadruped_medium::Body);
|
||||
generic_body_from_impl!(comp::quadruped_small::Body);
|
||||
generic_body_from_impl!(comp::bird_medium::Body);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct CharacterPosition {
|
||||
|
@ -82,6 +82,7 @@ use common::{
|
||||
fluid_dynamics,
|
||||
inventory::{slot::InvSlotId, trade_pricing::TradePricing},
|
||||
item::{tool::ToolKind, ItemDesc, MaterialStatManifest, Quality},
|
||||
pet::is_mountable,
|
||||
skillset::{skills::Skill, SkillGroupKind},
|
||||
BuffData, BuffKind, Item, MapMarkerChange,
|
||||
},
|
||||
@ -1929,7 +1930,8 @@ impl Hud {
|
||||
_,
|
||||
health,
|
||||
_,
|
||||
height_offset,
|
||||
scale,
|
||||
body,
|
||||
hpfl,
|
||||
in_group,
|
||||
dist_sqr,
|
||||
@ -2034,23 +2036,10 @@ impl Hud {
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
(info.is_some() || bubble.is_some()).then(|| {
|
||||
(
|
||||
entity,
|
||||
pos,
|
||||
info,
|
||||
bubble,
|
||||
stats,
|
||||
skill_set,
|
||||
health,
|
||||
buffs,
|
||||
body.height() * scale.map_or(1.0, |s| s.0) + 0.5,
|
||||
hpfl,
|
||||
in_group,
|
||||
dist_sqr,
|
||||
alignment,
|
||||
is_mount,
|
||||
entity, pos, info, bubble, stats, skill_set, health, buffs, scale,
|
||||
body, hpfl, in_group, dist_sqr, alignment, is_mount,
|
||||
)
|
||||
})
|
||||
},
|
||||
@ -2060,10 +2049,9 @@ impl Hud {
|
||||
&mut self.ids.overheads,
|
||||
&mut ui_widgets.widget_id_generator(),
|
||||
);
|
||||
let ingame_pos = pos + Vec3::unit_z() * height_offset;
|
||||
|
||||
//
|
||||
// * height_offset
|
||||
let height_offset = body.height() * scale.map_or(1.0, |s| s.0) + 0.5;
|
||||
let ingame_pos = pos + Vec3::unit_z() * height_offset;
|
||||
|
||||
// Speech bubble, name, level, and hp bars
|
||||
overhead::Overhead::new(
|
||||
@ -2093,6 +2081,7 @@ impl Hud {
|
||||
if Some(*owner) == client.uid()
|
||||
&& !client.is_riding()
|
||||
&& is_mount.is_none()
|
||||
&& is_mountable(body, bodies.get(client.entity()))
|
||||
&& dist_sqr < common::consts::MAX_MOUNT_RANGE.powi(2) =>
|
||||
{
|
||||
vec![(GameInput::Mount, i18n.get("hud.mount").to_string())]
|
||||
|
Loading…
Reference in New Issue
Block a user