From 09d95a7cf7abe5bf88c0159019634632e5c46d16 Mon Sep 17 00:00:00 2001 From: Mashy Date: Thu, 5 Dec 2019 22:52:17 +1000 Subject: [PATCH] core anims --- client/src/animations.utils.jsx | 73 ++++-------- .../components/game.construct.anim.text.jsx | 10 +- client/src/components/targeting.arrows.jsx | 6 +- client/src/events.jsx | 55 ++++----- core/src/game.rs | 7 ++ core/src/skill.rs | 107 +++--------------- 6 files changed, 75 insertions(+), 183 deletions(-) diff --git a/client/src/animations.utils.jsx b/client/src/animations.utils.jsx index 461abe84..8d961676 100644 --- a/client/src/animations.utils.jsx +++ b/client/src/animations.utils.jsx @@ -9,25 +9,22 @@ function none() { } function getObjects(resolution, game, account) { - if (!resolution) return none(); - if (!resolution.target) return none(); - - const [type, event] = resolution.event; + const [type, event] = resolution.variant; if (!event || !event.skill) return none(); 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(resolution.source.id); - const targetIsPlayer = playerTeamIds.includes(resolution.target.id); + const sourceIsPlayer = playerTeamIds.includes(event.source); + const targetIsPlayer = playerTeamIds.includes(resolution.target); const targetting = () => { if (type === 'AoeSkill') { if (targetIsPlayer) return playerTeamIds; return otherTeamIds; } - return [resolution.target.id]; + return [resolution.target]; }; const sameTeam = (sourceIsPlayer && targetIsPlayer) || (!sourceIsPlayer && !targetIsPlayer); @@ -35,41 +32,32 @@ function getObjects(resolution, game, account) { if (!sameTeam) y = targetIsPlayer ? 1 : -1; const i = sourceIsPlayer - ? playerTeamIds.findIndex(c => c === resolution.source.id) - : otherTeamIds.findIndex(c => c === resolution.source.id); + ? playerTeamIds.findIndex(c => c === event.source) + : otherTeamIds.findIndex(c => c === event.source); const j = targetIsPlayer - ? playerTeamIds.findIndex(c => c === resolution.target.id) - : otherTeamIds.findIndex(c => c === resolution.target.id); + ? 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; - const createSourceAnim = () => { - return { - animation: 'sourceCast', - constructId: resolution.source.id, - direction, - }; + const animSource = { + animation: 'sourceCast', + constructId: event.source, + direction, }; - const skipSource = !resolution.stages.includes('START_SKILL') - || resolution.source.id === resolution.target.id; - - const animSource = skipSource - ? null - : createSourceAnim(); - const animTarget = { skill: event.skill, constructId: targetting(), - player: playerTeamIds.includes(resolution.target.id), + player: playerTeamIds.includes(resolution.target), direction, }; + return { animSource, animTarget, - animSkill: event.skill, }; } @@ -86,30 +74,21 @@ function getTime(stages) { return time; } -function getFocusTargets(resolution, game) { - if (!resolution) return []; - if (!resolution.event) return []; - const [type] = resolution.event; - const source = resolution.source.id; - const target = resolution.target.id; - - if (type === 'AoeSkill') { - const targetTeam = game.players.find(t => t.constructs.find(c => c.id === target)); - const targetTeamIds = targetTeam.constructs.map(c => c.id); - if (source !== target) targetTeamIds.push(source); - return targetTeamIds; +function getFocusTargets(resolution) { + const [type, event] = resolution.variant; + if (type === 'HitCast') { + const { source } = event; + const { target } = resolution; + if (source !== target) return [source, target]; + return [target]; } - if (source !== target) return [source, target]; - return [target]; + return [resolution.target]; } function getText(resolution) { const nullText = { text: null, constructId: null, life: null }; - if (!resolution) return nullText; - if (!resolution.stages.includes('POST_SKILL')) return nullText; - + const [type, event] = resolution.variant; function generatePostSkill() { - const [type, event] = resolution.event; if (type === 'Ko') { return { text: 'KO!', css: 'ko-transition' }; } @@ -176,16 +155,14 @@ function getText(resolution) { return false; } - const { green, red, blue } = resolution.target; + const { green, red, blue } = event.display; const { text, css, effects } = generatePostSkill(); - const skill = resolution.event[1] ? resolution.event[1].skill : null; return { css, text, effects, life: { green, red, blue }, - constructId: resolution.target.id, - skill, + constructId: event.display.id, }; } diff --git a/client/src/components/game.construct.anim.text.jsx b/client/src/components/game.construct.anim.text.jsx index 14b8fde1..076658ac 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, itemInfo }) => ({ animText, itemInfo })); +const addState = connect(({ animText, animSkill, itemInfo }) => ({ animText, animSkill, itemInfo })); class AnimText extends preact.Component { shouldComponentUpdate(newProps) { @@ -27,11 +27,11 @@ class AnimText extends preact.Component { } } - render(props) { - const { construct, animText, itemInfo } = props; + render() { + const { construct, animText, animSkill, itemInfo } = this.props; if (animText && animText.constructId === construct.id) { const itemSourceDescription = () => { - const itemSource = itemInfo.combos.filter(c => c.item === removeTier(animText.skill)); + const itemSource = itemInfo.combos.filter(c => c.item === removeTier(animSkill)); const itemSourceInfo = itemSource.length ? `${itemSource[0].components[0]} ${itemSource[0].components[1]} ${itemSource[0].components[2]}` : false; @@ -60,7 +60,7 @@ class AnimText extends preact.Component { return (
-

{animText.skill}

+

{animSkill}

{itemSourceDescription()} {animationTextHtml()}
diff --git a/client/src/components/targeting.arrows.jsx b/client/src/components/targeting.arrows.jsx index 3b4b2476..384dd1d6 100644 --- a/client/src/components/targeting.arrows.jsx +++ b/client/src/components/targeting.arrows.jsx @@ -6,11 +6,11 @@ const reactStringReplace = require('react-string-replace'); const throttle = require('lodash/throttle'); const shapes = require('./shapes'); -const { effectInfo, removeTier } = require('../utils'); +const { effectInfo } = require('../utils'); const addState = connect( - ({ game, account, animSkill, animating, itemInfo, gameEffectInfo, tutorialGame }) => - ({ game, account, animSkill, animating, itemInfo, gameEffectInfo, tutorialGame }) + ({ game, account, animating, itemInfo, gameEffectInfo, tutorialGame }) => + ({ game, account, animating, itemInfo, gameEffectInfo, tutorialGame }) ); class TargetSvg extends Component { diff --git a/client/src/events.jsx b/client/src/events.jsx index a6469389..54a0bd11 100644 --- a/client/src/events.jsx +++ b/client/src/events.jsx @@ -87,48 +87,33 @@ 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[currentGame.events.length - 1]; return eachSeries(newRes, (r, cb) => { - if (!r.event) return cb(); - let timeout = animations.getTime(r.stages); + // if (!r.event) return cb(); + const timeout = r.delay; const anims = animations.getObjects(r, game, account); - const text = animations.getText(r); - store.dispatch(actions.setAnimFocus(animations.getFocusTargets(r, game))); - if (anims.animSkill) store.dispatch(actions.setAnimSkill(anims.animSkill)); - if (r.stages.includes('START_SKILL') && anims.animSource) { - store.dispatch(actions.setAnimSource(anims.animSource)); - store.dispatch(actions.setAnimText(null)); - } - if (r.stages.includes('END_SKILL') && anims.animTarget) { + if (r.variant[0].includes('Hit')) { + if (r.variant[0] === 'HitCast') { + store.dispatch(actions.setAnimSource(anims.animSource)); + } + const { skill } = r.variant[1]; + store.dispatch(actions.setAnimFocus(animations.getFocusTargets(r, game))); + store.dispatch(actions.setAnimSkill(skill)); store.dispatch(actions.setAnimTarget(anims.animTarget)); store.dispatch(actions.setAnimText(null)); - if (animations.isCbAnim(anims.animSkill)) store.dispatch(actions.setAnimCb(cb)); + if (animations.isCbAnim(skill)) store.dispatch(actions.setAnimCb(cb)); + return setTimeout(() => { + store.dispatch(actions.setAnimSource(null)); + store.dispatch(actions.setAnimTarget(null)); + if (r.variant[0].includes('Hit') && animations.isCbAnim(r.variant[1].skill)) return true; + return cb(); + }, timeout); } - - if (r.stages.includes('POST_SKILL') && text) { - // timeout to prevent text classes from being added too soon - if (timeout === TIMES.POST_SKILL_DURATION_MS) { - store.dispatch(actions.setAnimText(text)); - } else { - setTimeout( - () => store.dispatch(actions.setAnimText(text)), - timeout - TIMES.POST_SKILL_DURATION_MS - 700 - ); - timeout -= 700; - } - } - - return setTimeout(() => { - store.dispatch(actions.setAnimSkill(null)); - store.dispatch(actions.setAnimSource(null)); - store.dispatch(actions.setAnimTarget(null)); - // store.dispatch(actions.setAnimText(null)); - store.dispatch(actions.setAnimFocus([])); - if (r.stages.includes('END_SKILL') && animations.isCbAnim(anims.animSkill)) return true; - return cb(); - }, timeout); + const text = animations.getText(r); + store.dispatch(actions.setAnimText(text)); + return setTimeout(cb, timeout); }, err => { if (err) return console.error(err); // clear animation state diff --git a/core/src/game.rs b/core/src/game.rs index 8a6dd536..1cbef655 100644 --- a/core/src/game.rs +++ b/core/src/game.rs @@ -41,6 +41,7 @@ pub enum Colour { #[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] pub enum Action { Hit { construct: Uuid, skill: Skill }, + HitCast { construct: Uuid, skill: Skill, source: Uuid }, Damage { construct: Uuid, values: Vec, colour: Colour }, Effect { construct: Uuid, effect: ConstructEffect }, IncreaseCooldowns { construct: Uuid, turns: usize }, @@ -501,6 +502,7 @@ impl Game { for action in actions { match action { Action::Hit { construct, skill } => self.hit(construct, skill), + Action::HitCast { construct, skill, source } => self.hit_cast(construct, skill, source), Action::Damage { construct, values, colour } => self.damage(construct, values, colour), Action::Effect { construct, effect } => self.effect(construct, effect), Action::IncreaseCooldowns { construct, turns } => self.increase_cooldowns(construct, turns), @@ -510,6 +512,11 @@ impl Game { self } + fn hit_cast(&mut self, construct: Uuid, skill: Skill, source: Uuid) -> &mut Game { + self.event_add(vec![Event::new(EventVariant::HitCast { skill: skill, source: source }, construct)]); + self + } + fn hit(&mut self, construct: Uuid, skill: Skill) -> &mut Game { self.event_add(vec![Event::new(EventVariant::Hit { skill: skill }, construct)]); self diff --git a/core/src/skill.rs b/core/src/skill.rs index 13f9ab13..251f08d3 100644 --- a/core/src/skill.rs +++ b/core/src/skill.rs @@ -105,7 +105,7 @@ impl Cast { } pub fn actions(&self) -> Vec { - let mut actions = vec![Action::Hit { construct: self.target, skill: self.skill }]; + let mut actions = vec![Action::HitCast { construct: self.target, skill: self.skill, source: self.source }]; let mut rest = match self.skill { Skill::Amplify => vec![ @@ -186,15 +186,7 @@ impl Cast { }, ], - - - - - - - - - Skill::Strike | + Skill::Strike | Skill::StrikePlus | Skill::StrikePlusPlus => vec![ Action::Damage { @@ -218,19 +210,16 @@ pub type Disable = Vec; 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(); - + let delay = variant.delay(); Event { target, variant, - delay: stages.delay(), - stages: stages, + delay, } } } @@ -238,6 +227,7 @@ impl Event { #[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] pub enum EventVariant { Hit { skill: Skill }, + HitCast { skill: Skill, source: Uuid }, Damage { amount: usize, mitigation: usize, colour: Colour, display: EventConstruct }, Effect { effect: Effect, duration: u8, display: EventConstruct }, @@ -263,46 +253,17 @@ pub enum EventVariant { } 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_delay = 500; // Used for Source + Target + let target_duration = 1500; // Time for TARGET ONLY + let post_skill = 1000; // Time for all POST + let source_and_target_total = target_delay + target_duration; // SOURCE + TARGET time - EventVariant::CooldownDecrease { skill: _, turns: _ } - => EventStages::PostOnly, - EventVariant::CooldownIncrease { skill: _, turns: _ } - => EventStages::PostOnly, - - EventVariant::Hit { skill: _ } - => EventStages::PostOnly, + match self { + EventVariant::Hit { skill: _ } => target_duration, + EventVariant::HitCast { skill: _, source: _ } => source_and_target_total, + _ => post_skill, } } } @@ -328,44 +289,6 @@ impl EventConstruct { } } -#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] -pub enum EventStages { - #[serde(rename = "START_SKILL END_SKILL POST_SKILL")] - AllStages, // Anim Anim Anim - #[serde(rename = "START_SKILL END_SKILL")] - StartEnd, // Anim Anim Skip - #[serde(rename = "START_SKILL POST_SKILL")] - StartPost, // Anim Skip Anim - #[serde(rename = "START_SKILL")] - StartOnly, // Anim Skip Skip - #[serde(rename = "END_SKILL POST_SKILL")] - EndPost, // Skip Anim Anim - #[serde(rename = "END_SKILL")] - EndOnly, // Skip Anim Skip - #[serde(rename = "POST_SKILL")] - PostOnly, // Skip Skip Anim -} - -impl EventStages { - fn delay(self) -> i64 { - let source_duration = 1000; // Time for SOURCE ONLY - let target_delay = 500; // Used for Source + Target - let target_duration = 1500; // Time for TARGET ONLY - let post_skill = 1000; // Time for all POST - let source_and_target_total = target_delay + target_duration; // SOURCE + TARGET time - - match self { - EventStages::AllStages => source_and_target_total + post_skill, // Anim Anim Anim - EventStages::StartEnd => source_and_target_total, // Anim Anim Skip - EventStages::StartPost => source_duration + post_skill, // Anim Skip Anim - EventStages::StartOnly => source_duration, // Anim Skip Skip - EventStages::EndPost => target_duration + post_skill, // Skip Anim Anim - EventStages::EndOnly => target_duration, // Skip Anim Skip - EventStages::PostOnly => post_skill, // Skip Skip Anim - } - } -} - #[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] pub enum Skill { Attack,