2020-12-01 00:28:00 +00:00
|
|
|
use common::{
|
2021-06-06 23:48:47 +00:00
|
|
|
combat,
|
2020-11-15 21:05:02 +00:00
|
|
|
comp::{
|
2021-03-04 20:43:58 +00:00
|
|
|
self,
|
2022-05-28 23:41:31 +00:00
|
|
|
item::MaterialStatManifest,
|
2021-01-16 17:01:57 +00:00
|
|
|
skills::{GeneralSkill, Skill},
|
2023-02-07 18:02:26 +00:00
|
|
|
Body, CharacterState, Combo, Energy, Health, Inventory, Poise, Pos, SkillSet, Stats,
|
|
|
|
StatsModifier,
|
2020-11-15 21:05:02 +00:00
|
|
|
},
|
2020-01-11 04:08:33 +00:00
|
|
|
event::{EventBus, ServerEvent},
|
2021-05-05 13:54:24 +00:00
|
|
|
resources::{DeltaTime, EntitiesDiedLastTick, Time},
|
2022-10-24 01:12:59 +00:00
|
|
|
states,
|
2019-05-17 20:47:58 +00:00
|
|
|
};
|
2021-03-08 22:40:02 +00:00
|
|
|
use common_ecs::{Job, Origin, Phase, System};
|
2021-02-22 19:27:34 +00:00
|
|
|
use specs::{
|
2022-05-28 23:41:31 +00:00
|
|
|
shred::ResourceId, Entities, Join, Read, ReadExpect, ReadStorage, SystemData, World, Write,
|
|
|
|
WriteStorage,
|
2021-02-22 19:27:34 +00:00
|
|
|
};
|
2019-05-17 20:47:58 +00:00
|
|
|
|
2021-09-14 02:16:01 +00:00
|
|
|
const ENERGY_REGEN_ACCEL: f32 = 1.0;
|
2023-02-07 18:02:26 +00:00
|
|
|
const SIT_ENERGY_REGEN_ACCEL: f32 = 2.5;
|
2020-12-16 23:30:33 +00:00
|
|
|
const POISE_REGEN_ACCEL: f32 = 2.0;
|
2019-05-17 20:47:58 +00:00
|
|
|
|
2021-02-22 19:27:34 +00:00
|
|
|
#[derive(SystemData)]
|
2021-02-22 21:02:37 +00:00
|
|
|
pub struct ReadData<'a> {
|
2021-02-22 19:27:34 +00:00
|
|
|
entities: Entities<'a>,
|
|
|
|
dt: Read<'a, DeltaTime>,
|
2021-02-27 19:55:06 +00:00
|
|
|
time: Read<'a, Time>,
|
2021-02-22 19:27:34 +00:00
|
|
|
server_bus: Read<'a, EventBus<ServerEvent>>,
|
|
|
|
positions: ReadStorage<'a, Pos>,
|
|
|
|
bodies: ReadStorage<'a, Body>,
|
|
|
|
char_states: ReadStorage<'a, CharacterState>,
|
2021-05-21 00:52:29 +00:00
|
|
|
inventories: ReadStorage<'a, Inventory>,
|
2022-05-28 23:41:31 +00:00
|
|
|
msm: ReadExpect<'a, MaterialStatManifest>,
|
2021-02-22 19:27:34 +00:00
|
|
|
}
|
|
|
|
|
2019-11-22 00:53:28 +00:00
|
|
|
/// This system kills players, levels them up, and regenerates energy.
|
2021-03-04 14:00:16 +00:00
|
|
|
#[derive(Default)]
|
2019-05-17 20:47:58 +00:00
|
|
|
pub struct Sys;
|
2021-03-08 11:13:59 +00:00
|
|
|
impl<'a> System<'a> for Sys {
|
2019-05-17 20:47:58 +00:00
|
|
|
type SystemData = (
|
2021-02-22 21:02:37 +00:00
|
|
|
ReadData<'a>,
|
2019-05-19 20:14:18 +00:00
|
|
|
WriteStorage<'a, Stats>,
|
2021-04-14 15:35:34 +00:00
|
|
|
WriteStorage<'a, SkillSet>,
|
2020-10-31 22:34:08 +00:00
|
|
|
WriteStorage<'a, Health>,
|
2020-12-10 00:32:24 +00:00
|
|
|
WriteStorage<'a, Poise>,
|
2019-11-20 18:31:36 +00:00
|
|
|
WriteStorage<'a, Energy>,
|
2021-02-27 19:55:06 +00:00
|
|
|
WriteStorage<'a, Combo>,
|
2021-05-05 13:54:24 +00:00
|
|
|
Write<'a, EntitiesDiedLastTick>,
|
2019-05-17 20:47:58 +00:00
|
|
|
);
|
|
|
|
|
2021-03-04 14:00:16 +00:00
|
|
|
const NAME: &'static str = "stats";
|
|
|
|
const ORIGIN: Origin = Origin::Common;
|
|
|
|
const PHASE: Phase = Phase::Create;
|
|
|
|
|
2019-11-20 18:31:36 +00:00
|
|
|
fn run(
|
2021-03-08 11:13:59 +00:00
|
|
|
_job: &mut Job<Self>,
|
2020-10-31 22:34:08 +00:00
|
|
|
(
|
2021-02-22 21:02:37 +00:00
|
|
|
read_data,
|
2021-04-14 15:35:34 +00:00
|
|
|
stats,
|
|
|
|
mut skill_sets,
|
2020-10-31 22:34:08 +00:00
|
|
|
mut healths,
|
2020-12-10 00:32:24 +00:00
|
|
|
mut poises,
|
2020-10-31 22:34:08 +00:00
|
|
|
mut energies,
|
2021-02-27 19:55:06 +00:00
|
|
|
mut combos,
|
2021-05-05 13:54:24 +00:00
|
|
|
mut entities_died_last_tick,
|
2020-10-31 22:34:08 +00:00
|
|
|
): Self::SystemData,
|
2019-11-20 18:31:36 +00:00
|
|
|
) {
|
2021-05-05 13:54:24 +00:00
|
|
|
entities_died_last_tick.0.clear();
|
2021-02-22 21:02:37 +00:00
|
|
|
let mut server_event_emitter = read_data.server_bus.emitter();
|
|
|
|
let dt = read_data.dt.0;
|
2019-08-23 10:11:37 +00:00
|
|
|
|
2020-07-05 12:39:28 +00:00
|
|
|
// Update stats
|
2021-12-02 06:31:20 +00:00
|
|
|
for (entity, stats, mut health, pos, mut energy, inventory) in (
|
2021-02-22 21:02:37 +00:00
|
|
|
&read_data.entities,
|
2021-04-14 15:35:34 +00:00
|
|
|
&stats,
|
2021-07-27 20:22:39 +00:00
|
|
|
&mut healths,
|
2021-02-22 21:02:37 +00:00
|
|
|
&read_data.positions,
|
2021-07-27 20:22:39 +00:00
|
|
|
&mut energies,
|
2021-05-21 00:52:29 +00:00
|
|
|
read_data.inventories.maybe(),
|
2020-10-31 22:34:08 +00:00
|
|
|
)
|
|
|
|
.join()
|
|
|
|
{
|
2021-07-27 20:22:39 +00:00
|
|
|
let set_dead = { health.should_die() && !health.is_dead };
|
2019-12-01 21:54:21 +00:00
|
|
|
|
|
|
|
if set_dead {
|
2021-05-05 13:54:24 +00:00
|
|
|
let cloned_entity = (entity, *pos);
|
|
|
|
entities_died_last_tick.0.push(cloned_entity);
|
2019-11-23 08:26:39 +00:00
|
|
|
server_event_emitter.emit(ServerEvent::Destroy {
|
2019-05-27 19:41:24 +00:00
|
|
|
entity,
|
2021-11-13 20:46:45 +00:00
|
|
|
cause: health.last_change,
|
2019-08-23 10:11:37 +00:00
|
|
|
});
|
|
|
|
|
2020-10-31 22:34:08 +00:00
|
|
|
health.is_dead = true;
|
2019-05-17 20:47:58 +00:00
|
|
|
}
|
2021-04-14 15:35:34 +00:00
|
|
|
let stat = stats;
|
2021-03-20 17:29:57 +00:00
|
|
|
|
2022-01-18 05:17:20 +00:00
|
|
|
if let Some(new_max) = health.needs_maximum_update(stat.max_health_modifiers) {
|
2022-01-19 05:56:26 +00:00
|
|
|
// Only call this if we need to since mutable access will trigger sending an
|
|
|
|
// update to the client.
|
2022-01-18 05:52:31 +00:00
|
|
|
health.update_internal_integer_maximum(new_max);
|
2021-03-20 17:29:57 +00:00
|
|
|
}
|
|
|
|
|
2022-01-18 05:17:20 +00:00
|
|
|
// Calculates energy scaling from stats and inventory
|
|
|
|
let energy_mods = StatsModifier {
|
|
|
|
add_mod: stat.max_energy_modifiers.add_mod
|
2022-05-28 23:41:31 +00:00
|
|
|
+ combat::compute_max_energy_mod(inventory, &read_data.msm),
|
2022-01-18 05:17:20 +00:00
|
|
|
mult_mod: stat.max_energy_modifiers.mult_mod,
|
2021-06-06 23:48:47 +00:00
|
|
|
};
|
|
|
|
|
2022-01-18 05:17:20 +00:00
|
|
|
if let Some(new_max) = energy.needs_maximum_update(energy_mods) {
|
2022-01-19 05:56:26 +00:00
|
|
|
// Only call this if we need to since mutable access will trigger sending an
|
|
|
|
// update to the client.
|
2022-01-18 05:52:31 +00:00
|
|
|
energy.update_internal_integer_maximum(new_max);
|
2021-06-06 23:48:47 +00:00
|
|
|
}
|
2020-07-05 12:39:28 +00:00
|
|
|
}
|
2019-11-20 18:31:36 +00:00
|
|
|
|
2020-12-31 18:37:25 +00:00
|
|
|
// Apply effects from leveling skills
|
2021-04-14 15:35:34 +00:00
|
|
|
for (mut skill_set, mut health, mut energy, body) in (
|
2021-07-27 20:22:39 +00:00
|
|
|
&mut skill_sets,
|
|
|
|
&mut healths,
|
|
|
|
&mut energies,
|
2021-02-22 21:02:37 +00:00
|
|
|
&read_data.bodies,
|
2020-12-31 18:37:25 +00:00
|
|
|
)
|
|
|
|
.join()
|
|
|
|
{
|
2021-07-27 20:22:39 +00:00
|
|
|
if skill_set.modify_health {
|
|
|
|
let health_level = skill_set
|
2021-01-16 17:01:57 +00:00
|
|
|
.skill_level(Skill::General(GeneralSkill::HealthIncrease))
|
2020-12-31 18:37:25 +00:00
|
|
|
.unwrap_or(0);
|
2021-09-09 04:07:17 +00:00
|
|
|
health.update_max_hp(*body, health_level);
|
2021-07-27 20:22:39 +00:00
|
|
|
skill_set.modify_health = false;
|
2020-12-31 18:37:25 +00:00
|
|
|
}
|
2021-07-27 20:22:39 +00:00
|
|
|
if skill_set.modify_energy {
|
|
|
|
let energy_level = skill_set
|
2021-01-16 17:01:57 +00:00
|
|
|
.skill_level(Skill::General(GeneralSkill::EnergyIncrease))
|
2021-01-04 17:16:42 +00:00
|
|
|
.unwrap_or(0);
|
2021-09-14 02:16:01 +00:00
|
|
|
energy.update_max_energy(*body, energy_level);
|
2021-04-14 15:35:34 +00:00
|
|
|
skill_set.modify_energy = false;
|
2020-12-31 18:37:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-10 00:32:24 +00:00
|
|
|
// Update energies and poises
|
2021-07-27 20:22:39 +00:00
|
|
|
for (character_state, mut energy, mut poise) in
|
|
|
|
(&read_data.char_states, &mut energies, &mut poises).join()
|
2020-07-05 12:39:28 +00:00
|
|
|
{
|
2020-02-03 21:02:32 +00:00
|
|
|
match character_state {
|
2023-02-07 18:02:26 +00:00
|
|
|
// Sitting accelerates recharging energy the most
|
|
|
|
CharacterState::Sit => {
|
|
|
|
if energy.needs_regen() {
|
|
|
|
energy.regen(SIT_ENERGY_REGEN_ACCEL, dt);
|
|
|
|
}
|
|
|
|
if poise.needs_regen() {
|
|
|
|
poise.regen(POISE_REGEN_ACCEL, dt, *read_data.time);
|
|
|
|
}
|
|
|
|
},
|
2020-06-13 11:35:31 +00:00
|
|
|
// Accelerate recharging energy.
|
2022-02-21 04:39:28 +00:00
|
|
|
CharacterState::Idle(_)
|
|
|
|
| CharacterState::Talk
|
|
|
|
| CharacterState::Dance
|
|
|
|
| CharacterState::Glide(_)
|
|
|
|
| CharacterState::Skate(_)
|
|
|
|
| CharacterState::GlideWield(_)
|
|
|
|
| CharacterState::Wielding(_)
|
|
|
|
| CharacterState::Equipping(_)
|
2022-10-24 01:12:59 +00:00
|
|
|
| CharacterState::Boost(_)
|
|
|
|
| CharacterState::ComboMelee2(states::combo_melee2::Data {
|
|
|
|
stage_section: None,
|
|
|
|
..
|
|
|
|
}) => {
|
2023-02-07 18:02:26 +00:00
|
|
|
if energy.needs_regen() {
|
|
|
|
energy.regen(ENERGY_REGEN_ACCEL, dt);
|
2020-01-19 19:19:44 +00:00
|
|
|
}
|
2023-02-07 18:02:26 +00:00
|
|
|
if poise.needs_regen() {
|
|
|
|
poise.regen(POISE_REGEN_ACCEL, dt, *read_data.time);
|
2020-12-16 23:30:33 +00:00
|
|
|
}
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2021-04-27 14:41:48 +00:00
|
|
|
// Ability use does not regen and sets the rate back to zero.
|
2022-02-21 04:39:28 +00:00
|
|
|
CharacterState::BasicMelee(_)
|
|
|
|
| CharacterState::DashMelee(_)
|
|
|
|
| CharacterState::LeapMelee(_)
|
2023-02-15 00:10:37 +00:00
|
|
|
| CharacterState::LeapShockwave(_)
|
2022-02-21 04:39:28 +00:00
|
|
|
| CharacterState::SpinMelee(_)
|
|
|
|
| CharacterState::ComboMelee(_)
|
|
|
|
| CharacterState::ComboMelee2(_)
|
|
|
|
| CharacterState::BasicRanged(_)
|
|
|
|
| CharacterState::Music(_)
|
|
|
|
| CharacterState::ChargedMelee(_)
|
|
|
|
| CharacterState::ChargedRanged(_)
|
|
|
|
| CharacterState::RepeaterRanged(_)
|
|
|
|
| CharacterState::Shockwave(_)
|
|
|
|
| CharacterState::BasicBeam(_)
|
|
|
|
| CharacterState::BasicAura(_)
|
|
|
|
| CharacterState::Blink(_)
|
2023-02-07 18:02:26 +00:00
|
|
|
| CharacterState::Climb(_)
|
2022-02-21 04:39:28 +00:00
|
|
|
| CharacterState::BasicSummon(_)
|
|
|
|
| CharacterState::SelfBuff(_)
|
|
|
|
| CharacterState::SpriteSummon(_)
|
2022-03-05 06:35:57 +00:00
|
|
|
| CharacterState::FinisherMelee(_)
|
2022-03-05 18:52:43 +00:00
|
|
|
| CharacterState::DiveMelee(_)
|
2022-03-06 01:02:08 +00:00
|
|
|
| CharacterState::RiposteMelee(_)
|
|
|
|
| CharacterState::RapidMelee(_) => {
|
2023-02-07 18:02:26 +00:00
|
|
|
if energy.needs_regen_rate_reset() {
|
|
|
|
energy.reset_regen_rate();
|
2020-01-19 19:19:44 +00:00
|
|
|
}
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2021-04-10 03:40:20 +00:00
|
|
|
// Abilities that temporarily stall energy gain, but preserve regen_rate.
|
2022-02-21 04:39:28 +00:00
|
|
|
CharacterState::Roll(_)
|
|
|
|
| CharacterState::Wallrun(_)
|
|
|
|
| CharacterState::Stunned(_)
|
|
|
|
| CharacterState::BasicBlock(_)
|
|
|
|
| CharacterState::UseItem(_)
|
|
|
|
| CharacterState::SpriteInteract(_) => {},
|
2019-08-03 19:30:01 +00:00
|
|
|
}
|
2019-05-17 20:47:58 +00:00
|
|
|
}
|
2021-01-15 03:32:12 +00:00
|
|
|
|
2021-02-27 19:55:06 +00:00
|
|
|
// Decay combo
|
|
|
|
for (_, mut combo) in (&read_data.entities, &mut combos).join() {
|
2021-03-04 20:43:58 +00:00
|
|
|
if combo.counter() > 0
|
|
|
|
&& read_data.time.0 - combo.last_increase() > comp::combo::COMBO_DECAY_START
|
|
|
|
{
|
2021-02-27 19:55:06 +00:00
|
|
|
combo.reset();
|
|
|
|
}
|
|
|
|
}
|
2019-05-17 20:47:58 +00:00
|
|
|
}
|
|
|
|
}
|