combat events init

This commit is contained in:
ntr 2019-04-12 16:08:54 +10:00
parent c0303c5b61
commit 4a081d6ec1
18 changed files with 143 additions and 391 deletions

View File

@ -501,6 +501,11 @@ header {
border: 1px solid whitesmoke;
margin-bottom: 1em;
justify-content: center;
transition-property: all;
transition-duration: 0.5s;
transition-delay: 0;
transition-timing-function: ease;
}
.cryp-box-top {
@ -584,6 +589,27 @@ header {
.cryp-box.ko {
animation: none;
opacity: 0.5;
filter: grayscale(100%);
}
.cryp-box.unfocus {
filter: blur(5px);
}
.cryp-box.red-damage {
filter: drop-shadow(0 0 0.2em red);
border-width: 5px;
color: red;
border-color: red;
}
.red-damage button {
border: 3px solid red;
color: red;
}
.red-damage .stats {
border-top: 3px solid red;
}
.team-player {

View File

@ -1,105 +0,0 @@
const preact = require('preact');
const range = require('lodash/range');
const { stringSort } = require('./../utils');
const molecule = require('./molecule');
const SpawnButton = require('./spawn.button');
const idSort = stringSort('id');
const COLOURS = [
'#a52a2a',
'#1FF01F',
'#3498db',
];
function CrypList(args) {
const {
cryps,
selectedCryps,
setSelectedCryps,
sendPlayerMmCrypsSet,
sendInstanceJoin,
sendCrypSpawn
} = args;
if (!cryps) return <div></div>;
// redux limitation + suggested workaround
// so much for dumb components
function selectCryp(id) {
// remove
const i = selectedCryps.findIndex(sid => sid === id);
if (i > -1) {
selectedCryps[i] = null;
return setSelectedCryps(selectedCryps);
}
// window insert
const insert = selectedCryps.findIndex(j => j === null);
if (insert === -1) return setSelectedCryps([id, null, null]);
selectedCryps[insert] = id;
return setSelectedCryps(selectedCryps);
}
const instanceJoinHidden = !selectedCryps.every(c => !!c);
const mmSet = (
<button
className={`menu-instance-btn full left ${instanceJoinHidden ? 'hidden' : ''}`}
disabled={instanceJoinHidden}
onClick={() => sendPlayerMmCrypsSet()}>
Set Matchmaking Team
</button>
);
const instanceJoin = (
<button
className={`menu-instance-btn full right ${instanceJoinHidden ? 'hidden' : ''}`}
disabled={instanceJoinHidden}
onClick={() => sendInstanceJoin()}>
Join New Instance
</button>
);
const crypPanels = cryps.sort(idSort).map(cryp => {
const colour = selectedCryps.indexOf(cryp.id);
const selected = colour > -1;
const borderColour = selected ? COLOURS[colour] : '#000000';
return (
<div
key={cryp.id}
className="menu-cryp-ctr">
<div
className="menu-cryp"
style={ { 'border-color': borderColour || 'whitesmoke' } }
onClick={() => selectCryp(cryp.id)} >
<figure className="img">
{molecule}
</figure>
<h2>{cryp.name}</h2>
</div>
</div>
);
});
const spawnButtonsNum = cryps.length < 3
? (3 - cryps.length)
: 1;
const spawnButtons = range(spawnButtonsNum)
.map(i => <SpawnButton key={i} i={i} spawn={name => sendCrypSpawn(name)} />);
return (
<div className="menu-cryps">
{mmSet}
{instanceJoin}
{crypPanels}
{spawnButtons}
</div>
);
}
module.exports = CrypList;

View File

@ -1,65 +0,0 @@
const { connect } = require('preact-redux');
const CrypList = require('./cryp.list.component');
const actions = require('./../actions');
const addState = connect(
function receiveState(state) {
const { ws, cryps, selectedCryps, instances } = state;
function sendInstanceJoin() {
if (selectedCryps.length) {
return ws.sendInstanceJoin(selectedCryps);
}
return false;
}
function sendPlayerMmCrypsSet() {
if (selectedCryps.length) {
return ws.sendPlayerMmCrypsSet(selectedCryps);
}
return false;
}
function sendCrypSpawn(name) {
return ws.sendCrypSpawn(name);
}
return { cryps, selectedCryps, sendInstanceJoin, sendCrypSpawn, sendPlayerMmCrypsSet };
},
function receiveDispatch(dispatch) {
function setSelectedCryps(crypIds) {
dispatch(actions.setSelectedCryps(crypIds));
}
function setActiveInstance(instance) {
dispatch(actions.setInstance(instance));
}
return {
setSelectedCryps,
setActiveInstance,
};
}
);
module.exports = addState(CrypList);
function sendCrypsSet() {
console.log('set crypos');
// return ws.sendGamePvp(crypIds);
}
function sendInstanceJoin() {
if (selectedCryps.length) {
return ws.sendInstanceJoin(selectedCryps);
}
return false;
}
return { instances, sendCrypsSet, sendInstanceJoin };
},

View File

@ -140,6 +140,11 @@ function GamePanel(props) {
function Cryp(cryp) {
const ko = cryp.green_life.value === 0 ? 'ko' : '';
const unfocus = () => {
if (!resolution) return false;
if (cryp.id === resolution.source.id || cryp.id === resolution.target.id) return false;
return 'unfocus';
};
const skills = range(0, 3).map(i => Skill(cryp, i));
@ -161,7 +166,7 @@ function GamePanel(props) {
key={cryp.id}
style={ activeSkill ? { cursor: 'pointer' } : {}}
onClick={onClick}
className={`cryp-box ${ko}`} >
className={`cryp-box ${ko} ${unfocus()}`} >
<div className="cryp-box-top">
<figure
className="img"
@ -193,6 +198,12 @@ function GamePanel(props) {
function OpponentCryp(cryp, i) {
const ko = cryp.green_life.value === 0 ? 'ko' : '';
const unfocus = () => {
if (!resolution) return false;
if (cryp.id === resolution.source.id || cryp.id === resolution.target.id) return false;
return 'unfocus';
};
const stats = [STATS.greenLife, STATS.redLife, STATS.blueLife].map((s, j) => (
<figure key={j} alt={s.stat}>
{s.svg(`stat-icon ${s.colour}`)}
@ -203,7 +214,7 @@ function GamePanel(props) {
return (
<div
key={i}
className={`cryp-box ${ko}`}
className={`cryp-box ${ko} ${unfocus()}`}
style={ activeSkill ? { cursor: 'pointer' } : {}}
onClick={() => selectSkillTarget(cryp.id)} >
<div className="cryp-box-top">

View File

@ -1,13 +1,8 @@
// import 'particles.js/particles';
const { connect } = require('preact-redux');
const actions = require('../actions');
const Game = require('./game.component');
// const config = require('./particles.config');
// const particlesJS = window.particlesJS;
const addState = connect(
function receiveState(state) {

View File

@ -1,7 +1,7 @@
const preact = require('preact');
const range = require('lodash/range');
const { ITEMS: { SKILLS, COLOURS, SPECS: SPEC_CONSTANT } } = require('./constants');
const { ITEMS: { SKILLS, COLOURS, SPECS: SPEC_CONSTANT } } = require('./../constants');
const { COLOUR_ICONS, STATS, SPECS } = require('../utils');
function Info(args) {

View File

@ -1,131 +0,0 @@
const preact = require('preact');
const range = require('lodash/range');
const { stringSort, NULL_UUID } = require('./../utils');
const molecule = require('./molecule');
const SpawnButton = require('./spawn.button');
const idSort = stringSort('id');
const COLOURS = [
'#a52a2a',
'#1FF01F',
'#3498db',
];
function CrypList(args) {
const {
cryps,
selectedCryps,
setSelectedCryps,
sendPlayerMmCrypsSet,
sendInstanceJoin,
sendCrypSpawn
} = args;
if (!cryps) return <div></div>;
// redux limitation + suggested workaround
// so much for dumb components
function selectCryp(id) {
// remove
const i = selectedCryps.findIndex(sid => sid === id);
if (i > -1) {
selectedCryps[i] = null;
return setSelectedCryps(selectedCryps);
}
// window insert
const insert = selectedCryps.findIndex(j => j === null);
if (insert === -1) return setSelectedCryps([id, null, null]);
selectedCryps[insert] = id;
return setSelectedCryps(selectedCryps);
}
const instanceJoinHidden = !selectedCryps.every(c => !!c);
const mmSet = (
<button
className={`menu-instance-btn full left ${instanceJoinHidden ? 'hidden' : ''}`}
disabled={instanceJoinHidden}
onClick={() => sendPlayerMmCrypsSet()}>
Set Matchmaking Team
</button>
);
const instanceJoin = (
<button
className={`menu-instance-btn full right ${instanceJoinHidden ? 'hidden' : ''}`}
disabled={instanceJoinHidden}
onClick={() => sendInstanceJoin()}>
Join New Instance
</button>
);
const crypPanels = cryps.sort(idSort).map(cryp => {
const colour = selectedCryps.indexOf(cryp.id);
const selected = colour > -1;
const borderColour = selected ? COLOURS[colour] : '#000000';
return (
<div
key={cryp.id}
className="menu-cryp-ctr">
<div
className="menu-cryp"
style={ { 'border-color': borderColour || 'whitesmoke' } }
onClick={() => selectCryp(cryp.id)} >
<figure className="img">
{molecule}
</figure>
<h2>{cryp.name}</h2>
</div>
</div>
);
});
const spawnButtonsNum = cryps.length < 3
? (3 - cryps.length)
: 1;
const spawnButtons = range(spawnButtonsNum)
.map(i => <SpawnButton key={i} i={i} spawn={name => sendCrypSpawn(name)} />);
return (
<div className="menu-cryps">
{mmSet}
{instanceJoin}
{crypPanels}
{spawnButtons}
</div>
);
}
function instanceList({ instances, setActiveInstance }) {
if (!instances) return <div>...</div>;
const instancePanels = instances.map(instance => {
const globalInstance = instance.instance === NULL_UUID;
const name = globalInstance
? 'Global Matchmaking'
: `${instance.instance.substring(0, 5)} | ${instance.score.wins} : ${instance.score.losses}`;
return (
<button
className={`menu-instance-btn right ${globalInstance ? 'full' : ''}`}
key={instance.id}
onClick={() => setActiveInstance(instance)}>
{name}
</button>
);
});
return (
<section className="menu-instance-list" >
{instancePanels}
</section>
);
}
module.exports = instanceList;

View File

@ -1,35 +0,0 @@
const { connect } = require('preact-redux');
const actions = require('../actions');
const InstanceList = require('./instance.list.component');
const addState = connect(
function receiveState(state) {
const { ws, selectedCryps, instances } = state;
function sendCrypsSet() {
console.log('set crypos');
// return ws.sendGamePvp(crypIds);
}
function sendInstanceJoin() {
if (selectedCryps.length) {
return ws.sendInstanceJoin(selectedCryps);
}
return false;
}
return { instances, sendCrypsSet, sendInstanceJoin };
},
function receiveDispatch(dispatch) {
function setActiveInstance(instance) {
dispatch(actions.setInstance(instance));
}
return { setActiveInstance };
}
);
module.exports = addState(InstanceList);

View File

@ -20,7 +20,7 @@ function Menu(args) {
cryps,
selectedCryps,
setSelectedCryps,
setActiveInstance,
sendPlayerState,
sendPlayerMmCrypsSet,
sendInstanceJoin,
sendCrypSpawn,
@ -40,7 +40,7 @@ function Menu(args) {
<button
className={`menu-instance-btn right ${globalInstance ? 'full' : ''}`}
key={instance.id}
onClick={() => setActiveInstance(instance)}>
onClick={() => sendPlayerState(instance)}>
{name}
</button>
);

View File

@ -25,10 +25,15 @@ const addState = connect(
return ws.sendCrypSpawn(name);
}
function sendPlayerState(instance) {
return ws.sendPlayerState(instance.instance);
}
return {
cryps,
selectedCryps,
sendInstanceJoin,
sendPlayerState,
sendCrypSpawn,
sendPlayerMmCrypsSet,
instances,
@ -40,13 +45,8 @@ const addState = connect(
dispatch(actions.setSelectedCryps(crypIds));
}
function setActiveInstance(instance) {
dispatch(actions.setInstance(instance));
}
return {
setSelectedCryps,
setActiveInstance,
};
}
);

View File

@ -1,4 +1,8 @@
module.exports = {
TIMES: {
RESOLUTION_TIME_MS: 2000,
},
ITEMS: {
SKILLS: {
Amplify: {

View File

@ -2,6 +2,7 @@ const toast = require('izitoast');
const eachSeries = require('async/eachSeries');
const actions = require('./actions');
const { TIMES } = require('./constants');
function registerEvents(store) {
function setCryps(cryps) {
@ -23,7 +24,7 @@ function registerEvents(store) {
const newRes = game.resolved.slice(currentGame.resolved.length);
return eachSeries(newRes, (r, cb) => {
store.dispatch(actions.setResolution(r));
return setTimeout(cb, 500);
return setTimeout(cb, TIMES.RESOLUTION_TIME_MS);
}, err => {
if (err) return console.error(err);
store.dispatch(actions.setResolution(null));

View File

@ -97,6 +97,60 @@ const COLOUR_ICONS = {
green: { colour: 'green', caption: 'green', svg: shapes.square },
};
function eventClasses(resolution) {
const [type, event] = resolution.event;
if (type === 'Ko') {
return 'ko';
}
if (type === 'Disable') {
const { skill, disable } = event;
}
if (type === 'Immunity') {
const { skill, immunity } = event;
}
if (type === 'TargetKo') {
const { skill } = event;
}
if (type === 'Damage') {
const { skill, amount, mitigation, colour } = event;
}
if (type === 'Healing') {
const { skill, amount, overhealing } = event;
}
if (type === 'Inversion') {
const { skill } = event;
}
if (type === 'Reflection') {
const { skill } = event;
}
if (type === 'Effect') {
const { skill, effect, duration } = event;
}
if (type === 'Removal') {
const { effect } = event;
}
if (type === 'Recharge') {
const { skill, red, blue } = event;
}
if (type === 'Evasion') {
const { skill, evasion_rating } = event;
}
return false;
}
module.exports = {
stringSort,
numSort,

View File

@ -25,9 +25,6 @@
* resolve animations + effects
*SERVER*
cryp vbox
update defensives in skill.rs
consolidate buffs debuffs and disables
no more red/blue

View File

@ -536,7 +536,7 @@ impl Cryp {
skill,
amount: delta,
mitigation: 0,
category: Category::GreenDamage,
colour: Category::GreenDamage,
});
}
}
@ -584,7 +584,7 @@ impl Cryp {
skill,
amount: delta,
mitigation,
category: Category::RedDamage,
colour: Category::RedDamage,
});
},
true => {
@ -653,7 +653,7 @@ impl Cryp {
skill,
amount: delta,
mitigation,
category: Category::BlueDamage,
colour: Category::BlueDamage,
});
},
true => {

View File

@ -512,7 +512,7 @@ impl Game {
fn log_resolution(&mut self, speed: u64, resolution: &Resolution) -> &mut Game {
let Resolution { source, target, event } = resolution;
match event {
Event::Ko =>
Event::Ko { skill: _ }=>
self.log.push(format!("{:} KO!", target.name)),
Event::Disable { skill, disable } =>
@ -527,7 +527,7 @@ impl Game {
self.log.push(format!("[{:}] {:} {:?} {:} - target is KO",
speed, source.name, skill, target.name)),
Event::Damage { skill, amount, mitigation, category: _ } =>
Event::Damage { skill, amount, mitigation, colour: _ } =>
self.log.push(format!("[{:}] {:} {:?} {:} {:} ({:} mitigated)",
speed, source.name, skill, target.name, amount, mitigation)),

View File

@ -94,7 +94,7 @@ pub fn resolve(skill: Skill, source: &mut Cryp, target: &mut Cryp, mut resolutio
// have to think
for r in resolutions.clone() {
match r.event {
Event::Damage { amount, skill, mitigation: _, category: _ } => {
Event::Damage { amount, skill, mitigation: _, colour: _ } => {
if target.affected(Effect::Corrupt) {
resolutions = corruption(target, source, resolutions);
}
@ -113,7 +113,7 @@ pub fn resolve(skill: Skill, source: &mut Cryp, target: &mut Cryp, mut resolutio
// i don't think we need to check the source being ko
if target.is_ko() {
resolutions.push(Resolution::new(source, target).event(Event::Ko));
resolutions.push(Resolution::new(source, target).event(Event::Ko { skill }));
target.effects.clear();
}
@ -191,7 +191,7 @@ impl Resolution {
pub enum Event {
Disable { skill: Skill, disable: Disable },
Immunity { skill: Skill, immunity: Immunity },
Damage { skill: Skill, amount: u64, mitigation: u64, category: Category },
Damage { skill: Skill, amount: u64, mitigation: u64, colour: Category },
Healing { skill: Skill, amount: u64, overhealing: u64 },
Recharge { skill: Skill, red: u64, blue: u64 },
Inversion { skill: Skill },
@ -200,8 +200,8 @@ pub enum Event {
Removal { effect: Effect },
Evasion { skill: Skill, evasion_rating: u64 },
TargetKo { skill: Skill },
Ko,
// skill not necessary but makes it neater as all events are arrays in js
Ko { skill: Skill },
Incomplete,
}
@ -1058,7 +1058,7 @@ fn siphon_tick(source: &mut Cryp, target: &mut Cryp, mut results: Resolutions) -
for e in siphon_events {
match e {
Event::Damage { amount, mitigation: _, category: _, skill: _ } => {
Event::Damage { amount, mitigation: _, colour: _, skill: _ } => {
let dmg = source.deal_green_damage(Skill::Siphon, amount);
for e in dmg {
results.push(Resolution::new(source, target).event(e));
@ -1168,7 +1168,7 @@ mod tests {
let Resolution { source: _, target: _, event } = results.remove(0);
match event {
Event::Damage { amount, mitigation: _, category: _, skill: _ } => assert_eq!(amount, 50),
Event::Damage { amount, mitigation: _, colour: _, skill: _ } => assert_eq!(amount, 50),
_ => panic!("not damage"),
};
}
@ -1191,7 +1191,7 @@ mod tests {
let Resolution { source: _, target: _, event } = results.remove(0);
match event {
Event::Damage { amount, mitigation: _, category: _, skill: _ } => assert_eq!(amount, 1023),
Event::Damage { amount, mitigation: _, colour: _, skill: _ } => assert_eq!(amount, 1023),
_ => panic!("not damage"),
};
}
@ -1273,7 +1273,7 @@ mod tests {
let Resolution { source: _, target: _, event } = results.remove(0);
match event {
Event::Damage { amount, mitigation: _, category: _, skill: _ } => assert_eq!(amount, 256),
Event::Damage { amount, mitigation: _, colour: _, skill: _ } => assert_eq!(amount, 256),
_ => panic!("not damage"),
};
}
@ -1307,7 +1307,7 @@ mod tests {
let Resolution { source: _, target: _, event } = results.remove(0);
match event {
Event::Damage { amount, skill: _, mitigation: _, category: _} => assert_eq!(amount, 256),
Event::Damage { amount, skill: _, mitigation: _, colour: _} => assert_eq!(amount, 256),
_ => panic!("not damage siphon"),
};

View File

@ -295,29 +295,29 @@ impl From<Skill> for Var {
impl From<Spec> for Var {
fn from(spec: Spec) -> Var {
match spec {
Spec::Speed => Var::Speed,
Spec::RedSpeedI => Var::RedSpeedI,
Spec::BlueSpeedI => Var::BlueSpeedI,
Spec::GreenSpeedI => Var::GreenSpeedI,
Spec::GRSpeedI => Var::GRSpeedI,
Spec::GBSpeedI => Var::GBSpeedI,
Spec::RBSpeedI => Var::RBSpeedI,
Spec::Speed => Var::Speed,
Spec::RedSpeedI => Var::RedSpeedI,
Spec::BlueSpeedI => Var::BlueSpeedI,
Spec::GreenSpeedI => Var::GreenSpeedI,
Spec::GRSpeedI => Var::GRSpeedI,
Spec::GBSpeedI => Var::GBSpeedI,
Spec::RBSpeedI => Var::RBSpeedI,
Spec::Damage => Var::Damage,
Spec::RedDamageI => Var::RedDamageI,
Spec::BlueDamageI => Var::BlueDamageI,
Spec::GreenDamageI => Var::GreenDamageI,
Spec::GRDI => Var::GRDI,
Spec::GBDI => Var::GBDI,
Spec::RBDI => Var::RBDI,
Spec::Damage => Var::Damage,
Spec::RedDamageI => Var::RedDamageI,
Spec::BlueDamageI => Var::BlueDamageI,
Spec::GreenDamageI => Var::GreenDamageI,
Spec::GRDI => Var::GRDI,
Spec::GBDI => Var::GBDI,
Spec::RBDI => Var::RBDI,
Spec::Life => Var::Life,
Spec::GRLI => Var::GRLI,
Spec::GBLI => Var::GBLI,
Spec::RBLI => Var::RBLI,
Spec::GreenLifeI => Var::GreenLifeI,
Spec::RedLifeI => Var::RedLifeI,
Spec::BlueLifeI => Var::BlueLifeI,
Spec::Life => Var::Life,
Spec::GRLI => Var::GRLI,
Spec::GBLI => Var::GBLI,
Spec::RBLI => Var::RBLI,
Spec::GreenLifeI => Var::GreenLifeI,
Spec::RedLifeI => Var::RedLifeI,
Spec::BlueLifeI => Var::BlueLifeI,
// _ => panic!("{:?} not implemented as a var", spec),
}
}