Combo counter now uses outcomes.

This commit is contained in:
Sam 2021-03-04 15:43:58 -05:00
parent c29cb037e7
commit 940b4b5de7
7 changed files with 112 additions and 85 deletions

View File

@ -2,6 +2,8 @@ use serde::{Deserialize, Serialize};
use specs::{Component, DerefFlaggedStorage};
use specs_idvs::IdvStorage;
pub const COMBO_DECAY_START: f64 = 5.0; // seconds
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub struct Combo {
counter: u32,
@ -24,14 +26,14 @@ impl Combo {
pub fn reset(&mut self) { self.counter = 0; }
pub fn increase_by(&mut self, amount: u32, time: f64) {
self.counter = self.counter.saturating_add(amount);
pub fn change_by(&mut self, amount: i32, time: f64) {
if amount > 0 {
self.counter = self.counter.saturating_add(amount as u32);
} else {
self.counter = self.counter.saturating_sub(amount.abs() as u32);
}
self.last_increase = time;
}
pub fn decrease_by(&mut self, amount: u32) {
self.counter = self.counter.saturating_sub(amount);
}
}
impl Component for Combo {

View File

@ -37,16 +37,20 @@ pub enum Outcome {
// TODO: Access ECS to get position from Uid to conserve bandwidth
pos: Vec3<f32>,
},
ComboChange {
uid: Uid,
combo: u32,
},
}
impl Outcome {
pub fn get_pos(&self) -> Option<Vec3<f32>> {
match self {
Outcome::Explosion { pos, .. } => Some(*pos),
Outcome::ProjectileShot { pos, .. } => Some(*pos),
Outcome::Beam { pos, .. } => Some(*pos),
Outcome::ExpChange { .. } => None,
Outcome::SkillPointGain { pos, .. } => Some(*pos),
Outcome::Explosion { pos, .. }
| Outcome::ProjectileShot { pos, .. }
| Outcome::Beam { pos, .. }
| Outcome::SkillPointGain { pos, .. } => Some(*pos),
Outcome::ExpChange { .. } | Outcome::ComboChange { .. } => None,
}
}
}

View File

@ -1,5 +1,6 @@
use common::{
comp::{
self,
skills::{GeneralSkill, Skill},
Body, CharacterState, Combo, Energy, EnergyChange, EnergySource, Health, Poise,
PoiseChange, PoiseSource, Pos, Stats,
@ -18,7 +19,6 @@ use vek::Vec3;
const ENERGY_REGEN_ACCEL: f32 = 10.0;
const POISE_REGEN_ACCEL: f32 = 2.0;
const COMBO_DECAY_START: f64 = 5.0; // seconds
#[derive(SystemData)]
pub struct ReadData<'a> {
@ -264,7 +264,9 @@ impl<'a> System<'a> for Sys {
// Decay combo
for (_, mut combo) in (&read_data.entities, &mut combos).join() {
if combo.counter() > 0 && read_data.time.0 - combo.last_increase() > COMBO_DECAY_START {
if combo.counter() > 0
&& read_data.time.0 - combo.last_increase() > comp::combo::COMBO_DECAY_START
{
combo.reset();
}
}

View File

@ -895,11 +895,14 @@ fn handle_exp_gain(
pub fn handle_combo_change(server: &Server, entity: EcsEntity, change: i32) {
let ecs = &server.state.ecs();
if let Some(mut combo) = ecs.write_storage::<comp::Combo>().get_mut(entity) {
if change > 0 {
let time = ecs.read_resource::<Time>();
combo.increase_by(change as u32, time.0);
} else {
combo.decrease_by(change.abs() as u32);
let time = ecs.read_resource::<Time>();
let mut outcomes = ecs.write_resource::<Vec<Outcome>>();
combo.change_by(change, time.0);
if let Some(uid) = ecs.read_storage::<Uid>().get(entity) {
outcomes.push(Outcome::ComboChange {
uid: *uid,
combo: combo.counter(),
});
}
}
}

View File

@ -364,7 +364,7 @@ impl SfxMgr {
audio.play_sfx(file_ref, *pos, None);
},
},
Outcome::ExpChange { .. } => {},
Outcome::ExpChange { .. } | Outcome::ComboChange { .. } => {},
}
}

View File

@ -61,7 +61,6 @@ use crate::{
GlobalState,
};
use client::Client;
use common::resources::Time;
use common::{
combat,
comp::{
@ -309,6 +308,13 @@ pub struct SkillPointGain {
pub timer: f32,
}
#[derive(Debug, Clone, Copy)]
pub struct ComboFloater {
pub owner: Uid,
pub combo: u32,
pub timer: f64,
}
pub struct DebugInfo {
pub tps: f64,
pub frame_time: Duration,
@ -732,6 +738,7 @@ pub struct Hud {
crosshair_opacity: f32,
exp_floaters: Vec<ExpFloater>,
skill_point_displays: Vec<SkillPointGain>,
combo_floaters: VecDeque<ComboFloater>,
}
impl Hud {
@ -840,6 +847,7 @@ impl Hud {
crosshair_opacity: 0.0,
exp_floaters: Vec::new(),
skill_point_displays: Vec::new(),
combo_floaters: VecDeque::new(),
}
}
@ -887,7 +895,7 @@ impl Hud {
let items = ecs.read_storage::<comp::Item>();
let inventories = ecs.read_storage::<comp::Inventory>();
let msm = ecs.read_resource::<MaterialStatManifest>();
let entities = ecs.entities();
let entities = ecs.entities();
let me = client.entity();
if (client.pending_trade().is_some() && !self.show.trade)
@ -2158,8 +2166,19 @@ impl Hud {
let controllers = ecs.read_storage::<comp::Controller>();
let ability_map = ecs.fetch::<comp::item::tool::AbilityMap>();
let bodies = ecs.read_storage::<comp::Body>();
let combos = ecs.read_storage::<comp::Combo>();
let time = ecs.read_resource::<Time>();
// Combo floater stuffs
for combo_floater in self.combo_floaters.iter_mut() {
combo_floater.timer -= dt.as_secs_f64();
}
self.combo_floaters.retain(|f| f.timer > 0_f64);
let combo = if let Some(uid) = ecs.read_storage::<Uid>().get(entity) {
self.combo_floaters
.iter()
.find(|c| c.owner == *uid)
.copied()
} else {
None
};
if let (
Some(health),
@ -2167,16 +2186,12 @@ impl Hud {
Some(energy),
Some(_character_state),
Some(_controller),
Some(combo),
time,
) = (
healths.get(entity),
inventories.get(entity),
energies.get(entity),
character_states.get(entity),
controllers.get(entity).map(|c| &c.inputs),
combos.get(entity),
time,
) {
Skillbar::new(
global_state,
@ -2196,8 +2211,7 @@ impl Hud {
i18n,
&ability_map,
&msm,
&combo,
&time,
combo,
)
.set(self.ids.skillbar, ui_widgets);
}
@ -3211,6 +3225,11 @@ impl Hud {
total_points: *total_points,
timer: 5.0,
}),
Outcome::ComboChange { uid, combo } => self.combo_floaters.push_front(ComboFloater {
owner: *uid,
combo: *combo,
timer: comp::combo::COMBO_DECAY_START,
}),
_ => {},
}
}

View File

@ -6,6 +6,7 @@ use super::{
STAMINA_COLOR, TEXT_COLOR, UI_HIGHLIGHT_0,
};
use crate::{
hud::ComboFloater,
i18n::Localization,
ui::{
fonts::Fonts,
@ -15,16 +16,14 @@ use crate::{
window::GameInput,
GlobalState,
};
use common::{
comp::{
inventory::slot::EquipSlot,
item::{
tool::{AbilityMap, Tool, ToolKind},
Hands, Item, ItemKind, MaterialStatManifest,
},
Combo, Energy, Health, Inventory,
use common::comp::{
self,
inventory::slot::EquipSlot,
item::{
tool::{AbilityMap, Tool, ToolKind},
Hands, Item, ItemKind, MaterialStatManifest,
},
resources::Time,
Energy, Health, Inventory,
};
use conrod_core::{
color,
@ -149,8 +148,7 @@ pub struct Skillbar<'a> {
common: widget::CommonBuilder,
ability_map: &'a AbilityMap,
msm: &'a MaterialStatManifest,
combo: &'a Combo,
time: &'a Time,
combo: Option<ComboFloater>,
}
impl<'a> Skillbar<'a> {
@ -173,8 +171,7 @@ impl<'a> Skillbar<'a> {
localized_strings: &'a Localization,
ability_map: &'a AbilityMap,
msm: &'a MaterialStatManifest,
combo: &'a Combo,
time: &'a Time,
combo: Option<ComboFloater>,
) -> Self {
Self {
global_state,
@ -196,7 +193,6 @@ impl<'a> Skillbar<'a> {
ability_map,
msm,
combo,
time,
}
}
}
@ -925,49 +921,50 @@ impl<'a> Widget for Skillbar<'a> {
.set(state.ids.m2_ico, ui);
// Combo Counter
if self.combo.counter() > 0 {
let combo_txt = format!("{} Combo", self.combo.counter());
let combo_cnt = self.combo.counter() as f32;
let time_since_last_update = self.combo.last_increase() - self.time.0 as f64;
let fnt_col = Color::Rgba(
// White -> Yellow -> Red text color gradient depending on count
(1.0 - combo_cnt / (combo_cnt + tweak!(1.0))).max(0.79),
(1.0 - combo_cnt / (combo_cnt + tweak!(80.0))).max(0.19),
(1.0 - combo_cnt / (combo_cnt + tweak!(5.0))).max(0.17),
(time_since_last_update - 8.0).min(1.0) as f32,
);
let fnt_size = ((14.0 + self.combo.counter() as f32 * tweak!(0.5)).min(tweak!(20.0)))
as u32
+ if (time_since_last_update - 12.0) < 1.0 {
1
} else {
0
}; // Increase size for higher counts, "flash" on update by increasing the font size by 2
println!("{}", time_since_last_update); // REMOVE THIS
Rectangle::fill_with([10.0, 10.0], color::TRANSPARENT)
.middle_of(ui.window)
.set(state.ids.combo_align, ui);
Text::new(combo_txt.as_str())
.mid_bottom_with_margin_on(
state.ids.combo_align,
tweak!(-350.0) + time_since_last_update * tweak!(4.0) - 8.0,
)
.font_size(self.fonts.cyri.scale(fnt_size))
.font_id(self.fonts.cyri.conrod_id)
.color(Color::Rgba(
0.0,
0.0,
0.0,
if let Some(combo) = self.combo {
if combo.combo > 0 {
let combo_txt = format!("{} Combo", combo.combo);
let combo_cnt = combo.combo as f32;
let time_since_last_update = comp::combo::COMBO_DECAY_START - combo.timer;
let fnt_col = Color::Rgba(
// White -> Yellow -> Red text color gradient depending on count
(1.0 - combo_cnt / (combo_cnt + tweak!(1.0))).max(0.79),
(1.0 - combo_cnt / (combo_cnt + tweak!(80.0))).max(0.19),
(1.0 - combo_cnt / (combo_cnt + tweak!(5.0))).max(0.17),
(time_since_last_update - 8.0).min(1.0) as f32,
))
.set(state.ids.combo_bg, ui);
Text::new(combo_txt.as_str())
.bottom_right_with_margins_on(state.ids.combo_bg, 1.0, 1.0)
.font_size(self.fonts.cyri.scale(fnt_size))
.font_id(self.fonts.cyri.conrod_id)
.color(fnt_col)
.set(state.ids.combo, ui);
);
let fnt_size = ((14.0 + combo.timer as f32 * tweak!(0.5)).min(tweak!(20.0))) as u32
+ if (time_since_last_update - 12.0) < 1.0 {
1
} else {
0
}; // Increase size for higher counts, "flash" on update by increasing the font size by 2
//dbg!(combo); // Delete this before merging
Rectangle::fill_with([10.0, 10.0], color::TRANSPARENT)
.middle_of(ui.window)
.set(state.ids.combo_align, ui);
Text::new(combo_txt.as_str())
.mid_bottom_with_margin_on(
state.ids.combo_align,
tweak!(-350.0) + time_since_last_update * tweak!(4.0) - 8.0,
)
.font_size(self.fonts.cyri.scale(fnt_size))
.font_id(self.fonts.cyri.conrod_id)
.color(Color::Rgba(
0.0,
0.0,
0.0,
(time_since_last_update - 8.0).min(1.0) as f32,
))
.set(state.ids.combo_bg, ui);
Text::new(combo_txt.as_str())
.bottom_right_with_margins_on(state.ids.combo_bg, 1.0, 1.0)
.font_size(self.fonts.cyri.scale(fnt_size))
.font_id(self.fonts.cyri.conrod_id)
.color(fnt_col)
.set(state.ids.combo, ui);
}
}
}
}