mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Make charging take a discrete amount of energy and change energy
regeneration to use floats so it is smoother and tickrate-independent.
This commit is contained in:
committed by
Pfauenauge90
parent
b4337e57aa
commit
c10c31043c
@ -5,7 +5,7 @@ use specs_idvs::IDVStorage;
|
|||||||
pub struct Energy {
|
pub struct Energy {
|
||||||
current: u32,
|
current: u32,
|
||||||
maximum: u32,
|
maximum: u32,
|
||||||
pub regen_rate: i32,
|
pub regen_rate: f32,
|
||||||
pub last_change: Option<(i32, f64, EnergySource)>,
|
pub last_change: Option<(i32, f64, EnergySource)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17,12 +17,18 @@ pub enum EnergySource {
|
|||||||
Unknown,
|
Unknown,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum StatChangeError {
|
||||||
|
Underflow,
|
||||||
|
Overflow,
|
||||||
|
}
|
||||||
|
|
||||||
impl Energy {
|
impl Energy {
|
||||||
pub fn new(amount: u32) -> Energy {
|
pub fn new(amount: u32) -> Energy {
|
||||||
Energy {
|
Energy {
|
||||||
current: amount,
|
current: amount,
|
||||||
maximum: amount,
|
maximum: amount,
|
||||||
regen_rate: 0,
|
regen_rate: 0.0,
|
||||||
last_change: None,
|
last_change: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,6 +52,21 @@ impl Energy {
|
|||||||
self.last_change = Some((amount, 0.0, cause));
|
self.last_change = Some((amount, 0.0, cause));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn try_change_by(
|
||||||
|
&mut self,
|
||||||
|
amount: i32,
|
||||||
|
cause: EnergySource,
|
||||||
|
) -> Result<(), StatChangeError> {
|
||||||
|
if self.current as i32 + amount < 0 {
|
||||||
|
Err(StatChangeError::Underflow)
|
||||||
|
} else if self.current as i32 + amount > self.maximum as i32 {
|
||||||
|
Err(StatChangeError::Overflow)
|
||||||
|
} else {
|
||||||
|
self.change_by(amount, cause);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_maximum(&mut self, amount: u32) {
|
pub fn set_maximum(&mut self, amount: u32) {
|
||||||
self.maximum = amount;
|
self.maximum = amount;
|
||||||
self.current = self.current.min(self.maximum);
|
self.current = self.current.min(self.maximum);
|
||||||
|
@ -76,6 +76,26 @@ impl Health {
|
|||||||
self.current = self.current.min(self.maximum);
|
self.current = self.current.min(self.maximum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum StatChangeError {
|
||||||
|
Underflow,
|
||||||
|
Overflow,
|
||||||
|
}
|
||||||
|
use std::error::Error;
|
||||||
|
use std::fmt;
|
||||||
|
impl fmt::Display for StatChangeError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}",
|
||||||
|
match self {
|
||||||
|
Self::Underflow => "insufficient stat quantity",
|
||||||
|
Self::Overflow => "stat quantity would overflow",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Error for StatChangeError {}
|
||||||
|
|
||||||
impl Exp {
|
impl Exp {
|
||||||
pub fn current(&self) -> u32 {
|
pub fn current(&self) -> u32 {
|
||||||
|
@ -2,8 +2,8 @@ use super::movement::ROLL_DURATION;
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp::{
|
comp::{
|
||||||
self, item, projectile, ActionState, ActionState::*, Body, CharacterState, ControlEvent,
|
self, item, projectile, ActionState, ActionState::*, Body, CharacterState, ControlEvent,
|
||||||
Controller, ControllerInputs, HealthChange, HealthSource, ItemKind, Mounting,
|
Controller, ControllerInputs, Energy, EnergySource, HealthChange, HealthSource, ItemKind,
|
||||||
MovementState, MovementState::*, PhysicsState, Projectile, Stats, Vel,
|
Mounting, MovementState, MovementState::*, PhysicsState, Projectile, Stats, Vel,
|
||||||
},
|
},
|
||||||
event::{Emitter, EventBus, LocalEvent, ServerEvent},
|
event::{Emitter, EventBus, LocalEvent, ServerEvent},
|
||||||
state::DeltaTime,
|
state::DeltaTime,
|
||||||
@ -16,6 +16,8 @@ use specs::{
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
|
const CHARGE_COST: i32 = 50;
|
||||||
|
|
||||||
/// # Controller System
|
/// # Controller System
|
||||||
/// #### Responsible for validating controller inputs and setting new Character States
|
/// #### Responsible for validating controller inputs and setting new Character States
|
||||||
/// ----
|
/// ----
|
||||||
@ -247,6 +249,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
WriteStorage<'a, Controller>,
|
WriteStorage<'a, Controller>,
|
||||||
WriteStorage<'a, CharacterState>,
|
WriteStorage<'a, CharacterState>,
|
||||||
ReadStorage<'a, Stats>,
|
ReadStorage<'a, Stats>,
|
||||||
|
WriteStorage<'a, Energy>,
|
||||||
ReadStorage<'a, Body>,
|
ReadStorage<'a, Body>,
|
||||||
ReadStorage<'a, Vel>,
|
ReadStorage<'a, Vel>,
|
||||||
ReadStorage<'a, PhysicsState>,
|
ReadStorage<'a, PhysicsState>,
|
||||||
@ -264,6 +267,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
mut controllers,
|
mut controllers,
|
||||||
mut character_states,
|
mut character_states,
|
||||||
stats,
|
stats,
|
||||||
|
mut energies,
|
||||||
bodies,
|
bodies,
|
||||||
velocities,
|
velocities,
|
||||||
physics_states,
|
physics_states,
|
||||||
@ -273,12 +277,13 @@ impl<'a> System<'a> for Sys {
|
|||||||
) {
|
) {
|
||||||
let mut server_emitter = server_bus.emitter();
|
let mut server_emitter = server_bus.emitter();
|
||||||
let mut local_emitter = local_bus.emitter();
|
let mut local_emitter = local_bus.emitter();
|
||||||
for (entity, uid, controller, mut character, stats, body, vel, physics, mount) in (
|
for (entity, uid, controller, mut character, stats, energy, body, vel, physics, mount) in (
|
||||||
&entities,
|
&entities,
|
||||||
&uids,
|
&uids,
|
||||||
&mut controllers,
|
&mut controllers,
|
||||||
&mut character_states,
|
&mut character_states,
|
||||||
&stats,
|
&stats,
|
||||||
|
&mut energies,
|
||||||
&bodies,
|
&bodies,
|
||||||
&velocities,
|
&velocities,
|
||||||
&physics_states,
|
&physics_states,
|
||||||
@ -579,9 +584,14 @@ impl<'a> System<'a> for Sys {
|
|||||||
|
|
||||||
// Try to charge
|
// Try to charge
|
||||||
if inputs.charge.is_pressed() && !inputs.charge.is_held_down() {
|
if inputs.charge.is_pressed() && !inputs.charge.is_held_down() {
|
||||||
|
if energy
|
||||||
|
.try_change_by(-CHARGE_COST, EnergySource::CastSpell)
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
character.action = Charge {
|
character.action = Charge {
|
||||||
time_left: Duration::from_millis(250),
|
time_left: Duration::from_millis(250),
|
||||||
};
|
}
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,12 +5,9 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage};
|
use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage};
|
||||||
|
|
||||||
const ENERGY_REGEN_ACCEL: i32 = 1;
|
const ENERGY_REGEN_ACCEL: f32 = 1.0;
|
||||||
const BLOCK_COST: i32 = 50;
|
|
||||||
const ROLL_CHARGE_COST: i32 = 200;
|
|
||||||
|
|
||||||
/// This system kills players
|
/// This system kills players, levels them up, and regenerates energy.
|
||||||
/// and handles players levelling up
|
|
||||||
pub struct Sys;
|
pub struct Sys;
|
||||||
impl<'a> System<'a> for Sys {
|
impl<'a> System<'a> for Sys {
|
||||||
type SystemData = (
|
type SystemData = (
|
||||||
@ -75,25 +72,15 @@ impl<'a> System<'a> for Sys {
|
|||||||
.set_to(stat.health.maximum(), HealthSource::LevelUp)
|
.set_to(stat.health.maximum(), HealthSource::LevelUp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recharge energy if not wielding, and accelerate.
|
// Accelerate recharging energy if not wielding.
|
||||||
match character_state.action {
|
match character_state.action {
|
||||||
ActionState::Wield { .. } | ActionState::Attack { .. } => energy.regen_rate = 0,
|
|
||||||
ActionState::Block { .. } => {
|
|
||||||
energy.change_by(framerate_dt(-BLOCK_COST, dt.0), EnergySource::CastSpell)
|
|
||||||
}
|
|
||||||
ActionState::Roll { .. } | ActionState::Charge { .. } => energy.change_by(
|
|
||||||
framerate_dt(-ROLL_CHARGE_COST, dt.0),
|
|
||||||
EnergySource::CastSpell,
|
|
||||||
),
|
|
||||||
ActionState::Idle => {
|
ActionState::Idle => {
|
||||||
energy.regen_rate += ENERGY_REGEN_ACCEL;
|
energy.regen_rate += ENERGY_REGEN_ACCEL * dt.0;
|
||||||
energy.change_by(energy.regen_rate, EnergySource::Regen);
|
energy.change_by(energy.regen_rate as i32, EnergySource::Regen);
|
||||||
}
|
}
|
||||||
|
// All other states do not regen and set the rate back to zero.
|
||||||
|
_ => energy.regen_rate = 0.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Convience method to scale an integer by dt
|
|
||||||
fn framerate_dt(a: i32, dt: f32) -> i32 {
|
|
||||||
(a as f32 * (dt)) as i32
|
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user