reimplement animations

This commit is contained in:
ntr 2019-12-18 16:32:29 +10:00
parent 14ddc0b237
commit 90bffcb6b7
8 changed files with 161 additions and 188 deletions

View File

@ -4,9 +4,7 @@ const toast = require('izitoast');
const eachSeries = require('async/eachSeries'); const eachSeries = require('async/eachSeries');
const actions = require('./actions'); const actions = require('./actions');
const { TIMES } = require('./constants'); const { setAnimations, clearAnimations } = require('./animations.utils');
const animations = require('./animations.utils');
const { removeTier } = require('./utils');
const SOCKET_URL = process.env.NODE_ENV === 'production' ? 'wss://mnml.gg/api/ws' : 'ws://localhost/api/ws'; const SOCKET_URL = process.env.NODE_ENV === 'production' ? 'wss://mnml.gg/api/ws' : 'ws://localhost/api/ws';
@ -20,73 +18,32 @@ function createSocket(store) {
ws.send(cbor.encode(msg)); ws.send(cbor.encode(msg));
} }
function sendDevResolve(a, b, skill) { function sendDevResolve(skill) {
send(['DevResolve', { a, b, skill }]); send(['DevResolve', { skill }]);
} }
function onDevResolutions(newRes) { function setGame(game) {
const { game, account, animating } = store.getState(); store.dispatch(actions.setGame(game));
if (animating) return false;
store.dispatch(actions.setAnimating(true)); store.dispatch(actions.setAnimating(true));
store.dispatch(actions.setGameSkillInfo(null));
// stop fetching the game state til animations are done // stop fetching the game state til animations are done
const newRes = game.resolutions[game.resolutions.length - 1];
return eachSeries(newRes, (r, cb) => { return eachSeries(newRes, (r, cb) => {
if (!r.event) return cb(); // if (r.delay === 0) return cb(); // TargetKo etc
const timeout = animations.getTime(r.stages); setAnimations(r, store);
const anims = animations.getObjects(r, game, account); return setTimeout(cb, r.delay);
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));
}
if (r.stages.includes('END_SKILL') && anims.animTarget) {
store.dispatch(actions.setAnimTarget(anims.animTarget));
if (animations.isCbAnim(anims.animSkill)) store.dispatch(actions.setAnimCb(cb));
}
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.setResolution(text));
} else {
setTimeout(
() => store.dispatch(actions.setResolution(text)),
timeout - TIMES.POST_SKILL_DURATION_MS
);
}
}
return setTimeout(() => {
store.dispatch(actions.setAnimSkill(null));
store.dispatch(actions.setAnimSource(null));
store.dispatch(actions.setAnimTarget(null));
store.dispatch(actions.setResolution(null));
store.dispatch(actions.setAnimFocus([]));
if (r.stages.includes('END_SKILL') && animations.isCbAnim(anims.animSkill)) return true;
return cb();
}, timeout);
}, err => { }, err => {
if (err) return console.error(err); if (err) return console.error(err);
// clear animation state clearAnimations(store);
store.dispatch(actions.setAnimSkill(null));
store.dispatch(actions.setAnimSource(null));
store.dispatch(actions.setAnimTarget(null));
store.dispatch(actions.setResolution(null));
store.dispatch(actions.setAnimating(false));
store.dispatch(actions.setGameEffectInfo(null));
// set the game state so resolutions don't fire twice // set the game state so resolutions don't fire twice
store.dispatch(actions.setGame(game)); store.dispatch(actions.setGame(game));
// ws.sendGameState(game.id);
return true; return true;
}); });
} }
const handlers = { const handlers = {
DevResolutions: onDevResolutions, GameState: setGame,
}; };
// decodes the cbor and // decodes the cbor and

View File

