diff --git a/client/src/animations.utils.jsx b/client/src/animations.utils.jsx index 25542967..dbdd2957 100644 --- a/client/src/animations.utils.jsx +++ b/client/src/animations.utils.jsx @@ -1,40 +1,31 @@ const actions = require('./actions'); const { TIMES } = require('./constants'); -function setAnimations(r, store, account) { - const { skill, focus, event: [type, variant] } = r; +function setAnimations(r, store) { + const { focus, event: [type, variant] } = r; + + if (type === 'HitAoe') { + const { construct } = variant; + const aoeFocus = focus.concat(construct); + + store.dispatch(actions.setResolution(null)); + store.dispatch(actions.setAnimFocus(aoeFocus)); + store.dispatch(actions.setAnimTarget(r)); + + return setTimeout(() => store.dispatch(actions.setAnimSource(null)), TIMES.SOURCE_DURATION_MS); + } store.dispatch(actions.setAnimFocus(focus)); if (type === 'Cast') { store.dispatch(actions.setResolution(null)); - - const { construct, player, direction: [x, y] } = variant; - const animY = y && player === account.id ? -1 : y; - const animSource = { - animation: 'sourceCast', - constructId: construct, - direction: { x, y: animY }, - }; - store.dispatch(actions.setAnimSource(animSource)); - + store.dispatch(actions.setAnimSource(r)); return setTimeout(() => store.dispatch(actions.setAnimSource(null)), TIMES.SOURCE_DURATION_MS); } - if (type.includes('Hit')) { + if (type === 'Hit') { store.dispatch(actions.setResolution(null)); - - const { construct, player, direction: [x, y] } = variant; - const animY = y && player === account.id ? -1 : y; - const isPlayer = player === account.id; - const animTarget = { - constructId: construct, - player: isPlayer, - skill, - direction: { x, y: animY }, - }; - store.dispatch(actions.setAnimTarget(animTarget)); - + store.dispatch(actions.setAnimTarget(r)); return setTimeout(() => store.dispatch(actions.setAnimTarget(null)), TIMES.TARGET_DURATION_MS); } diff --git a/client/src/components/animations.jsx b/client/src/components/animations.jsx index 42b640fa..38aaa2b6 100644 --- a/client/src/components/animations.jsx +++ b/client/src/components/animations.jsx @@ -44,8 +44,8 @@ const { removeTier } = require('../utils'); const addState = connect( function receiveState(state) { - const { animTarget } = state; - return { animTarget }; + const { animTarget, account } = state; + return { animTarget, account }; } ); @@ -60,16 +60,18 @@ class ConstructAnimation extends Component { const { animTarget, construct, + account, } = props; if (!animTarget) return false; - const { - skill, - player, - direction, - constructId, - } = animTarget; + const { skill, event: [, variant] } = animTarget; + const { construct: constructId, player, direction: [x, y] } = variant; + + const animY = y && player === account.id ? -1 : y; + const isPlayer = player === account.id; + const direction = { x, y: animY }; + const animSkill = removeTier(skill); if (!constructId.includes(construct.id)) return false; @@ -93,9 +95,9 @@ class ConstructAnimation extends Component { case 'Haste': return ; case 'Triage': return ; case 'TriageTick': return ; - case 'Link': return ; + case 'Link': return ; case 'Hybrid': return ; - case 'Intercept': return ; + case 'Intercept': return ; // Debuff base case 'Debuff': return ; @@ -118,15 +120,15 @@ class ConstructAnimation extends Component { // Block Base case 'Block': return ; - case 'Sustain': return ; + case 'Sustain': return ; case 'Electrify': return ; case 'Electrocute': return ; case 'ElectrocuteTick': return ; - case 'Counter': return ; + case 'Counter': return ; case 'CounterAttack': return ; - case 'Purify': return ; - case 'Recharge': return ; - case 'Reflect': return ; + case 'Purify': return ; + case 'Recharge': return ; + case 'Reflect': return ; default: return false; } diff --git a/client/src/components/anims/triage.tick.jsx b/client/src/components/anims/triage.tick.jsx index 96952c5e..f416148d 100644 --- a/client/src/components/anims/triage.tick.jsx +++ b/client/src/components/anims/triage.tick.jsx @@ -20,7 +20,6 @@ function projectile(x, y, radius, colour) { class TriageTick extends Component { constructor(props) { super(); - this.team = props.team; this.animations = []; const points = randomPoints(15, 10, { x: 0, y: 0, width: 300, height: 400 }); this.charges = points.map(coord => projectile(coord[0], coord[1], 15, COLOURS.GREEN)); diff --git a/client/src/components/construct.jsx b/client/src/components/construct.jsx index f4ecbd3e..fba6a9e4 100644 --- a/client/src/components/construct.jsx +++ b/client/src/components/construct.jsx @@ -13,8 +13,8 @@ const { ConstructAnimation } = require('./animations'); const addState = connect( function receiveState(state) { - const { animSource, animTarget, resolution } = state; - return { animSource, animTarget, resolution }; + const { animSource, animTarget, resolution, account } = state; + return { animSource, animTarget, resolution, account }; } ); @@ -62,19 +62,21 @@ class ConstructAvatar extends Component { } componentDidUpdate(prevProps) { - const { animSource, animTarget, resolution, construct } = this.props; + const { animSource, animTarget, resolution, construct, account } = this.props; // a different text object and text construct - if (resolution && resolution !== prevProps.resolution && resolution.constructId === construct.id) { + if (resolution && resolution !== prevProps.resolution && resolution.event[1].construct === construct.id) { return wiggle(construct.id, this.idle); } // different source object and source construct - if (animSource && animSource !== prevProps.animSource && animSource.constructId === construct.id) { - return sourceCast(animSource.constructId, animSource.direction, this.idle); + if (animSource && animSource !== prevProps.animSource && animSource.event[1].construct === construct.id) { + const { construct: constructId, player, direction: [x, y] } = animSource.event[1]; + const animY = y && player === account.id ? -1 : y; + return sourceCast(constructId, { x, y: animY }, this.idle); } // different target object and target construct - if (animTarget && animTarget !== prevProps.animTarget && animTarget.constructId.includes(construct.id)) { + if (animTarget && animTarget !== prevProps.animTarget && animTarget.event[1].construct.includes(construct.id)) { switch (animTarget.skill) { case 'Banish': return banish(construct.id, this.idle); case 'Invert': return invert(construct.id, this.idle); diff --git a/client/src/components/game.construct.anim.text.jsx b/client/src/components/game.construct.anim.text.jsx index 07773ad7..e8ac9de9 100644 --- a/client/src/components/game.construct.anim.text.jsx +++ b/client/src/components/game.construct.anim.text.jsx @@ -55,8 +55,8 @@ class AnimText extends preact.Component { return

{amount} {mitigationText}

; } if (type === 'Healing') { - const { amount, overhealing } = event; - return

{amount} ({overhealing}OH)

; + const { amount, overhealing, colour } = event; + return

{amount} ({overhealing}OH)

; } if (type === 'Inversion') return

INVERT

; if (type === 'Reflection') return

REFLECT

; @@ -64,14 +64,6 @@ class AnimText extends preact.Component { const { effect, duration } = event; return

+{effect} {duration}T

; } - if (type === 'Recharge') { - const { red, blue } = event; - if (red > 0 && blue > 0) { - return

`+{red}R+{blue}B

; - } - if (red > 0) return

`+{red}R

; - if (blue > 0) return

`+{blue}R

; - } if (type === 'Removal') { const { effect } = event; if (!effect) return

Effect Removal

; diff --git a/client/src/events.jsx b/client/src/events.jsx index ea02db70..0bbbb386 100644 --- a/client/src/events.jsx +++ b/client/src/events.jsx @@ -77,7 +77,7 @@ function registerEvents(store) { } function setGame(game) { - const { game: currentGame, account, ws, animating } = store.getState(); + const { game: currentGame, ws, animating } = store.getState(); if (animating) return false; @@ -90,7 +90,7 @@ function registerEvents(store) { console.log(newRes); return eachSeries(newRes, (r, cb) => { const timeout = r.delay; - setAnimations(r, store, account); + setAnimations(r, store); return setTimeout(cb, timeout); }, err => { if (err) return console.error(err); diff --git a/core/src/game.rs b/core/src/game.rs index ee232af9..77b8ebb3 100644 --- a/core/src/game.rs +++ b/core/src/game.rs @@ -468,9 +468,18 @@ impl Game { } fn resolve(&mut self, cast: Cast) -> &mut Game { + // Send custom intial cast / hit aoe actions + if cast.skill.aoe() { + let actions = match cast.skill.cast_animation() { + true => vec![Action::Cast, Action::HitAoe], + false => vec![Action::HitAoe] + }; + self.execute(cast, actions); + } + let casts = self.modify_cast(cast); for cast in casts { - self.execute(cast); + self.execute(cast, cast.actions()); } self @@ -508,16 +517,17 @@ impl Game { return casts; } - fn execute(&mut self, cast: Cast) -> &mut Game { + fn execute(&mut self, cast: Cast, actions: Vec) -> &mut Game { // this list is used to calculate values // that are dependent on the result of previous events // such as healing based on damage done etc let mut event_list = vec![]; - for action in cast.actions() { + for action in actions { let events = match action { Action::Cast => self.cast(cast), Action::Hit => self.hit(cast), + Action::HitAoe => self.hit_aoe(cast), Action::Damage { construct, values, colour } => { let amount = self.reduce_values(&values, &event_list); @@ -616,6 +626,18 @@ impl Game { vec![Event::Hit { construct: cast.target, player: cast.player, direction: self.direction(cast) }] } + fn hit_aoe(&mut self, cast: Cast) -> Vec { + let construct = self.players.iter() + .find(|t| t.constructs.iter().any(|c| c.id == cast.target)) + .unwrap() + .constructs + .iter() + .map(|c| c.id) + .collect(); + + vec![Event::HitAoe { construct, player: cast.player, direction: self.direction(cast) }] + } + fn damage(&mut self, construct: Uuid, amount: usize, colour: Colour) -> Vec { self.construct_by_id(construct).unwrap().damage(amount, colour) } @@ -841,6 +863,7 @@ pub enum Value { #[derive(Debug,Clone,PartialEq)] pub enum Action { Hit, + HitAoe, Cast, Heal { construct: Uuid, values: Vec, colour: Colour }, Damage { construct: Uuid, values: Vec, colour: Colour }, @@ -848,7 +871,6 @@ pub enum Action { Remove { construct: Uuid, effect: Effect }, RemoveAll { construct: Uuid }, IncreaseCooldowns { construct: Uuid, turns: usize }, - // Recharge { skill: Skill, red: usize, blue: usize }, } #[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] @@ -864,7 +886,7 @@ impl Resolution { // maybe map events construct_ids let focus = match event { - Event::HitAoe { construct: _ } => vec![cast.source, cast.target], // fixme + Event::HitAoe { construct: _, player: _, direction: _ } => vec![cast.source], _ => vec![cast.source, cast.target], }; @@ -889,7 +911,7 @@ pub type Direction = (i8, i8); pub enum Event { Cast { construct: Uuid, player: Uuid, direction: Direction }, Hit { construct: Uuid, player: Uuid, direction: Direction }, - HitAoe { construct: Uuid }, + HitAoe { construct: Vec, player: Uuid, direction: Direction }, Damage { construct: Uuid, amount: usize, mitigation: usize, colour: Colour, display: EventConstruct }, Effect { construct: Uuid, effect: Effect, duration: u8, display: EventConstruct }, @@ -927,7 +949,7 @@ impl Event { } }, Event::Hit { construct: _, direction: _, player: _ } | - Event::HitAoe { construct: _ } => { + Event::HitAoe { construct: _, direction: _, player: _ } => { match next_event { Some(e) => { match e.event { diff --git a/core/src/skill.rs b/core/src/skill.rs index 5bfe2ed9..a50ad547 100644 --- a/core/src/skill.rs +++ b/core/src/skill.rs @@ -56,12 +56,13 @@ impl Cast { let mut actions = vec![]; - if self.skill.cast_animation() { - actions.push(Action::Cast); + if !self.skill.aoe() { + if self.skill.cast_animation() { + actions.push(Action::Cast); + } + actions.push(Action::Hit); } - actions.push(Action::Hit); - let mut rest = match self.skill { Skill::Attack => vec![ Action::Damage { @@ -1545,7 +1546,7 @@ impl Skill { } } - fn cast_animation(&self) -> bool { + pub fn cast_animation(&self) -> bool { match self { Skill::HybridBlast | Skill::HasteStrike |