mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'payload1/add-endurance-fitness-willpower' into 'master'
endurance, fitness, willpower stats and improve movement speed based on fitness Closes #402 and #400 See merge request veloren/veloren!723
This commit is contained in:
commit
c0d2ac3ada
@ -1,3 +1,4 @@
|
|||||||
|
use crate::comp::{body::humanoid::Race, Body};
|
||||||
use crate::{comp, sync::Uid};
|
use crate::{comp, sync::Uid};
|
||||||
use specs::{Component, FlaggedStorage};
|
use specs::{Component, FlaggedStorage};
|
||||||
use specs_idvs::IDVStorage;
|
use specs_idvs::IDVStorage;
|
||||||
@ -135,7 +136,7 @@ impl Level {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn change_by(&mut self, level: u32) {
|
pub fn change_by(&mut self, level: u32) {
|
||||||
self.amount = self.amount + level;
|
self.amount += level;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,6 +147,9 @@ pub struct Stats {
|
|||||||
pub level: Level,
|
pub level: Level,
|
||||||
pub exp: Exp,
|
pub exp: Exp,
|
||||||
pub equipment: Equipment,
|
pub equipment: Equipment,
|
||||||
|
pub endurance: u32,
|
||||||
|
pub fitness: u32,
|
||||||
|
pub willpower: u32,
|
||||||
pub is_dead: bool,
|
pub is_dead: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,7 +170,23 @@ impl Stats {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Stats {
|
impl Stats {
|
||||||
pub fn new(name: String, main: Option<comp::Item>) -> Self {
|
pub fn new(name: String, body: Body, main: Option<comp::Item>) -> Self {
|
||||||
|
let race = if let comp::Body::Humanoid(hbody) = body {
|
||||||
|
Some(hbody.race)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let (endurance, fitness, willpower) = match race {
|
||||||
|
Some(Race::Danari) => (0, 2, 3), // Small, flexible, intelligent, physically weak
|
||||||
|
Some(Race::Dwarf) => (2, 2, 1), // phyiscally strong, intelligent, slow reflexes
|
||||||
|
Some(Race::Elf) => (1, 2, 2), // Intelligent, quick, physically weak
|
||||||
|
Some(Race::Human) => (2, 1, 2), // Perfectly balanced
|
||||||
|
Some(Race::Orc) => (3, 2, 0), // Physically strong, non intelligent, medium reflexes
|
||||||
|
Some(Race::Undead) => (1, 3, 1), // Very good reflexes, equally intelligent and strong
|
||||||
|
None => (0, 0, 0),
|
||||||
|
};
|
||||||
|
|
||||||
let mut stats = Self {
|
let mut stats = Self {
|
||||||
name,
|
name,
|
||||||
health: Health {
|
health: Health {
|
||||||
@ -186,6 +206,9 @@ impl Stats {
|
|||||||
maximum: 50,
|
maximum: 50,
|
||||||
},
|
},
|
||||||
equipment: Equipment { main, alt: None },
|
equipment: Equipment { main, alt: None },
|
||||||
|
endurance,
|
||||||
|
fitness,
|
||||||
|
willpower,
|
||||||
is_dead: false,
|
is_dead: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -15,13 +15,13 @@ use vek::*;
|
|||||||
|
|
||||||
pub const ROLL_DURATION: Duration = Duration::from_millis(600);
|
pub const ROLL_DURATION: Duration = Duration::from_millis(600);
|
||||||
|
|
||||||
const HUMANOID_ACCEL: f32 = 100.0;
|
const BASE_HUMANOID_ACCEL: f32 = 100.0;
|
||||||
const HUMANOID_SPEED: f32 = 120.0;
|
const BASE_HUMANOID_SPEED: f32 = 120.0;
|
||||||
const HUMANOID_AIR_ACCEL: f32 = 15.0;
|
const BASE_HUMANOID_AIR_ACCEL: f32 = 15.0;
|
||||||
const HUMANOID_AIR_SPEED: f32 = 100.0;
|
const BASE_HUMANOID_AIR_SPEED: f32 = 100.0;
|
||||||
const HUMANOID_WATER_ACCEL: f32 = 70.0;
|
const BASE_HUMANOID_WATER_ACCEL: f32 = 70.0;
|
||||||
const HUMANOID_WATER_SPEED: f32 = 120.0;
|
const BASE_HUMANOID_WATER_SPEED: f32 = 120.0;
|
||||||
const HUMANOID_CLIMB_ACCEL: f32 = 10.0;
|
const BASE_HUMANOID_CLIMB_ACCEL: f32 = 10.0;
|
||||||
const ROLL_SPEED: f32 = 17.0;
|
const ROLL_SPEED: f32 = 17.0;
|
||||||
const CHARGE_SPEED: f32 = 20.0;
|
const CHARGE_SPEED: f32 = 20.0;
|
||||||
const GLIDE_ACCEL: f32 = 15.0;
|
const GLIDE_ACCEL: f32 = 15.0;
|
||||||
@ -142,24 +142,33 @@ impl<'a> System<'a> for Sys {
|
|||||||
vel.0 += Vec2::broadcast(dt.0)
|
vel.0 += Vec2::broadcast(dt.0)
|
||||||
* inputs.move_dir
|
* inputs.move_dir
|
||||||
* match (physics.on_ground, &character.movement) {
|
* match (physics.on_ground, &character.movement) {
|
||||||
(true, Run) if vel.0.magnitude_squared() < HUMANOID_SPEED.powf(2.0) => {
|
(true, Run)
|
||||||
HUMANOID_ACCEL
|
if vel.0.magnitude_squared()
|
||||||
|
< (BASE_HUMANOID_SPEED + stats.fitness as f32 * 50.0).powf(2.0) =>
|
||||||
|
{
|
||||||
|
BASE_HUMANOID_ACCEL
|
||||||
}
|
}
|
||||||
(false, Climb) if vel.0.magnitude_squared() < HUMANOID_SPEED.powf(2.0) => {
|
(false, Climb)
|
||||||
HUMANOID_CLIMB_ACCEL
|
if vel.0.magnitude_squared() < BASE_HUMANOID_SPEED.powf(2.0) =>
|
||||||
|
{
|
||||||
|
BASE_HUMANOID_CLIMB_ACCEL
|
||||||
}
|
}
|
||||||
(false, Glide) if vel.0.magnitude_squared() < GLIDE_SPEED.powf(2.0) => {
|
(false, Glide) if vel.0.magnitude_squared() < GLIDE_SPEED.powf(2.0) => {
|
||||||
GLIDE_ACCEL
|
GLIDE_ACCEL
|
||||||
}
|
}
|
||||||
(false, Fall) | (false, Jump)
|
(false, Fall) | (false, Jump)
|
||||||
if vel.0.magnitude_squared() < HUMANOID_AIR_SPEED.powf(2.0) =>
|
if vel.0.magnitude_squared()
|
||||||
|
< (BASE_HUMANOID_AIR_SPEED + stats.fitness as f32 * 10.0)
|
||||||
|
.powf(2.0) =>
|
||||||
{
|
{
|
||||||
HUMANOID_AIR_ACCEL
|
BASE_HUMANOID_AIR_ACCEL
|
||||||
}
|
}
|
||||||
(false, Swim)
|
(false, Swim)
|
||||||
if vel.0.magnitude_squared() < HUMANOID_WATER_SPEED.powf(2.0) =>
|
if vel.0.magnitude_squared()
|
||||||
|
< (BASE_HUMANOID_WATER_SPEED + stats.fitness as f32 * 30.0)
|
||||||
|
.powf(2.0) =>
|
||||||
{
|
{
|
||||||
HUMANOID_WATER_ACCEL
|
BASE_HUMANOID_WATER_ACCEL + stats.fitness as f32 * 10.0
|
||||||
}
|
}
|
||||||
_ => 0.0,
|
_ => 0.0,
|
||||||
};
|
};
|
||||||
@ -228,7 +237,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if character.movement == Swim && inputs.jump.is_pressed() {
|
if character.movement == Swim && inputs.jump.is_pressed() {
|
||||||
vel.0.z = (vel.0.z + dt.0 * GRAVITY * 1.25).min(HUMANOID_WATER_SPEED);
|
vel.0.z = (vel.0.z + dt.0 * GRAVITY * 1.25).min(BASE_HUMANOID_WATER_SPEED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
|
|
||||||
stat.update_max_hp();
|
stat.update_max_hp();
|
||||||
stat.health
|
stat.health
|
||||||
.set_to(stat.health.maximum(), HealthSource::LevelUp)
|
.set_to(stat.health.maximum(), HealthSource::LevelUp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accelerate recharging energy if not wielding.
|
// Accelerate recharging energy if not wielding.
|
||||||
|
@ -484,9 +484,14 @@ fn handle_spawn(server: &mut Server, entity: EcsEntity, args: String, action: &C
|
|||||||
);
|
);
|
||||||
|
|
||||||
let body = kind_to_body(id);
|
let body = kind_to_body(id);
|
||||||
|
|
||||||
let new_entity = server
|
let new_entity = server
|
||||||
.state
|
.state
|
||||||
.create_npc(pos, comp::Stats::new(get_npc_name(id), None), body)
|
.create_npc(
|
||||||
|
pos,
|
||||||
|
comp::Stats::new(get_npc_name(id), body, None),
|
||||||
|
body,
|
||||||
|
)
|
||||||
.with(comp::Vel(vel))
|
.with(comp::Vel(vel))
|
||||||
.with(comp::MountState::Unmounted)
|
.with(comp::MountState::Unmounted)
|
||||||
.with(agent.clone())
|
.with(agent.clone())
|
||||||
|
@ -257,7 +257,7 @@ impl Server {
|
|||||||
let spawn_point = state.ecs().read_resource::<SpawnPoint>().0;
|
let spawn_point = state.ecs().read_resource::<SpawnPoint>().0;
|
||||||
|
|
||||||
state.write_component(entity, body);
|
state.write_component(entity, body);
|
||||||
state.write_component(entity, comp::Stats::new(name, main));
|
state.write_component(entity, comp::Stats::new(name, body, main));
|
||||||
state.write_component(entity, comp::Energy::new(1000));
|
state.write_component(entity, comp::Energy::new(1000));
|
||||||
state.write_component(entity, comp::Controller::default());
|
state.write_component(entity, comp::Controller::default());
|
||||||
state.write_component(entity, comp::Pos(spawn_point));
|
state.write_component(entity, comp::Pos(spawn_point));
|
||||||
@ -501,11 +501,10 @@ impl Server {
|
|||||||
.get(entity)
|
.get(entity)
|
||||||
.map(|inv| !inv.is_full())
|
.map(|inv| !inv.is_full())
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
|
&& state.try_set_block(pos, Block::empty()).is_some()
|
||||||
{
|
{
|
||||||
if state.try_set_block(pos, Block::empty()).is_some() {
|
comp::Item::try_reclaim_from_block(block)
|
||||||
comp::Item::try_reclaim_from_block(block)
|
.map(|item| state.give_item(entity, item));
|
||||||
.map(|item| state.give_item(entity, item));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -517,8 +516,8 @@ impl Server {
|
|||||||
.get_mut(entity)
|
.get_mut(entity)
|
||||||
.and_then(|inv| inv.remove(slot));
|
.and_then(|inv| inv.remove(slot));
|
||||||
|
|
||||||
match item_opt {
|
if let Some(item) = item_opt {
|
||||||
Some(item) => match item.kind {
|
match item.kind {
|
||||||
comp::ItemKind::Tool { .. } => {
|
comp::ItemKind::Tool { .. } => {
|
||||||
if let Some(stats) = state
|
if let Some(stats) = state
|
||||||
.ecs()
|
.ecs()
|
||||||
@ -548,8 +547,7 @@ impl Server {
|
|||||||
.get_mut(entity)
|
.get_mut(entity)
|
||||||
.map(|inv| inv.insert(slot, item));
|
.map(|inv| inv.insert(slot, item));
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state.write_component(entity, comp::InventoryUpdate);
|
state.write_component(entity, comp::InventoryUpdate);
|
||||||
|
@ -97,15 +97,16 @@ impl<'a> System<'a> for Sys {
|
|||||||
// Handle chunk supplement
|
// Handle chunk supplement
|
||||||
for npc in supplement.npcs {
|
for npc in supplement.npcs {
|
||||||
let (mut stats, mut body) = if rand::random() {
|
let (mut stats, mut body) = if rand::random() {
|
||||||
|
let body = comp::Body::Humanoid(comp::humanoid::Body::random());
|
||||||
let stats = comp::Stats::new(
|
let stats = comp::Stats::new(
|
||||||
"Traveler".to_string(),
|
"Traveler".to_string(),
|
||||||
|
body,
|
||||||
Some(assets::load_expect_cloned("common.items.weapons.staff_1")),
|
Some(assets::load_expect_cloned("common.items.weapons.staff_1")),
|
||||||
);
|
);
|
||||||
let body = comp::Body::Humanoid(comp::humanoid::Body::random());
|
|
||||||
(stats, body)
|
(stats, body)
|
||||||
} else {
|
} else {
|
||||||
let stats = comp::Stats::new("Wolf".to_string(), None);
|
|
||||||
let body = comp::Body::QuadrupedMedium(comp::quadruped_medium::Body::random());
|
let body = comp::Body::QuadrupedMedium(comp::quadruped_medium::Body::random());
|
||||||
|
let stats = comp::Stats::new("Wolf".to_string(), body, None);
|
||||||
(stats, body)
|
(stats, body)
|
||||||
};
|
};
|
||||||
let mut scale = 1.0;
|
let mut scale = 1.0;
|
||||||
@ -115,11 +116,13 @@ impl<'a> System<'a> for Sys {
|
|||||||
|
|
||||||
if npc.boss {
|
if npc.boss {
|
||||||
if rand::random::<f32>() < 0.8 {
|
if rand::random::<f32>() < 0.8 {
|
||||||
|
let hbody = comp::humanoid::Body::random();
|
||||||
|
body = comp::Body::Humanoid(hbody);
|
||||||
stats = comp::Stats::new(
|
stats = comp::Stats::new(
|
||||||
"Fearless Wanderer".to_string(),
|
"Fearless Wanderer".to_string(),
|
||||||
|
body,
|
||||||
Some(assets::load_expect_cloned("common.items.weapons.hammer_1")),
|
Some(assets::load_expect_cloned("common.items.weapons.hammer_1")),
|
||||||
);
|
);
|
||||||
body = comp::Body::Humanoid(comp::humanoid::Body::random());
|
|
||||||
}
|
}
|
||||||
stats.level.set_level(rand::thread_rng().gen_range(8, 15));
|
stats.level.set_level(rand::thread_rng().gen_range(8, 15));
|
||||||
scale = 2.0 + rand::random::<f32>();
|
scale = 2.0 + rand::random::<f32>();
|
||||||
|
@ -116,13 +116,13 @@ fn main() {
|
|||||||
panic!("Failed to save settings: {:?}", err);
|
panic!("Failed to save settings: {:?}", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut audio = if settings.audio.audio_on {
|
let audio_device = || match &settings.audio.audio_device {
|
||||||
let audio_device = match &settings.audio.audio_device {
|
Some(d) => d.to_string(),
|
||||||
Some(d) => d.to_string(),
|
None => audio::get_default_device(),
|
||||||
None => audio::get_default_device(),
|
};
|
||||||
};
|
|
||||||
|
|
||||||
AudioFrontend::new(audio_device, 16)
|
let mut audio = if settings.audio.audio_on {
|
||||||
|
AudioFrontend::new(audio_device(), 16)
|
||||||
} else {
|
} else {
|
||||||
AudioFrontend::no_audio()
|
AudioFrontend::no_audio()
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user