@ -5,18 +5,7 @@ const { createStore, combineReducers } = require('redux');
const reducers = require('./reducers'); const reducers = require('./reducers');
const actions = require('./actions'); const actions = require('./actions');
const createSocket = require('./animations.socket'); const createSocket = require('./animations.socket');
// const TrippyTriangle = require('./components/svgs/trippy.triangle');
// const Amplify = require('./components/svgs/amplify');
// const Hex = require('./components/svgs/hex');
const Game = require('./components/game'); const Game = require('./components/game');
const testGameBuilder = require('./test.game');
const testGame = testGameBuilder('8552e0bf-340d-4fc8-b6fc-cccccccccccc');
const testAccount = {
id: '8552e0bf-340d-4fc8-b6fc-cccccccccccc',
name: 'ntr',
};
// Redux Store // Redux Store
const store = createStore( const store = createStore(
@ -24,20 +13,15 @@ const store = createStore(
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(), window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(),
); );
const testAccount = {
id: '8552e0bf-340d-4fc8-b6fc-cccccccccccc',
name: 'ntr',
};
store.dispatch(actions.setAccount(testAccount)); store.dispatch(actions.setAccount(testAccount));
store.dispatch(actions.setGame(testGame));
function animationsNav(ws) { function animationsNav(ws) {
function useSkill(skill) { function useSkill(skill) {
const ateam = Math.round(Math.random()); return ws.sendDevResolve(skill);
const bteam = Math.round(Math.random());
const acon = Math.floor(Math.random() * 3);
const bcon = Math.floor(Math.random() * 3);
const a = testGame.players[ateam].constructs[acon].id;
const b = testGame.players[bteam].constructs[bcon].id;
return ws.sendDevResolve(a, b, skill);
} }
return SKILLS.map((s, i) => ( return SKILLS.map((s, i) => (
@ -81,19 +65,19 @@ const SKILLS = [
'Buff', 'Buff',
'Chaos', 'Chaos',
'Counter', 'Counter',
'CounterAttack', // 'CounterAttack',
'Curse', 'Curse',
'Debuff', 'Debuff',
'Decay', 'Decay',
'DecayTick', 'DecayTick',
'Electrify', 'Electrify',
'Electrocute', 'Electrocute',
'ElectrocuteTick', // 'ElectrocuteTick',
'Haste', 'Haste',
'HasteStrike', // 'HasteStrike',
'Heal', 'Heal',
'Hybrid', 'Hybrid',
'HybridBlast', // 'HybridBlast',
'Intercept', 'Intercept',
'Invert', 'Invert',
'Link', 'Link',
@ -105,12 +89,12 @@ const SKILLS = [
'Ruin', 'Ruin',
'Silence', 'Silence',
'Siphon', 'Siphon',
'SiphonTick', // 'SiphonTick',
'Slay', 'Slay',
'Sleep', 'Sleep',
'Strike', 'Strike',
'Stun', 'Stun',
'Sustain', 'Sustain',
'Triage', 'Triage',
'TriageTick', // 'TriageTick',
]; ];

View File

@ -75,7 +75,6 @@ class ConstructAnimation extends Component {
const animSkill = removeTier(skill); const animSkill = removeTier(skill);
if (!constructId.includes(construct.id)) return false; if (!constructId.includes(construct.id)) return false;
// find target animation // find target animation
const chooseAnim = () => { const chooseAnim = () => {
switch (animSkill) { switch (animSkill) {

View File

@ -87,7 +87,6 @@ function registerEvents(store) {
store.dispatch(actions.setGameSkillInfo(null)); store.dispatch(actions.setGameSkillInfo(null));
// stop fetching the game state til animations are done // stop fetching the game state til animations are done
const newRes = game.resolutions[game.resolutions.length - 1]; const newRes = game.resolutions[game.resolutions.length - 1];
console.log(newRes);
return eachSeries(newRes, (r, cb) => { return eachSeries(newRes, (r, cb) => {
if (r.delay === 0) return cb(); // TargetKo etc if (r.delay === 0) return cb(); // TargetKo etc
setAnimations(r, store); setAnimations(r, store);

View File

@ -1596,54 +1596,53 @@ mod tests {
// } // }
// #[test] #[test]
// fn sleep_cooldown_test() { fn sleep_cooldown_test() {
// let mut game = create_test_game(); let mut game = create_test_game();
// let x_player = game.players[0].clone(); let x_player = game.players[0].clone();
// let y_player = game.players[1].clone(); let y_player = game.players[1].clone();
// let x_construct = x_player.constructs[0].clone(); let x_construct = x_player.constructs[0].clone();
// let y_construct = y_player.constructs[0].clone(); let y_construct = y_player.constructs[0].clone();
// for _n in 1..10 { for _n in 1..10 {
// // should auto progress back to skill phase // should auto progress back to skill phase
// assert!(game.phase == Phase::Skill); assert!(game.phase == Phase::Skill);
// // Sleep 2T CD // Sleep 2T CD
// assert!(game.player_by_id(x_player.id).unwrap().constructs[0].skill_on_cd(Skill::Decay).is_none()); assert!(game.player_by_id(x_player.id).unwrap().constructs[0].skill_on_cd(Skill::Decay).is_none());
// assert!(game.player_by_id(x_player.id).unwrap().constructs[0].skill_on_cd(Skill::Sleep).is_some()); assert!(game.player_by_id(x_player.id).unwrap().constructs[0].skill_on_cd(Skill::Sleep).is_some());
// game.player_ready(x_player.id).unwrap(); game.player_ready(x_player.id).unwrap();
// game.player_ready(y_player.id).unwrap(); game.player_ready(y_player.id).unwrap();
// game = game.resolve_phase_start(); game = game.resolve_phase_start();
// // Sleep 1T CD // Sleep 1T CD
// assert!(game.player_by_id(x_player.id).unwrap().constructs[0].skill_on_cd(Skill::Decay).is_none()); assert!(game.player_by_id(x_player.id).unwrap().constructs[0].skill_on_cd(Skill::Decay).is_none());
// assert!(game.player_by_id(x_player.id).unwrap().constructs[0].skill_on_cd(Skill::Sleep).is_some()); assert!(game.player_by_id(x_player.id).unwrap().constructs[0].skill_on_cd(Skill::Sleep).is_some());
// game.add_skill(x_player.id, x_construct.id, y_construct.id, Skill::Decay).unwrap(); game.add_skill(x_player.id, x_construct.id, y_construct.id, Skill::Decay).unwrap();
// // game.add_skill(x_player.id, x_construct.id, y_construct.id, Skill::Attack).unwrap(); // game.add_skill(x_player.id, x_construct.id, y_construct.id, Skill::Attack).unwrap();
// game.player_ready(x_player.id).unwrap(); game.player_ready(x_player.id).unwrap();
// game.player_ready(y_player.id).unwrap(); game.player_ready(y_player.id).unwrap();
// game = game.resolve_phase_start(); game = game.resolve_phase_start();
// // Sleep 0T CD (we use it here) // Sleep 0T CD (we use it here)
// assert!(game.player_by_id(x_player.id).unwrap().constructs[0].skill_on_cd(Skill::Decay).is_none()); assert!(game.player_by_id(x_player.id).unwrap().constructs[0].skill_on_cd(Skill::Decay).is_none());
// assert!(game.player_by_id(x_player.id).unwrap().constructs[0].skill_on_cd(Skill::Sleep).is_none()); assert!(game.player_by_id(x_player.id).unwrap().constructs[0].skill_on_cd(Skill::Sleep).is_none());
// game.add_skill(x_player.id, x_construct.id, y_construct.id, Skill::Sleep).unwrap(); game.add_skill(x_player.id, x_construct.id, y_construct.id, Skill::Sleep).unwrap();
// game.player_ready(x_player.id).unwrap(); game.player_ready(x_player.id).unwrap();
// game.player_ready(y_player.id).unwrap(); game.player_ready(y_player.id).unwrap();
// game = game.resolve_phase_start(); game = game.resolve_phase_start();
// // Sleep back to 2T CD // Sleep back to 2T CD
// assert!(game.player_by_id(x_player.id).unwrap().constructs[0].skill_on_cd(Skill::Decay).is_none()); assert!(game.player_by_id(x_player.id).unwrap().constructs[0].skill_on_cd(Skill::Decay).is_none());
// assert!(game.player_by_id(x_player.id).unwrap().constructs[0].skill_on_cd(Skill::Sleep).is_some()); assert!(game.player_by_id(x_player.id).unwrap().constructs[0].skill_on_cd(Skill::Sleep).is_some());
// } }
}
// }
// #[test] // #[test]
// fn counter_test() { // fn counter_test() {
@ -1885,52 +1884,52 @@ mod tests {
// } // }
// } // }
// #[test] #[test]
// fn ko_pve_test() { fn ko_pve_test() {
// let mut game = create_2v2_test_game(); let mut game = create_2v2_test_game();
// let i_player = game.players[0].clone(); let i_player = game.players[0].clone();
// let x_player = game.players[1].clone(); let x_player = game.players[1].clone();
// let i_construct = i_player.constructs[0].clone(); let i_construct = i_player.constructs[0].clone();
// let j_construct = i_player.constructs[1].clone(); let j_construct = i_player.constructs[1].clone();
// let x_construct = x_player.constructs[0].clone(); let x_construct = x_player.constructs[0].clone();
// let y_construct = x_player.constructs[1].clone(); let y_construct = x_player.constructs[1].clone();
// game.add_skill(i_player.id, i_construct.id, x_construct.id, Skill::Attack).unwrap() game.add_skill(i_player.id, i_construct.id, x_construct.id, Skill::Attack).unwrap()
// .add_skill(i_player.id, j_construct.id, x_construct.id, Skill::Attack).unwrap() .add_skill(i_player.id, j_construct.id, x_construct.id, Skill::Attack).unwrap()
// .add_skill(x_player.id, x_construct.id, i_construct.id, Skill::Attack).unwrap() .add_skill(x_player.id, x_construct.id, i_construct.id, Skill::Attack).unwrap()
// .add_skill(x_player.id, y_construct.id, i_construct.id, Skill::Attack).unwrap() .add_skill(x_player.id, y_construct.id, i_construct.id, Skill::Attack).unwrap()
// .player_ready(i_player.id).unwrap() .player_ready(i_player.id).unwrap()
// .player_ready(x_player.id).unwrap(); .player_ready(x_player.id).unwrap();
// assert!(game.skill_phase_finished()); assert!(game.skill_phase_finished());
// game = game.resolve_phase_start(); game = game.resolve_phase_start();
// assert!([Phase::Skill, Phase::Finished].contains(&game.phase)); assert!([Phase::Skill, Phase::Finished].contains(&game.phase));
// // kill a construct // kill a construct
// game.player_by_id(i_player.id).unwrap().construct_by_id(i_construct.id).unwrap().green_life.reduce(usize::max_value()); game.player_by_id(i_player.id).unwrap().construct_by_id(i_construct.id).unwrap().green_life.reduce(usize::max_value());
// assert!(game.player_by_id(i_player.id).unwrap().skills_required() == 1); assert!(game.player_by_id(i_player.id).unwrap().skills_required() == 1);
// assert!(game.player_by_id(x_player.id).unwrap().skills_required() == 2); assert!(game.player_by_id(x_player.id).unwrap().skills_required() == 2);
// // add some more skills // add some more skills
// game.add_skill(i_player.id, j_construct.id, x_construct.id, Skill::Attack).unwrap(); game.add_skill(i_player.id, j_construct.id, x_construct.id, Skill::Attack).unwrap();
// game.add_skill(x_player.id, x_construct.id, j_construct.id, Skill::Attack).unwrap(); game.add_skill(x_player.id, x_construct.id, j_construct.id, Skill::Attack).unwrap();
// game.add_skill(x_player.id, y_construct.id, j_construct.id, Skill::Attack).unwrap(); game.add_skill(x_player.id, y_construct.id, j_construct.id, Skill::Attack).unwrap();
// assert!(game.add_skill(x_player.id, x_construct.id, i_construct.id, Skill::Attack).is_err()); assert!(game.add_skill(x_player.id, x_construct.id, i_construct.id, Skill::Attack).is_err());
// game.player_ready(i_player.id).unwrap(); game.player_ready(i_player.id).unwrap();
// game.player_ready(x_player.id).unwrap(); game.player_ready(x_player.id).unwrap();
// assert!(game.skill_phase_finished()); assert!(game.skill_phase_finished());
// game = game.resolve_phase_start(); game = game.resolve_phase_start();
// assert!(game.player_by_id(i_player.id).unwrap().skills_required() == 1); assert!(game.player_by_id(i_player.id).unwrap().skills_required() == 1);
// assert!(game.player_by_id(x_player.id).unwrap().skills_required() == 2); assert!(game.player_by_id(x_player.id).unwrap().skills_required() == 2);
// return; return;
// } }
// #[test] // #[test]
// fn tick_removal_test() { // fn tick_removal_test() {

View File

@ -1,10 +1,13 @@
use uuid::Uuid; use uuid::Uuid;
use std::iter; use std::iter;
use rand::prelude::*;
use construct::{Construct}; use construct::{Construct};
use names::{name}; use names::{name};
use player::{Player}; use player::{Player};
use game::{Game};
use skill::{Skill, Cast};
pub fn generate_mob() -> Construct { pub fn generate_mob() -> Construct {
let mob = Construct::new() let mob = Construct::new()
@ -28,3 +31,51 @@ pub fn bot_player() -> Player {
Player::new(bot_id, None, &name(), constructs).set_bot(true) Player::new(bot_id, None, &name(), constructs).set_bot(true)
} }
pub fn anim_test_game(skill: Skill) -> Game {
let mut rng = thread_rng();
let mut game = Game::new();
game
.set_player_num(2)
.set_player_constructs(3);
let x_id = Uuid::parse_str("8552e0bf-340d-4fc8-b6fc-cccccccccccc").unwrap();
let constructs = iter::repeat_with(||
generate_mob()
.set_account(x_id)
.learn(Skill::Attack))
.take(3)
.collect::<Vec<Construct>>();
let x_player = Player::new(x_id, None, &name(), constructs);
let id = Uuid::new_v4();
let constructs = iter::repeat_with(||
generate_mob()
.set_account(id)
.learn(Skill::Attack))
.take(3)
.collect::<Vec<Construct>>();
let y_player = Player::new(id, None, &name(), constructs);
game
.player_add(x_player).unwrap()
.player_add(y_player).unwrap();
game = game.start();
let x_id = game.players[0].id;
let x_construct = game.players[0].constructs[1].id;
let y_id = game.players[1].id;
let y_construct = game.players[1].constructs[1].id;
let cast = match rng.gen_bool(0.5) {
true => Cast::new(x_construct, x_id, y_construct, skill),
false => Cast::new(y_construct, y_id, x_construct, skill),
};
game.stack.push(cast);
game = game.resolve_phase_start();
return game;
}

View File

@ -199,20 +199,6 @@ impl Cast {
} }
} }
// pub fn dev_resolve(a_id: Uuid, b_id: Uuid, skill: Skill) {
// let mut resolutions =vec![];
// let mut a = Construct::new();
// a.id = a_id;
// let mut b = Construct::new();
// b.id = b_id;
// if skill.aoe() { // Send an aoe skill event for anims
// game.event(Event::new(&a, &b).event(Event::AoeSkill { skill }).stages(EventStages::StartEnd));
// }
// return cast_actions(skill, &mut a, &mut b, resolutions);
// }
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] #[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
pub enum Skill { pub enum Skill {
Attack, Attack,

View File

@ -53,7 +53,7 @@ use mnml_core::player::Player;
use mnml_core::vbox::{ItemType}; use mnml_core::vbox::{ItemType};
use mnml_core::item::Item; use mnml_core::item::Item;
use mnml_core::skill::Skill; use mnml_core::skill::Skill;
// use mnml_core::skill::{dev_resolve, Resolutions}; use mnml_core::mob::{anim_test_game};
use mnml_core::instance::{Instance}; use mnml_core::instance::{Instance};
use mtx; use mtx;
@ -88,8 +88,6 @@ pub enum RpcMessage {
Pong(()), Pong(()),
// DevResolutions(Resolutions),
QueueRequested(()), QueueRequested(()),
QueueJoined(()), QueueJoined(()),
QueueLeft(()), QueueLeft(()),
@ -108,7 +106,7 @@ pub enum RpcMessage {
pub enum RpcRequest { pub enum RpcRequest {
Ping {}, Ping {},
ItemInfo {}, ItemInfo {},
DevResolve { a: Uuid, b: Uuid, skill: Skill }, DevResolve { skill: Skill },
MtxConstructApply { mtx: mtx::MtxVariant, construct_id: Uuid, name: String }, MtxConstructApply { mtx: mtx::MtxVariant, construct_id: Uuid, name: String },
MtxConstructSpawn { }, MtxConstructSpawn { },
@ -171,8 +169,8 @@ impl Connection {
match v { match v {
RpcRequest::Ping {} => return Ok(RpcMessage::Pong(())), RpcRequest::Ping {} => return Ok(RpcMessage::Pong(())),
RpcRequest::ItemInfo {} => return Ok(RpcMessage::ItemInfo(item_info())), RpcRequest::ItemInfo {} => return Ok(RpcMessage::ItemInfo(item_info())),
// RpcRequest::DevResolve {a, b, skill } => RpcRequest::DevResolve { skill } =>
// return Ok(RpcMessage::DevResolutions(dev_resolve(a, b, skill))), return Ok(RpcMessage::GameState(anim_test_game(skill))),
_ => (), _ => (),
}; };