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:
parent
b4337e57aa
commit
c10c31043c
@ -5,7 +5,7 @@ use specs_idvs::IDVStorage;
|
||||
pub struct Energy {
|
||||
current: u32,
|
||||
maximum: u32,
|
||||
pub regen_rate: i32,
|
||||
pub regen_rate: f32,
|
||||
pub last_change: Option<(i32, f64, EnergySource)>,
|
||||
}
|
||||
|
||||
@ -17,12 +17,18 @@ pub enum EnergySource {
|
||||
Unknown,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum StatChangeError {
|
||||
Underflow,
|
||||
Overflow,
|
||||
}
|
||||
|
||||
impl Energy {
|
||||
pub fn new(amount: u32) -> Energy {
|
||||
Energy {
|
||||
current: amount,
|
||||
maximum: amount,
|
||||
regen_rate: 0,
|
||||
regen_rate: 0.0,
|
||||
last_change: None,
|
||||
}
|
||||
}
|
||||
@ -46,6 +52,21 @@ impl Energy {
|
||||
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) {
|
||||
self.maximum = amount;
|
||||
self.current = self.current.min(self.maximum);
|
||||
|
@ -76,6 +76,26 @@ impl Health {
|
||||
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 {
|
||||
pub fn current(&self) -> u32 {
|
||||
|
@ -2,8 +2,8 @@ use super::movement::ROLL_DURATION;
|
||||
use crate::{
|
||||
comp::{
|
||||
self, item, projectile, ActionState, ActionState::*, Body, CharacterState, ControlEvent,
|
||||
Controller, ControllerInputs, HealthChange, HealthSource, ItemKind, Mounting,
|
||||
MovementState, MovementState::*, PhysicsState, Projectile, Stats, Vel,
|
||||
Controller, ControllerInputs, Energy, EnergySource, HealthChange, HealthSource, ItemKind,
|
||||
Mounting, MovementState, MovementState::*, PhysicsState, Projectile, Stats, Vel,
|
||||
},
|
||||
event::{Emitter, EventBus, LocalEvent, ServerEvent},
|
||||
state::DeltaTime,
|
||||
@ -16,6 +16,8 @@ use specs::{
|
||||
use std::time::Duration;
|
||||
use vek::*;
|
||||
|
||||
const CHARGE_COST: i32 = 50;
|
||||
|
||||
/// # Controller System
|
||||
/// #### 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, CharacterState>,
|
||||
ReadStorage<'a, Stats>,
|
||||
WriteStorage<'a, Energy>,
|
||||
ReadStorage<'a, Body>,
|
||||
ReadStorage<'a, Vel>,
|
||||
ReadStorage<'a, PhysicsState>,
|
||||
@ -264,6 +267,7 @@ impl<'a> System<'a> for Sys {
|
||||
mut controllers,
|
||||
mut character_states,
|
||||
stats,
|
||||
mut energies,
|
||||
bodies,
|
||||
velocities,
|
||||
physics_states,
|
||||
@ -273,12 +277,13 @@ impl<'a> System<'a> for Sys {
|
||||
) {
|
||||
let mut server_emitter = server_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,
|
||||
&uids,
|
||||
&mut controllers,
|
||||
&mut character_states,
|
||||
&stats,
|
||||
&mut energies,
|
||||
&bodies,
|
||||
&velocities,
|
||||
&physics_states,
|
||||
@ -579,9 +584,14 @@ impl<'a> System<'a> for Sys {
|
||||
|
||||
// Try to charge
|
||||
if inputs.charge.is_pressed() && !inputs.charge.is_held_down() {
|
||||
character.action = Charge {
|
||||
time_left: Duration::from_millis(250),
|
||||
};
|
||||
if energy
|
||||
.try_change_by(-CHARGE_COST, EnergySource::CastSpell)
|
||||
.is_ok()
|
||||
{
|
||||
character.action = Charge {
|
||||
time_left: Duration::from_millis(250),
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -5,12 +5,9 @@ use crate::{
|
||||
};
|
||||
use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage};
|
||||
|
||||
const ENERGY_REGEN_ACCEL: i32 = 1;
|
||||
const BLOCK_COST: i32 = 50;
|
||||
const ROLL_CHARGE_COST: i32 = 200;
|
||||
const ENERGY_REGEN_ACCEL: f32 = 1.0;
|
||||
|
||||
/// This system kills players
|
||||
/// and handles players levelling up
|
||||
/// This system kills players, levels them up, and regenerates energy.
|
||||
pub struct Sys;
|
||||
impl<'a> System<'a> for Sys {
|
||||
type SystemData = (
|
||||
@ -75,25 +72,15 @@ impl<'a> System<'a> for Sys {
|
||||
.set_to(stat.health.maximum(), HealthSource::LevelUp)
|
||||
}
|
||||
|
||||
// Recharge energy if not wielding, and accelerate.
|
||||
// Accelerate recharging energy if not wielding.
|
||||
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 => {
|
||||
energy.regen_rate += ENERGY_REGEN_ACCEL;
|
||||
energy.change_by(energy.regen_rate, EnergySource::Regen);
|
||||
energy.regen_rate += ENERGY_REGEN_ACCEL * dt.0;
|
||||
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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user