vbox specs

This commit is contained in:
ntr 2019-03-06 18:08:39 +11:00
parent 9ba8c478cc
commit 5ea6b911ad
5 changed files with 155 additions and 166 deletions

View File

@ -8,9 +8,13 @@ const {
function FindColour(item) { function FindColour(item) {
// Future add skills and use a constants lookup file ?? // Future add skills and use a constants lookup file ??
switch (item) { switch (item) {
case 'Green': return 0x61B329; case 'Green': return 0x396E26;
case 'Red': return 0xCC3333; case 'Red': return 0x622433;
case 'Blue': return 0x6633FF; case 'Blue': return 0x223158;
// case 'Green': return 0x043003;
// case 'Red': return 0x5C0202;
// case 'Blue': return 0x040345;
default: return 0x222222; default: return 0x222222;
} }
} }

View File

@ -20,7 +20,7 @@ class Header extends Phaser.Scene {
} }
create() { create() {
this.add.text(0, 0, 'cryps.gg', TEXT.HEADER); this.add.text(0, 0, 'CRYPS.GG', TEXT.HEADER);
} }
} }

View File

@ -10,7 +10,7 @@ use failure::err_msg;
use account::{Account}; use account::{Account};
use rpc::{CrypSpawnParams, CrypLearnParams, CrypForgetParams, CrypUnspecParams}; use rpc::{CrypSpawnParams, CrypLearnParams, CrypForgetParams, CrypUnspecParams};
use skill::{Skill, Cooldown, Effect, Cast, Category, Immunity, Disable, ResolutionResult}; use skill::{Skill, Cooldown, Effect, Cast, Category, Immunity, Disable, ResolutionResult};
use spec::{Spec, SpecLevel}; use spec::{Spec};
use game::{Log}; use game::{Log};
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] #[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
@ -49,8 +49,8 @@ pub enum Stat {
RedDamageTaken, RedDamageTaken,
BlueDamage, BlueDamage,
BlueDamageTaken, BlueDamageTaken,
Healing, GreenDamage,
HealingTaken, GreenDamageTaken,
RedShield, RedShield,
BlueShield, BlueShield,
Evasion, Evasion,
@ -64,13 +64,18 @@ pub struct CrypStat {
} }
impl CrypStat { impl CrypStat {
pub fn set(&mut self, v: u64, specs: &CrypSpecs) -> &mut CrypStat { pub fn set(&mut self, v: u64, specs: &Vec<Spec>) -> &mut CrypStat {
self.base = v; self.base = v;
self.recalculate(specs) self.recalculate(specs)
} }
pub fn recalculate(&mut self, specs: &CrypSpecs) -> &mut CrypStat { pub fn recalculate(&mut self, specs: &Vec<Spec>) -> &mut CrypStat {
let specs = specs.affects(self.stat); let specs = specs
.iter()
.filter(|s| s.affects() == self.stat)
.map(|s| *s)
.collect::<Vec<Spec>>();
// applied with fold because it can be zeroed or multiplied // applied with fold because it can be zeroed or multiplied
// but still needs access to the base amount // but still needs access to the base amount
let value = specs.iter().fold(self.base, |acc, s| s.apply(acc, self.base)); let value = specs.iter().fold(self.base, |acc, s| s.apply(acc, self.base));
@ -97,32 +102,6 @@ impl CrypStat {
} }
} }
#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct CrypSpecs {
common: Vec<Spec>,
uncommon: Vec<Spec>,
rare: Vec<Spec>,
}
impl CrypSpecs {
fn new() -> CrypSpecs {
CrypSpecs {
common: vec![],
uncommon: vec![],
rare: vec![],
}
}
fn affects(&self, stat: Stat) -> Vec<Spec> {
[&self.common, &self.uncommon, &self.rare]
.iter()
.flat_map(|specs| specs.iter().filter(|s| s.affects == stat))
.map(|s| *s)
.collect::<Vec<Spec>>()
}
}
#[derive(Debug,Clone,Serialize,Deserialize)] #[derive(Debug,Clone,Serialize,Deserialize)]
pub struct CrypRecover { pub struct CrypRecover {
pub id: Uuid, pub id: Uuid,
@ -148,7 +127,7 @@ pub struct Cryp {
pub lvl: u8, pub lvl: u8,
pub skills: Vec<CrypSkill>, pub skills: Vec<CrypSkill>,
pub effects: Vec<CrypEffect>, pub effects: Vec<CrypEffect>,
pub specs: CrypSpecs, pub specs: Vec<Spec>,
pub name: String, pub name: String,
pub ko_logged: bool, pub ko_logged: bool,
} }
@ -176,7 +155,7 @@ impl Cryp {
xp: 0, xp: 0,
skills: vec![], skills: vec![],
effects: vec![], effects: vec![],
specs: CrypSpecs::new(), specs: vec![],
name: String::new(), name: String::new(),
ko_logged: false, ko_logged: false,
}; };
@ -276,57 +255,14 @@ impl Cryp {
} }
pub fn spec_add(&mut self, spec: Spec) -> Result<&mut Cryp, Error> { pub fn spec_add(&mut self, spec: Spec) -> Result<&mut Cryp, Error> {
let max_common = 20; self.specs.push(spec);
let max_uncommon = 10;
let max_rare = 5;
match spec.level {
SpecLevel::Common => {
if self.specs.common.len() >= max_common {
return Err(format_err!("cryp at maximum common specalisations ({:})", max_common))
}
self.specs.common.push(spec);
},
SpecLevel::Uncommon => {
if self.specs.uncommon.len() >= max_uncommon {
return Err(format_err!("cryp at maximum uncommon specalisations ({:})", max_uncommon))
}
self.specs.uncommon.push(spec);
},
SpecLevel::Rare => {
if self.specs.rare.len() >= max_rare {
return Err(format_err!("cryp at maximum rare specalisations ({:})", max_rare))
}
if self.specs.rare.iter().find(|s| s.spec == spec.spec).is_some() {
return Err(format_err!("duplicate rare specialisation {:?}", spec.spec));
}
self.specs.rare.push(spec);
},
};
return Ok(self.recalculate_stats()); return Ok(self.recalculate_stats());
} }
pub fn spec_remove(&mut self, spec: Spec) -> Result<&mut Cryp, Error> { pub fn spec_remove(&mut self, spec: Spec) -> Result<&mut Cryp, Error> {
let find_spec = |spec_v: &Vec<Spec>| spec_v.iter().position(|s| s.spec == spec.spec); match self.specs.iter().position(|s| *s == spec) {
Some(p) => self.specs.remove(p),
match spec.level {
SpecLevel::Common => match find_spec(&self.specs.common) {
Some(p) => self.specs.common.remove(p),
None => return Err(err_msg("spec not found")), None => return Err(err_msg("spec not found")),
},
SpecLevel::Uncommon => match find_spec(&self.specs.uncommon) {
Some(p) => self.specs.uncommon.remove(p),
None => return Err(err_msg("spec not found")),
},
SpecLevel::Rare => match find_spec(&self.specs.rare) {
Some(p) => self.specs.rare.remove(p),
None => return Err(err_msg("spec not found")),
},
}; };
Ok(self.recalculate_stats()) Ok(self.recalculate_stats())
@ -529,7 +465,7 @@ impl Cryp {
} }
let healing_mods = self.effects.iter() let healing_mods = self.effects.iter()
.filter(|e| e.effect.modifications().contains(&Stat::HealingTaken)) .filter(|e| e.effect.modifications().contains(&Stat::GreenDamageTaken))
.map(|cryp_effect| cryp_effect.effect) .map(|cryp_effect| cryp_effect.effect)
.collect::<Vec<Effect>>(); .collect::<Vec<Effect>>();

View File

@ -1,54 +1,33 @@
use cryp::{Stat}; use cryp::{Stat};
#[derive(Debug,Copy,Clone,Serialize,Deserialize)] #[derive(Debug,Copy,Clone,Serialize,Deserialize,PartialEq)]
pub enum SpecLevel { pub enum Spec {
Common, SpeedI,
Uncommon, StaminaI,
Rare, RedDamageI,
} GreenDamageI,
BlueDamageI,
#[derive(Debug,Copy,Clone,Serialize,Deserialize)]
pub struct Spec {
pub affects: Stat,
pub spec: SpecType,
pub level: SpecLevel,
} }
impl Spec { impl Spec {
pub fn new(spec_type: SpecType) -> Spec { pub fn affects(&self) -> Stat {
Spec { match *self {
affects: spec_type.affects(), Spec::RedDamageI => Stat::RedDamage,
level: spec_type.level(), Spec::GreenDamageI => Stat::GreenDamage,
spec: spec_type, Spec::BlueDamageI => Stat::BlueDamage,
Spec::SpeedI => Stat::Speed,
Spec::StaminaI => Stat::Stamina,
} }
} }
pub fn apply(&self, modified: u64, base: u64) -> u64 { pub fn apply(&self, modified: u64, base: u64) -> u64 {
match self.spec {
SpecType::RedDamage5 => modified + (base * 5 / 100),
SpecType::BlueDamage5 => modified + (base * 5 / 100),
}
}
}
#[derive(Debug,Copy,Clone,Serialize,Deserialize,PartialEq)]
pub enum SpecType {
RedDamage5,
BlueDamage5,
}
impl SpecType {
fn affects(&self) -> Stat {
match *self { match *self {
SpecType::RedDamage5 => Stat::RedDamage, Spec::RedDamageI => modified + (base * 5 / 100),
SpecType::BlueDamage5 => Stat::BlueDamage, Spec::GreenDamageI => modified + (base * 5 / 100),
Spec::BlueDamageI => modified + (base * 5 / 100),
Spec::SpeedI => modified + (base * 5 / 100),
Spec::StaminaI => modified + (base * 5 / 100),
} }
} }
fn level(&self) -> SpecLevel {
match *self {
SpecType::RedDamage5 => SpecLevel::Common,
SpecType::BlueDamage5 => SpecLevel::Common,
}
}
} }

View File

@ -14,6 +14,7 @@ use failure::err_msg;
use account::Account; use account::Account;
use rpc::{VboxAcceptParams, VboxDiscardParams, VboxCombineParams, VboxApplyParams, VboxDropParams}; use rpc::{VboxAcceptParams, VboxDiscardParams, VboxCombineParams, VboxApplyParams, VboxDropParams};
use skill::{Skill}; use skill::{Skill};
use spec::{Spec};
use player::{Player, player_get, player_update}; use player::{Player, player_get, player_update};
use cryp::{cryp_get, cryp_write}; use cryp::{cryp_get, cryp_write};
@ -37,8 +38,10 @@ pub enum Var {
Speed, Speed,
Hp, Hp,
HpI, StaminaI,
StamI, RedDamageI,
BlueDamageI,
GreenDamageI,
SpeedI, SpeedI,
Amplify, Amplify,
@ -69,6 +72,11 @@ pub enum Var {
Triage, Triage,
} }
enum VarEffect {
Skill,
Spec,
}
impl Var { impl Var {
fn is_base(&self) -> bool { fn is_base(&self) -> bool {
match self { match self {
@ -81,34 +89,78 @@ impl Var {
} }
} }
fn skill(&self) -> Result<Skill, Error> { fn effect(&self) -> Result<VarEffect, Error> {
match self { match self {
Var::Amplify => Ok(Skill::Amplify), Var::Amplify |
Var::Banish => Ok(Skill::Banish), Var::Banish |
Var::Blast => Ok(Skill::Blast), Var::Blast |
Var::Curse => Ok(Skill::Curse), Var::Curse |
Var::Empower => Ok(Skill::Empower), Var::Empower |
Var::Haste => Ok(Skill::Haste), Var::Haste |
Var::Heal => Ok(Skill::Heal), Var::Heal |
Var::Hex => Ok(Skill::Hex), Var::Hex |
Var::Parry => Ok(Skill::Parry), Var::Parry |
Var::Purge => Ok(Skill::Purge), Var::Purge |
Var::Purify => Ok(Skill::Purify), Var::Purify |
// Var::Reflect => Ok(Skill::Reflect), // Var::Reflect |
Var::Ruin => Ok(Skill::Ruin), Var::Ruin |
Var::Shield => Ok(Skill::Shield), Var::Shield |
Var::Silence => Ok(Skill::Silence), Var::Silence |
Var::Slay => Ok(Skill::Slay), Var::Slay |
Var::Slow => Ok(Skill::Slow), Var::Slow |
Var::Snare => Ok(Skill::Snare), Var::Snare |
Var::Strangle => Ok(Skill::Strangle), Var::Strangle |
Var::Strike => Ok(Skill::Strike), Var::Strike |
// Var::Clutch => Ok(Skill::Clutch), // Var::Clutch |
// Var::Taunt => Ok(Skill::Taunt), // Var::Taunt |
Var::Throw => Ok(Skill::Throw), Var::Throw |
// Var::Toxic => Ok(Skill::Toxic), // Var::Toxic |
Var::Triage => Ok(Skill::Triage), Var::Triage => Ok(VarEffect::Skill),
_ => Err(err_msg("not a usable var"))
Var::StaminaI |
Var::SpeedI => Ok(VarEffect::Spec),
_ => Err(err_msg("var has no effect on cryps"))
}
}
fn skill(&self) -> Skill {
match self {
Var::Amplify => Skill::Amplify,
Var::Banish => Skill::Banish,
Var::Blast => Skill::Blast,
Var::Curse => Skill::Curse,
Var::Empower => Skill::Empower,
Var::Haste => Skill::Haste,
Var::Heal => Skill::Heal,
Var::Hex => Skill::Hex,
Var::Parry => Skill::Parry,
Var::Purge => Skill::Purge,
Var::Purify => Skill::Purify,
// Var::Reflect => Skill::Reflect,
Var::Ruin => Skill::Ruin,
Var::Shield => Skill::Shield,
Var::Silence => Skill::Silence,
Var::Slay => Skill::Slay,
Var::Slow => Skill::Slow,
Var::Snare => Skill::Snare,
Var::Strangle => Skill::Strangle,
Var::Strike => Skill::Strike,
// Var::Clutch => Skill::Clutch,
// Var::Taunt => Skill::Taunt,
Var::Throw => Skill::Throw,
// Var::Toxic => Skill::Toxic,
Var::Triage => Skill::Triage,
_ => panic!("not a skill var"),
}
}
fn spec(&self) -> Spec {
match *self {
Var::StaminaI => Spec::StaminaI,
Var::RedDamageI => Spec::RedDamageI,
Var::SpeedI => Spec::SpeedI,
_ => panic!("not a spec var"),
} }
} }
} }
@ -139,7 +191,7 @@ impl Vbox {
Var::Attack, Var::Attack,
Var::Attack, Var::Attack,
Var::Attack, Var::Attack,
Var::HpI, Var::StaminaI,
Var::SpeedI, Var::SpeedI,
Var::Damage, Var::Damage,
Var::Red, Var::Red,
@ -312,6 +364,17 @@ impl Vbox {
ColourCode::GB => Var::Silence, ColourCode::GB => Var::Silence,
ColourCode::BR => Var::Hex, ColourCode::BR => Var::Hex,
}, },
// SPECS
Var::Damage => match colour_code {
ColourCode::RR => Var::RedDamageI,
ColourCode::GG => Var::GreenDamageI,
ColourCode::BB => Var::BlueDamageI,
ColourCode::RG => return Err(err_msg("unhandled skill combo")),
ColourCode::GB => return Err(err_msg("unhandled skill combo")),
ColourCode::BR => return Err(err_msg("unhandled skill combo")),
},
_ => panic!("wrong base {:?}", base), _ => panic!("wrong base {:?}", base),
}; };
@ -348,10 +411,10 @@ pub fn vbox_drop(params: VboxDropParams, tx: &mut Transaction, account: &Account
pub fn vbox_apply(params: VboxApplyParams, tx: &mut Transaction, account: &Account) -> Result<Player, Error> { pub fn vbox_apply(params: VboxApplyParams, tx: &mut Transaction, account: &Account) -> Result<Player, Error> {
let mut player = player_get(tx, account.id, params.instance_id)?; let mut player = player_get(tx, account.id, params.instance_id)?;
let var = player.vbox.bound.remove(params.index); let var = player.vbox.bound.remove(params.index);
let skill = var.skill()?;
// mess with cryp then release it match var.effect()? {
{ VarEffect::Skill => {
let skill = var.skill();
let cryp = player.cryp_get(params.cryp_id)?; let cryp = player.cryp_get(params.cryp_id)?;
// done here because i teach them a tonne of skills for tests // done here because i teach them a tonne of skills for tests
let max_skills = 4; let max_skills = 4;
@ -360,6 +423,13 @@ pub fn vbox_apply(params: VboxApplyParams, tx: &mut Transaction, account: &Accou
} }
cryp.learn_mut(skill); cryp.learn_mut(skill);
},
VarEffect::Spec => {
let spec = var.spec();
let cryp = player.cryp_get(params.cryp_id)?;
cryp.spec_add(spec)?;
},
} }
return player_update(tx, player); return player_update(tx, player);