diff --git a/client/src/animations.utils.jsx b/client/src/animations.utils.jsx index abd1cb0d..5220f3c7 100644 --- a/client/src/animations.utils.jsx +++ b/client/src/animations.utils.jsx @@ -1,71 +1,58 @@ -function getObjects(resolution, game, account) { - const [type, event] = resolution.variant; +const actions = require('./actions'); +const { TIMES } = require('./constants'); - const playerTeam = game.players.find(t => t.id === account.id); - const playerTeamIds = playerTeam.constructs.map(c => c.id); - const otherTeam = game.players.find(t => t.id !== account.id); - const otherTeamIds = otherTeam.constructs.map(c => c.id); - const sourceIsPlayer = playerTeamIds.includes(event.source); - const targetIsPlayer = playerTeamIds.includes(resolution.target); +function setAnimations(r, store, account) { + store.dispatch(actions.setAnimFocus(r.focus)); - const targetting = () => { - if (type === 'AoeSkill') { - if (targetIsPlayer) return playerTeamIds; - return otherTeamIds; - } - return [resolution.target]; - }; + if (r.variant[0] === 'Cast') { + store.dispatch(actions.setAnimText(null)); - const sameTeam = (sourceIsPlayer && targetIsPlayer) || (!sourceIsPlayer && !targetIsPlayer); - let y = 0; - if (!sameTeam) y = targetIsPlayer ? 1 : -1; + const { player } = r.cast; + const { x, y, target } = r.variant[1]; + const animY = y && player === account.id ? -1 : y; + const animSource = { + animation: 'sourceCast', + constructId: target, + direction: { x, y: animY }, + }; + store.dispatch(actions.setAnimSource(animSource)); - const i = sourceIsPlayer - ? playerTeamIds.findIndex(c => c === event.source) - : otherTeamIds.findIndex(c => c === event.source); + return setTimeout(() => store.dispatch(actions.setAnimSource(null)), TIMES.SOURCE_DURATION_MS); + } - const j = targetIsPlayer - ? playerTeamIds.findIndex(c => c === resolution.target) - : otherTeamIds.findIndex(c => c === resolution.target); - const x = j - i; - const direction = { x, y }; - // const targetTeam = targetIsPlayer ? playerTeamIds : otherTeamIds; + if (r.variant[0].includes('Hit')) { + store.dispatch(actions.setAnimText(null)); - const getFocusTargets = () => { - if (type === 'HitCast') { - const { source } = event; - const { target } = resolution; - if (source !== target) return [source, target]; - return [target]; - } - if (type === 'AoeSkill') { - if (targetIsPlayer) return playerTeamIds; - return otherTeamIds; - } - return [resolution.target]; - }; + const { player, skill } = r.cast; + const { x, y, target } = r.variant[1]; + const animY = y && player === account.id ? -1 : y; + const isPlayer = player === account.id; + const animTarget = { + constructId: target, + player: isPlayer, + skill, + direction: { x, y: animY }, + }; + store.dispatch(actions.setAnimTarget(animTarget)); - const animSource = { - animation: 'sourceCast', - constructId: event.source, - direction, - }; + return setTimeout(() => store.dispatch(actions.setAnimTarget(null)), TIMES.TARGET_DURATION_MS); + } - const animTarget = { - skill: event.skill, - constructId: targetting(), - player: playerTeamIds.includes(resolution.target), - direction, - }; - - return { - animSource, - animTarget, - focusTargets: getFocusTargets(), - skill: event.skill, - }; + return store.dispatch(actions.setAnimText(r)); } +function clearAnimations(store) { + store.dispatch(actions.setAnimSkill(null)); + store.dispatch(actions.setAnimSource(null)); + store.dispatch(actions.setAnimTarget(null)); + store.dispatch(actions.setAnimText(null)); + store.dispatch(actions.setAnimating(false)); + store.dispatch(actions.setGameEffectInfo(null)); + store.dispatch(actions.setAnimFocus(null)); +} + + module.exports = { - getObjects, + setAnimations, + clearAnimations, }; diff --git a/client/src/components/anims/attack.jsx b/client/src/components/anims/attack.jsx index 65756c1f..0f5dd317 100644 --- a/client/src/components/anims/attack.jsx +++ b/client/src/components/anims/attack.jsx @@ -46,8 +46,8 @@ class Attack extends Component { y: [400, 200], height: [100, 10, 0], width: [12, 5, 0], - delay: () => anime.random(TIMES.TARGET_DELAY_MS, TIMES.TARGET_DELAY_MS + TIMES.TARGET_DURATION_MS / 2), - duration: TIMES.TARGET_DURATION_MS, + delay: () => anime.random(0, TIMES.TARGET_DURATION_MS / 4), + duration: TIMES.TARGET_DURATION_MS * 5 / 4, })); } @@ -59,9 +59,7 @@ class Attack extends Component { for (let i = this.animations.length - 1; i >= 0; i--) { this.animations[i].reset(); } - this.props.animCb && this.props.animCb(); } - } module.exports = addState(Attack); diff --git a/client/src/components/game.construct.anim.text.jsx b/client/src/components/game.construct.anim.text.jsx index ad39219d..b54d9cd1 100644 --- a/client/src/components/game.construct.anim.text.jsx +++ b/client/src/components/game.construct.anim.text.jsx @@ -7,7 +7,7 @@ const shapes = require('./shapes'); const { removeTier } = require('../utils'); const { TIMES } = require('./../constants'); -const addState = connect(({ animText, animSkill, itemInfo }) => ({ animText, animSkill, itemInfo })); +const addState = connect(({ animText, itemInfo }) => ({ animText, itemInfo })); class AnimText extends preact.Component { shouldComponentUpdate(newProps) { @@ -17,7 +17,7 @@ class AnimText extends preact.Component { componentDidUpdate(prevProps) { const { animText, construct } = this.props; - if (animText && animText !== prevProps.animText && animText.target === construct.id) { + if (animText && animText !== prevProps.animText && animText.variant[1].target === construct.id) { anime({ targets: '.combat-text', top: '40%', @@ -28,10 +28,10 @@ class AnimText extends preact.Component { } render() { - const { construct, animText, animSkill, itemInfo } = this.props; - if (animText && animText.target === construct.id) { + const { construct, animText, itemInfo } = this.props; + if (animText && animText.variant[1].target === construct.id) { const itemSourceDescription = () => { - const itemSource = itemInfo.combos.filter(c => c.item === removeTier(animSkill)); + const itemSource = itemInfo.combos.filter(c => c.item === removeTier(animText.cast.skill)); const itemSourceInfo = itemSource.length ? `${itemSource[0].components[0]} ${itemSource[0].components[1]} ${itemSource[0].components[2]}` : false; @@ -82,7 +82,7 @@ class AnimText extends preact.Component { return (
-

{animSkill}

+

{animText.cast.skill}

{itemSourceDescription()} {generateAnimText()}
diff --git a/client/src/components/game.construct.effect.box.jsx b/client/src/components/game.construct.effect.box.jsx index a6215475..598c2ae8 100644 --- a/client/src/components/game.construct.effect.box.jsx +++ b/client/src/components/game.construct.effect.box.jsx @@ -21,11 +21,10 @@ const addState = connect( class GameConstructEffects extends preact.Component { shouldComponentUpdate(newProps) { - if (newProps.animText !== this.props.animText) { - if (newProps.animText && newProps.animText.constructId === this.props.construct.id) { - const [type] = newProps.animText.variant; - if (type === 'Effect' || type === 'Removal') return true; - } + if (newProps.animText && newProps.animText !== this.props.animText) { + const [type, info] = newProps.animText.variant; + if (info.target === this.props.construct.id + && (type === 'Effect' || type === 'Removal')) return true; } if (newProps.construct !== this.props.construct) return true; return false; diff --git a/client/src/components/game.construct.life.jsx b/client/src/components/game.construct.life.jsx index 680f657c..fe2f76a1 100644 --- a/client/src/components/game.construct.life.jsx +++ b/client/src/components/game.construct.life.jsx @@ -7,11 +7,10 @@ const addState = connect(({ animText }) => ({ animText })); class GameConstructLife extends preact.Component { shouldComponentUpdate(newProps) { - if (newProps.animText !== this.props.animText) { - if (newProps.animText && newProps.animText.target === this.props.construct.id) { - const [type] = newProps.animText.variant; - if (type === 'Damage' || type === 'Healing' || type === 'Recharge') return true; - } + if (newProps.animText && newProps.animText !== this.props.animText) { + const [type, info] = newProps.animText.variant; + if (info.target === this.props.construct.id + && (type === 'Damage' || type === 'Healing' || type === 'Recharge')) return true; } if (newProps.construct !== this.props.construct) return true; return false; diff --git a/client/src/events.jsx b/client/src/events.jsx index ca91776d..5230b256 100644 --- a/client/src/events.jsx +++ b/client/src/events.jsx @@ -5,10 +5,9 @@ const eachSeries = require('async/eachSeries'); const sample = require('lodash/sample'); const actions = require('./actions'); -const animations = require('./animations.utils'); +const { setAnimations, clearAnimations } = require('./animations.utils'); const { infoToast, errorToast } = require('./utils'); const { tutorialVbox } = require('./tutorial.utils'); -const { TIMES } = require('./constants'); function registerEvents(store) { function notify(msg) { @@ -87,41 +86,14 @@ function registerEvents(store) { store.dispatch(actions.setAnimating(true)); store.dispatch(actions.setGameSkillInfo(null)); // stop fetching the game state til animations are done - const newRes = game.events[currentGame.events.length]; + const newRes = game.events[game.events.length - 1]; return eachSeries(newRes, (r, cb) => { const timeout = r.delay; - - if (r.variant[0].includes('Hit')) { - let animTimeOut = TIMES.TARGET_DURATION_MS; - const anims = animations.getObjects(r, game, account); - - if (r.variant[0] === 'HitCast') { - animTimeOut += TIMES.TARGET_DELAY_MS; - store.dispatch(actions.setAnimSource(anims.animSource)); - } - - store.dispatch(actions.setAnimFocus(anims.focusTargets)); - store.dispatch(actions.setAnimSkill(anims.skill)); - store.dispatch(actions.setAnimTarget(anims.animTarget)); - store.dispatch(actions.setAnimText(null)); - setTimeout(() => { - store.dispatch(actions.setAnimSource(null)); - store.dispatch(actions.setAnimTarget(null)); - }, animTimeOut); - } else { - store.dispatch(actions.setAnimText(r)); - } + setAnimations(r, store, account); return setTimeout(cb, timeout); }, err => { if (err) return console.error(err); - // clear animation state - store.dispatch(actions.setAnimSkill(null)); - store.dispatch(actions.setAnimSource(null)); - store.dispatch(actions.setAnimTarget(null)); - store.dispatch(actions.setAnimText(null)); - store.dispatch(actions.setAnimating(false)); - store.dispatch(actions.setGameEffectInfo(null)); - store.dispatch(actions.setAnimFocus(null)); + clearAnimations(store); // set the game state so resolutions don't fire twice store.dispatch(actions.setGame(game)); ws.sendGameState(game.id); diff --git a/core/src/construct.rs b/core/src/construct.rs index f8a3efbf..84f1b9e2 100644 --- a/core/src/construct.rs +++ b/core/src/construct.rs @@ -4,7 +4,7 @@ use rand::prelude::*; use failure::Error; use failure::err_msg; -use skill::{Skill, Cast, Disable, Event, EventVariant, EventConstruct}; +use skill::{Skill, Cast, Disable, EventVariant, EventConstruct}; use game::{Colour}; use effect::{Cooldown, Effect}; use spec::{Spec}; @@ -415,7 +415,7 @@ impl Construct { self } - pub fn increase_cooldowns(&mut self, turns: usize) -> Vec { + pub fn increase_cooldowns(&mut self, turns: usize) -> Vec { let mut events = vec![]; for skill in self.skills.iter_mut() { @@ -423,11 +423,11 @@ impl Construct { match skill.cd { Some(cd) => { skill.cd = Some(cd.saturating_add(turns)); - events.push(Event::new(EventVariant::CooldownIncrease { turns, skill: skill.skill }, self.id)) + events.push(EventVariant::CooldownIncrease { target: self.id, turns }) }, None => { skill.cd = Some(turns); - events.push(Event::new(EventVariant::CooldownIncrease { turns, skill: skill.skill }, self.id)) + events.push(EventVariant::CooldownIncrease { target: self.id, turns }) }, } } @@ -546,9 +546,9 @@ impl Construct { } } - pub fn recharge(&mut self, red_amount: usize, blue_amount: usize) -> Vec { + pub fn recharge(&mut self, red_amount: usize, blue_amount: usize) -> Vec { let mut events = vec![]; - + let target = self.id; if self.is_ko() { return events; } match self.affected(Effect::Invert) { @@ -565,7 +565,7 @@ impl Construct { let blue = new_blue_life - current_blue_life; if red != 0 || blue != 0 { - events.push(Event::new(EventVariant::Recharge { red, blue }, self.id)); + events.push(EventVariant::Recharge { target, red, blue }); } }, true => { @@ -591,12 +591,13 @@ impl Construct { self.reduce_green_life(red_remainder); let red_damage_amount = red_current_green_life - self.green_life(); - events.push(Event::new(EventVariant::Damage { + events.push(EventVariant::Damage { + target, amount: red_damage_amount, mitigation: red_mitigation, colour: Colour::Red, display: EventConstruct::new(self), - }, self.id)); + }); } if blue_amount != 0 { @@ -620,21 +621,23 @@ impl Construct { self.reduce_green_life(blue_remainder); let blue_damage_amount = blue_current_green_life - self.green_life(); - events.push(Event::new(EventVariant::Damage { + events.push(EventVariant::Damage { + target, amount: blue_damage_amount, mitigation: blue_mitigation, colour: Colour::Blue, display: EventConstruct::new(self), - }, self.id)); + }); } } } return events; } - pub fn deal_green_damage(&mut self, amount: usize) -> Vec { + pub fn deal_green_damage(&mut self, amount: usize) -> Vec { let mut events = vec![]; if self.is_ko() { return events; } + let target = self.id; let mods = self.effects.iter() .filter(|e| e.effect.modifications().contains(&Stat::GreenDamageTaken)) @@ -653,10 +656,11 @@ impl Construct { let healing = new_green_life - current_green_life; let overhealing = modified_power - healing; - events.push(Event::new(EventVariant::Healing { + events.push(EventVariant::Healing { + target, amount: healing, overhealing, - }, self.id)); + }); }, true => { // events.push(Event::new(EventVariant::Inversion { skill })); @@ -666,22 +670,24 @@ impl Construct { self.reduce_green_life(modified_power); let delta = current_green_life - self.green_life(); - events.push(Event::new(EventVariant::Damage { + events.push(EventVariant::Damage { + target, amount: delta, mitigation: 0, colour: Colour::Green, display: EventConstruct::new(self), - }, self.id)); + }); } } return events; } - pub fn deal_red_damage(&mut self, amount: usize) -> Vec { + pub fn deal_red_damage(&mut self, amount: usize) -> Vec { let mut events = vec![]; if self.is_ko() { return events; } + let target = self.id; let mods = self.effects.iter() .filter(|e| e.effect.modifications().contains(&Stat::RedDamageTaken)) @@ -708,17 +714,17 @@ impl Construct { self.reduce_green_life(remainder); let delta = current_green_life - self.green_life(); - events.push(Event::new( + events.push( EventVariant::Damage { + target, amount: delta, mitigation, colour: Colour::Red, display: EventConstruct::new(self), - }, - self.id - )); + } + ); if self.is_ko() { - events.push(Event::new(EventVariant::Ko {}, self.id)); + events.push(EventVariant::Ko { target }); } }, true => { @@ -735,16 +741,17 @@ impl Construct { let recharge = self.red_life.value - current_life; if healing > 0 { - events.push(Event::new( - EventVariant::Healing{ + events.push( + EventVariant::Healing { + target, amount: healing, overhealing: overhealing - recharge, - }, self.id - )); + } + ); } if recharge > 0 { - events.push(Event::new(EventVariant::Recharge { red: recharge, blue: 0 }, self.id)); + events.push(EventVariant::Recharge { target, red: recharge, blue: 0 }); } } }; @@ -752,10 +759,11 @@ impl Construct { return events; } - pub fn deal_blue_damage(&mut self, amount: usize) -> Vec { + pub fn deal_blue_damage(&mut self, amount: usize) -> Vec { let mut events = vec![]; if self.is_ko() { return events; } + let target = self.id; let mods = self.effects.iter() .filter(|e| e.effect.modifications().contains(&Stat::BlueDamageTaken)) @@ -778,12 +786,13 @@ impl Construct { self.reduce_green_life(remainder); let delta = current_green_life - self.green_life(); - events.push(Event::new(EventVariant::Damage { + events.push(EventVariant::Damage { + target, amount: delta, mitigation, colour: Colour::Blue, - display: EventConstruct::new(self), - }, self.id)); + display: EventConstruct::new(self), + }); }, true => { // events.push(Event::new(EventVariant::Inversion { skill })); @@ -799,17 +808,11 @@ impl Construct { let recharge = self.blue_life.value - current_life; if healing > 0 { - events.push( - Event::new(EventVariant::Healing { - amount: healing, - overhealing, - }, - self.id - )); + events.push(EventVariant::Healing { target, amount: healing, overhealing }); } if recharge > 0 { - events.push(Event::new(EventVariant::Recharge { red: 0, blue: recharge }, self.id)); + events.push(EventVariant::Recharge { target, red: 0, blue: recharge }); } } }; @@ -817,7 +820,7 @@ impl Construct { return events; } - pub fn add_effect(&mut self, effect: ConstructEffect) -> Vec { + pub fn add_effect(&mut self, effect: ConstructEffect) -> Vec { if self.is_ko() { return vec![] } if self.affected(Effect::Banish) { panic!("banish immunity not fixt yet") } @@ -834,13 +837,12 @@ impl Construct { } // todo modified durations cause of buffs - let result = Event::new( - EventVariant::Effect { - effect: effect.effect, - duration: effect.duration, - display: EventConstruct::new(self), - }, self.id - ); + let result = EventVariant::Effect { + target: self.id, + effect: effect.effect, + duration: effect.duration, + display: EventConstruct::new(self) + }; return vec![result]; } diff --git a/core/src/game.rs b/core/src/game.rs index a09f4647..94594e9e 100644 --- a/core/src/game.rs +++ b/core/src/game.rs @@ -42,12 +42,13 @@ pub enum Colour { #[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] pub enum Action { - Cast { construct: Uuid, skill: Skill }, - Hit { construct: Uuid, skill: Skill }, - Damage { construct: Uuid, values: Vec, colour: Colour }, - Healing { construct: Uuid, values: Vec, colour: Colour }, - Effect { construct: Uuid, effect: ConstructEffect }, - IncreaseCooldowns { construct: Uuid, turns: usize }, + Hit { skill: Skill }, + Cast { skill: Skill }, + Damage { skill: Skill, construct: Uuid, values: Vec, colour: Colour }, + Effect { skill: Skill, construct: Uuid, effect: ConstructEffect }, + IncreaseCooldowns { skill: Skill, construct: Uuid, turns: usize }, + Healing { skill: Skill, construct: Uuid, values: Vec, colour: Colour }, + // Recharge { skill: Skill, red: usize, blue: usize }, } #[derive(Debug,Clone,Serialize,Deserialize)] @@ -495,15 +496,15 @@ impl Game { self.skill_phase_start(r_animation_ms) } - pub fn actions(&mut self, actions: Vec) -> &mut Game { + pub fn actions(&mut self, cast: Cast) -> &mut Game { let mut events_group = vec![]; // calculate values first? // for result damage value need to pass &events and .find() - for action in actions { + for action in cast.actions() { let mut events = match action { - Action::Cast { construct, skill } => self.cast(construct, skill), + Action::Cast { construct, skill, direction } => self.cast(construct, skill), Action::Hit { construct, skill } => self.hit(construct, skill), Action::Damage { construct, values, colour } => self.damage(construct, values, colour), Action::Healing { construct, values, colour } => unimplemented!(), @@ -540,6 +541,31 @@ impl Game { self.construct_by_id(construct).unwrap().increase_cooldowns(turns) } + fn direction(&mut self, cast: Cast) -> (i8, i8) { + let i = self.players.iter() + .find(|t| t.constructs.iter().any(|c| c.id == cast.source)) + .unwrap().constructs + .iter() + .position(|c| c.id == cast.source) + .unwrap() as i8; + + let j = self.players.iter() + .find(|t| t.constructs.iter().any(|c| c.id == cast.target)) + .unwrap().constructs + .iter() + .position(|c| c.id == cast.target) + .unwrap() as i8; + let x = j - i; + + let target = self.construct_by_id(cast.target).unwrap(); + // is the caster player account same as target player account side of screen + let y = match cast.player == target.account { + true => 0, + false => 1 + }; + (x, y) + } + fn progress_durations(&mut self, events: &Vec) -> &mut Game { for mut construct in self.all_constructs() { // info!("progressing durations for {:}", construct.name); diff --git a/core/src/skill.rs b/core/src/skill.rs index 97771943..8d6c79d0 100644 --- a/core/src/skill.rs +++ b/core/src/skill.rs @@ -32,6 +32,10 @@ impl Cast { }; } + pub fn target(self) -> Uuid { + self.target + } + pub fn new_tick(source: &mut Construct, target: &mut Construct, skill: Skill) -> Cast { Cast { id: Uuid::new_v4(), @@ -53,10 +57,10 @@ impl Cast { let mut actions = vec![]; if self.skill.cast_animation() { - actions.push({ Action::Cast { construct: self.source, skill: self.skill }}); + actions.push(Action::Cast { cast: *self }); } - actions.push(Action::Hit { construct: self.target, skill: self.skill }); + actions.push(Action::Hit { cast: *self }); let mut rest = match self.skill { Skill::Attack => vec![ @@ -85,18 +89,21 @@ impl Cast { Skill::Amplify => vec![ Action::Effect { + cast: *self, construct: self.target, effect: ConstructEffect { effect: Effect::Amplify, duration: 2, meta: Some(EffectMeta::Multiplier(150)), tick: None }, }, ], Skill::AmplifyPlus => vec![ Action::Effect { + cast: *self, construct: self.target, effect: ConstructEffect { effect: Effect::Amplify, duration: 3, meta: Some(EffectMeta::Multiplier(175)), tick: None }, }, ], Skill::AmplifyPlusPlus => vec![ Action::Effect { + cast: *self, construct: self.target, effect: ConstructEffect { effect: Effect::Amplify, duration: 4, meta: Some(EffectMeta::Multiplier(200)), tick: None }, }, @@ -115,6 +122,7 @@ impl Cast { ], Skill::AbsorbPlus => vec![ Action::Effect { + cast: *self, construct: self.target, effect: ConstructEffect { effect: Effect::Absorb, duration: 1, meta: Some(EffectMeta::Skill(Skill::AbsorptionPlus)), tick: None }, }, @@ -126,6 +134,7 @@ impl Cast { ], Skill::AbsorbPlusPlus => vec![ Action::Effect { + cast: *self, construct: self.target, effect: ConstructEffect { effect: Effect::Absorb, duration: 1, meta: Some(EffectMeta::Skill(Skill::AbsorptionPlusPlus)), tick: None }, }, @@ -150,6 +159,7 @@ impl Cast { values: vec![Value::Stat { construct: self.target, stat: Stat::BlueLife, mult: self.skill.multiplier() }], }, Action::Effect { + cast: *self, construct: self.target, effect: ConstructEffect { effect: Effect::Banish, duration: 2, meta: None, tick: None } } @@ -159,6 +169,7 @@ impl Cast { Skill::BashPlus | Skill::BashPlusPlus => vec![ Action::Damage { + cast: *self, construct: self.target, colour: Colour::Red, values: vec![ @@ -167,10 +178,12 @@ impl Cast { ], }, Action::Effect { + cast: *self, construct: self.target, effect: ConstructEffect {effect: Effect::Stun, duration: 2, meta: None, tick: None } }, Action::IncreaseCooldowns { + cast: *self, construct: self.target, turns: 1, }, @@ -180,6 +193,7 @@ impl Cast { Skill::BlastPlus | Skill::BlastPlusPlus => vec![ Action::Damage { + cast: *self, construct: self.target, colour: Colour::Blue, values: vec![Value::Stat { construct: self.source, stat: Stat::BluePower, mult: self.skill.multiplier() }], @@ -260,6 +274,7 @@ impl Cast { Skill::CounterAttackPlus | Skill::CounterAttackPlusPlus => vec![ Action::Damage { + cast: *self, construct: self.target, colour: Colour::Red, values: vec![Value::Stat { construct: self.source, stat: Stat::RedPower, mult: self.skill.multiplier() }], @@ -295,7 +310,6 @@ impl Cast { ], - Skill::Slay | Skill::SlayPlus | Skill::SlayPlusPlus => vec![ @@ -387,7 +401,6 @@ impl Cast { colour: Colour::Red, }, ], - _ => unimplemented!() }; @@ -398,7 +411,6 @@ impl Cast { fn end() {} - // fn heal(source: &mut Construct, target: &mut Construct, skill: Skill) { // let amount = source.green_power().pct(skill.multiplier()); // target.deal_green_damage(skill, amount) @@ -756,105 +768,72 @@ pub fn resolve(game: &mut Game, cast: Cast) { pub type Disable = Vec; -#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] -pub struct Event { - pub target: Uuid, - pub variant: EventVariant, - pub stages: EventStages, - pub delay: i64, -} - -impl Event { - pub fn new(variant: EventVariant, target: Uuid) -> Event { - let stages = variant.stages(); - - Event { - target, - variant, - delay: stages.delay(), - stages: stages, - } - } -} - -#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] +#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] pub enum EventVariant { - Cast { skill: Skill }, - Hit { skill: Skill }, + Cast { target: Uuid, player: Uuid, x: i8, y: i8 }, + Hit { target: Uuid, player: Uuid, x: i8, y: i8 }, + HitAoe { target: Uuid }, - Damage { amount: usize, mitigation: usize, colour: Colour, display: EventConstruct }, - Effect { effect: Effect, duration: u8, display: EventConstruct }, - Removal { effect: Option, display: EventConstruct }, + Damage { target: Uuid, amount: usize, mitigation: usize, colour: Colour, display: EventConstruct }, + Effect { target: Uuid, effect: Effect, duration: u8, display: EventConstruct }, + Removal { target: Uuid, effect: Option, display: EventConstruct }, - Disable { disable: Disable }, - Healing { amount: usize, overhealing: usize }, - Recharge { red: usize, blue: usize }, - Inversion { skill: Skill }, - Reflection { skill: Skill }, - AoeSkill { skill: Skill }, - Skill { skill: Skill }, - TargetKo { skill: Skill }, - // skill not necessary but makes it neater as all events are arrays in js - Ko (), + Healing { target: Uuid, amount: usize, overhealing: usize }, + Recharge { target: Uuid, red: usize, blue: usize }, + Inversion { target: Uuid }, + Reflection { target: Uuid }, + Ko { target: Uuid }, + + CooldownIncrease { target: Uuid, turns: usize }, + CooldownDecrease { target: Uuid, turns: usize }, Forfeit (), - Incomplete (), - // not used - Evasion { skill: Skill, evasion_rating: usize }, - - CooldownIncrease { turns: usize, skill: Skill }, - CooldownDecrease { turns: usize, skill: Skill }, } impl EventVariant { - fn stages(&self) -> EventStages { - match self { - EventVariant::Disable { disable: _} - => EventStages::PostOnly, - EventVariant::Damage { amount: _, mitigation: _, colour: _, display: _ } - => EventStages::PostOnly, - EventVariant::Healing { amount: _, overhealing: _} - => EventStages::PostOnly, - EventVariant::Recharge { red: _, blue: _} - => EventStages::PostOnly, - EventVariant::Inversion { skill: _ } - => EventStages::PostOnly, - EventVariant::Reflection { skill: _ } - => EventStages::PostOnly, - EventVariant::AoeSkill { skill: _ } - => EventStages::PostOnly, - EventVariant::Skill { skill: _ } - => EventStages::PostOnly, - EventVariant::Effect { effect: _, duration: _, display: _ } - => EventStages::PostOnly, - EventVariant::Removal { effect: _, display: _ } - => EventStages::PostOnly, - EventVariant::TargetKo { skill: _ } - => EventStages::PostOnly, - EventVariant::Ko () - => EventStages::PostOnly, - EventVariant::Forfeit () - => EventStages::PostOnly, - EventVariant::Incomplete () - => EventStages::PostOnly, - EventVariant::Evasion { skill: _, evasion_rating: _ } - => EventStages::PostOnly, + fn delay(&self) -> i64 { + // let source_duration = 1000; // Time for SOURCE ONLY + let target_duration = 1500; // Time for target animation + let target_delay = 500; // Add delay if theres source animation + let combat_text_delay = 1300; // Time for all post skill + let combat_text_overlap = 600; // overlap between animation and combat text - EventVariant::CooldownDecrease { skill: _, turns: _ } - => EventStages::PostOnly, - EventVariant::CooldownIncrease { skill: _, turns: _ } - => EventStages::PostOnly, + match self { + EventVariant::Cast { target: _, x: _, y: _, player: _ } => target_delay, + EventVariant::Hit { target: _, x: _, y: _, player: _ } | + EventVariant::HitAoe { target: _ } => target_duration - combat_text_overlap, + _ => combat_text_delay, + } + } - EventVariant::Hit { skill: _ } - => EventStages::PostOnly, - EventVariant::Cast { skill: _ } - => EventStages::PostOnly, + pub fn to_event(&self, cast: Cast) -> Event { + let delay = self.delay(); + let focus = match self { + EventVariant::HitAoe { target: _ } => vec![cast.source, cast.target], // some tricky multi target here l8r + _ => vec![cast.source, cast.target], + }; + + Event { + cast, + focus, + variant: *self, + delay, } } } + +#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] +pub struct Event { + pub cast: Cast, + pub focus: Vec, + pub variant: EventVariant, + pub delay: i64, +} + + // used to show the progress of a construct // while the resolutions are animating -#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] +#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] pub struct EventConstruct { pub id: Uuid, pub red: usize, @@ -1763,8 +1742,6 @@ impl Skill { } - - // #[cfg(test)] mod tests { use skill::*; @@ -1775,18 +1752,19 @@ mod tests { let actions = cast.actions(); match actions[0] { - Action::Hit { construct: _, skill } => { - assert_eq!(skill, Skill::Attack); + Action::Hit { cast } => { + assert_eq!(cast.skill, Skill::Attack); }, _ => panic!("{:?}", actions), }; match actions[1] { - Action::Damage { construct: _, values: _, colour } => { + Action::Damage { cast: _, construct: _, values: _, colour } => { assert_eq!(colour, Colour::Red); }, _ => panic!("{:?}", actions), }; + } // #[test]