add aoe events cleanup client anim code

This commit is contained in:
Mashy 2019-12-10 20:57:19 +10:00
parent 89fb27d858
commit 5ea22ec4b3
8 changed files with 81 additions and 72 deletions

View File

@ -1,40 +1,31 @@
const actions = require('./actions'); const actions = require('./actions');
const { TIMES } = require('./constants'); const { TIMES } = require('./constants');
function setAnimations(r, store, account) { function setAnimations(r, store) {
const { skill, focus, event: [type, variant] } = r; 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)); store.dispatch(actions.setAnimFocus(focus));
if (type === 'Cast') { if (type === 'Cast') {
store.dispatch(actions.setResolution(null)); store.dispatch(actions.setResolution(null));
store.dispatch(actions.setAnimSource(r));
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));
return setTimeout(() => store.dispatch(actions.setAnimSource(null)), TIMES.SOURCE_DURATION_MS); return setTimeout(() => store.dispatch(actions.setAnimSource(null)), TIMES.SOURCE_DURATION_MS);
} }
if (type.includes('Hit')) { if (type === 'Hit') {
store.dispatch(actions.setResolution(null)); store.dispatch(actions.setResolution(null));
store.dispatch(actions.setAnimTarget(r));
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));
return setTimeout(() => store.dispatch(actions.setAnimTarget(null)), TIMES.TARGET_DURATION_MS); return setTimeout(() => store.dispatch(actions.setAnimTarget(null)), TIMES.TARGET_DURATION_MS);
} }

View File

@ -44,8 +44,8 @@ const { removeTier } = require('../utils');
const addState = connect( const addState = connect(
function receiveState(state) { function receiveState(state) {
const { animTarget } = state; const { animTarget, account } = state;
return { animTarget }; return { animTarget, account };
} }
); );
@ -60,16 +60,18 @@ class ConstructAnimation extends Component {
const { const {
animTarget, animTarget,
construct, construct,
account,
} = props; } = props;
if (!animTarget) return false; if (!animTarget) return false;
const { const { skill, event: [, variant] } = animTarget;
skill, const { construct: constructId, player, direction: [x, y] } = variant;
player,
direction, const animY = y && player === account.id ? -1 : y;
constructId, const isPlayer = player === account.id;
} = animTarget; const direction = { x, y: animY };
const animSkill = removeTier(skill); const animSkill = removeTier(skill);
if (!constructId.includes(construct.id)) return false; if (!constructId.includes(construct.id)) return false;
@ -93,9 +95,9 @@ class ConstructAnimation extends Component {
case 'Haste': return <Haste />; case 'Haste': return <Haste />;
case 'Triage': return <Triage />; case 'Triage': return <Triage />;
case 'TriageTick': return <TriageTick />; case 'TriageTick': return <TriageTick />;
case 'Link': return <Link player={player} />; case 'Link': return <Link player={isPlayer} />;
case 'Hybrid': return <Hybrid />; case 'Hybrid': return <Hybrid />;
case 'Intercept': return <Intercept player={player} />; case 'Intercept': return <Intercept player={isPlayer} />;
// Debuff base // Debuff base
case 'Debuff': return <Debuff />; case 'Debuff': return <Debuff />;
@ -118,15 +120,15 @@ class ConstructAnimation extends Component {
// Block Base // Block Base
case 'Block': return <Block />; case 'Block': return <Block />;
case 'Sustain': return <Sustain player={player} />; case 'Sustain': return <Sustain player={isPlayer} />;
case 'Electrify': return <Electrify />; case 'Electrify': return <Electrify />;
case 'Electrocute': return <Electrocute />; case 'Electrocute': return <Electrocute />;
case 'ElectrocuteTick': return <Electrocute />; case 'ElectrocuteTick': return <Electrocute />;
case 'Counter': return <Counter player={player} />; case 'Counter': return <Counter player={isPlayer} />;
case 'CounterAttack': return <Attack direction={direction} />; case 'CounterAttack': return <Attack direction={direction} />;
case 'Purify': return <Purify player={player} />; case 'Purify': return <Purify player={isPlayer} />;
case 'Recharge': return <Recharge player={player} />; case 'Recharge': return <Recharge player={isPlayer} />;
case 'Reflect': return <Refl player={player} />; case 'Reflect': return <Refl player={isPlayer} />;
default: return false; default: return false;
} }

View File

@ -20,7 +20,6 @@ function projectile(x, y, radius, colour) {
class TriageTick extends Component { class TriageTick extends Component {
constructor(props) { constructor(props) {
super(); super();
this.team = props.team;
this.animations = []; this.animations = [];
const points = randomPoints(15, 10, { x: 0, y: 0, width: 300, height: 400 }); 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)); this.charges = points.map(coord => projectile(coord[0], coord[1], 15, COLOURS.GREEN));

View File

@ -13,8 +13,8 @@ const { ConstructAnimation } = require('./animations');
const addState = connect( const addState = connect(
function receiveState(state) { function receiveState(state) {
const { animSource, animTarget, resolution } = state; const { animSource, animTarget, resolution, account } = state;
return { animSource, animTarget, resolution }; return { animSource, animTarget, resolution, account };
} }
); );
@ -62,19 +62,21 @@ class ConstructAvatar extends Component {
} }
componentDidUpdate(prevProps) { componentDidUpdate(prevProps) {
const { animSource, animTarget, resolution, construct } = this.props; const { animSource, animTarget, resolution, construct, account } = this.props;
// a different text object and text construct // 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); return wiggle(construct.id, this.idle);
} }
// different source object and source construct // different source object and source construct
if (animSource && animSource !== prevProps.animSource && animSource.constructId === construct.id) { if (animSource && animSource !== prevProps.animSource && animSource.event[1].construct === construct.id) {
return sourceCast(animSource.constructId, animSource.direction, this.idle); 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 // 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) { switch (animTarget.skill) {
case 'Banish': return banish(construct.id, this.idle); case 'Banish': return banish(construct.id, this.idle);
case 'Invert': return invert(construct.id, this.idle); case 'Invert': return invert(construct.id, this.idle);

View File

@ -55,8 +55,8 @@ class AnimText extends preact.Component {
return <h1><span class={colour.toLowerCase()}>{amount} {mitigationText} </span></h1>; return <h1><span class={colour.toLowerCase()}>{amount} {mitigationText} </span></h1>;
} }
if (type === 'Healing') { if (type === 'Healing') {
const { amount, overhealing } = event; const { amount, overhealing, colour } = event;
return <h1><span>{amount} ({overhealing}OH)</span></h1>; return <h1><span class={colour.toLowerCase()}>{amount} ({overhealing}OH)</span></h1>;
} }
if (type === 'Inversion') return <h1><span>INVERT</span></h1>; if (type === 'Inversion') return <h1><span>INVERT</span></h1>;
if (type === 'Reflection') return <h1><span>REFLECT</span></h1>; if (type === 'Reflection') return <h1><span>REFLECT</span></h1>;
@ -64,14 +64,6 @@ class AnimText extends preact.Component {
const { effect, duration } = event; const { effect, duration } = event;
return <h1><span>+{effect} {duration}T</span></h1>; return <h1><span>+{effect} {duration}T</span></h1>;
} }
if (type === 'Recharge') {
const { red, blue } = event;
if (red > 0 && blue > 0) {
return <h1><span class="red">`+{red}R</span><span class="blue">+{blue}B</span></h1>;
}
if (red > 0) return <h1><span class="red">`+{red}R</span></h1>;
if (blue > 0) return <h1><span class="blue">`+{blue}R</span></h1>;
}
if (type === 'Removal') { if (type === 'Removal') {
const { effect } = event; const { effect } = event;
if (!effect) return <h1><span>Effect Removal</span></h1>; if (!effect) return <h1><span>Effect Removal</span></h1>;

View File

@ -77,7 +77,7 @@ function registerEvents(store) {
} }
function setGame(game) { function setGame(game) {
const { game: currentGame, account, ws, animating } = store.getState(); const { game: currentGame, ws, animating } = store.getState();
if (animating) return false; if (animating) return false;
@ -90,7 +90,7 @@ function registerEvents(store) {
console.log(newRes); console.log(newRes);
return eachSeries(newRes, (r, cb) => { return eachSeries(newRes, (r, cb) => {
const timeout = r.delay; const timeout = r.delay;
setAnimations(r, store, account); setAnimations(r, store);
return setTimeout(cb, timeout); return setTimeout(cb, timeout);
}, err => { }, err => {
if (err) return console.error(err); if (err) return console.error(err);

View File

@ -468,9 +468,18 @@ impl Game {
} }
fn resolve(&mut self, cast: Cast) -> &mut 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); let casts = self.modify_cast(cast);
for cast in casts { for cast in casts {
self.execute(cast); self.execute(cast, cast.actions());
} }
self self
@ -508,16 +517,17 @@ impl Game {
return casts; return casts;
} }
fn execute(&mut self, cast: Cast) -> &mut Game { fn execute(&mut self, cast: Cast, actions: Vec<Action>) -> &mut Game {
// this list is used to calculate values // this list is used to calculate values
// that are dependent on the result of previous events // that are dependent on the result of previous events
// such as healing based on damage done etc // such as healing based on damage done etc
let mut event_list = vec![]; let mut event_list = vec![];
for action in cast.actions() { for action in actions {
let events = match action { let events = match action {
Action::Cast => self.cast(cast), Action::Cast => self.cast(cast),
Action::Hit => self.hit(cast), Action::Hit => self.hit(cast),
Action::HitAoe => self.hit_aoe(cast),
Action::Damage { construct, values, colour } => { Action::Damage { construct, values, colour } => {
let amount = self.reduce_values(&values, &event_list); 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) }] vec![Event::Hit { construct: cast.target, player: cast.player, direction: self.direction(cast) }]
} }
fn hit_aoe(&mut self, cast: Cast) -> Vec<Event> {
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<Event> { fn damage(&mut self, construct: Uuid, amount: usize, colour: Colour) -> Vec<Event> {
self.construct_by_id(construct).unwrap().damage(amount, colour) self.construct_by_id(construct).unwrap().damage(amount, colour)
} }
@ -841,6 +863,7 @@ pub enum Value {
#[derive(Debug,Clone,PartialEq)] #[derive(Debug,Clone,PartialEq)]
pub enum Action { pub enum Action {
Hit, Hit,
HitAoe,
Cast, Cast,
Heal { construct: Uuid, values: Vec<Value>, colour: Colour }, Heal { construct: Uuid, values: Vec<Value>, colour: Colour },
Damage { construct: Uuid, values: Vec<Value>, colour: Colour }, Damage { construct: Uuid, values: Vec<Value>, colour: Colour },
@ -848,7 +871,6 @@ pub enum Action {
Remove { construct: Uuid, effect: Effect }, Remove { construct: Uuid, effect: Effect },
RemoveAll { construct: Uuid }, RemoveAll { construct: Uuid },
IncreaseCooldowns { construct: Uuid, turns: usize }, IncreaseCooldowns { construct: Uuid, turns: usize },
// Recharge { skill: Skill, red: usize, blue: usize },
} }
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] #[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
@ -864,7 +886,7 @@ impl Resolution {
// maybe map events construct_ids // maybe map events construct_ids
let focus = match event { 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], _ => vec![cast.source, cast.target],
}; };
@ -889,7 +911,7 @@ pub type Direction = (i8, i8);
pub enum Event { pub enum Event {
Cast { construct: Uuid, player: Uuid, direction: Direction }, Cast { construct: Uuid, player: Uuid, direction: Direction },
Hit { construct: Uuid, player: Uuid, direction: Direction }, Hit { construct: Uuid, player: Uuid, direction: Direction },
HitAoe { construct: Uuid }, HitAoe { construct: Vec<Uuid>, player: Uuid, direction: Direction },
Damage { construct: Uuid, amount: usize, mitigation: usize, colour: Colour, display: EventConstruct }, Damage { construct: Uuid, amount: usize, mitigation: usize, colour: Colour, display: EventConstruct },
Effect { construct: Uuid, effect: Effect, duration: u8, display: EventConstruct }, Effect { construct: Uuid, effect: Effect, duration: u8, display: EventConstruct },
@ -927,7 +949,7 @@ impl Event {
} }
}, },
Event::Hit { construct: _, direction: _, player: _ } | Event::Hit { construct: _, direction: _, player: _ } |
Event::HitAoe { construct: _ } => { Event::HitAoe { construct: _, direction: _, player: _ } => {
match next_event { match next_event {
Some(e) => { Some(e) => {
match e.event { match e.event {

View File

@ -56,12 +56,13 @@ impl Cast {
let mut actions = vec![]; let mut actions = vec![];
if self.skill.cast_animation() { if !self.skill.aoe() {
actions.push(Action::Cast); if self.skill.cast_animation() {
actions.push(Action::Cast);
}
actions.push(Action::Hit);
} }
actions.push(Action::Hit);
let mut rest = match self.skill { let mut rest = match self.skill {
Skill::Attack => vec![ Skill::Attack => vec![
Action::Damage { Action::Damage {
@ -1545,7 +1546,7 @@ impl Skill {
} }
} }
fn cast_animation(&self) -> bool { pub fn cast_animation(&self) -> bool {
match self { match self {
Skill::HybridBlast | Skill::HybridBlast |
Skill::HasteStrike | Skill::HasteStrike |