move item into its own mod

This commit is contained in:
ntr 2019-05-20 12:54:10 +10:00
parent 331844f904
commit b35909e231
20 changed files with 469 additions and 731 deletions

View File

@ -1,4 +1,4 @@
# vbox_info -> # item_info ->
combos [strike, [R R Attack]] combos [strike, [R R Attack]]
specs [spec [bonus amount, [r g b]] specs [spec [bonus amount, [r g b]]

View File

@ -4,8 +4,8 @@ export const setAccount = value => ({ type: SET_ACCOUNT, value });
export const SET_CRYPS = 'SET_CRYPS'; export const SET_CRYPS = 'SET_CRYPS';
export const setCryps = value => ({ type: SET_CRYPS, value }); export const setCryps = value => ({ type: SET_CRYPS, value });
export const SET_VBOX_INFO = 'SET_VBOX_INFO'; export const SET_ITEM_INFO = 'SET_ITEM_INFO';
export const setVboxInfo = value => ({ type: SET_VBOX_INFO, value }); export const setItemInfo = value => ({ type: SET_ITEM_INFO, value });
export const SET_SKIP = 'SET_SKIP'; export const SET_SKIP = 'SET_SKIP';
export const setSkip = value => ({ type: SET_SKIP, value }); export const setSkip = value => ({ type: SET_SKIP, value });

View File

@ -15,7 +15,7 @@ function Info(args) {
sendUnequip, sendUnequip,
instance, instance,
player, player,
vboxInfo, itemInfo,
vboxHidden, vboxHidden,
} = args; } = args;
@ -166,7 +166,7 @@ function Info(args) {
if (!player) return false; if (!player) return false;
if (!(combiner.every(u => u === null))) { if (!(combiner.every(u => u === null))) {
const filteredCombos = vboxInfo.combos const filteredCombos = itemInfo.combos
.filter(combo => combiner.every(u => u === null .filter(combo => combiner.every(u => u === null
|| combo.units.includes(player.vbox.bound[u]))); || combo.units.includes(player.vbox.bound[u])));
if (filteredCombos.length > 6) return false; if (filteredCombos.length > 6) return false;
@ -183,7 +183,7 @@ function Info(args) {
</table> </table>
); );
} }
const vboxCombos = vboxInfo.combos.filter(c => c.units.includes(info[1])); const vboxCombos = itemInfo.combos.filter(c => c.units.includes(info[1]));
if (vboxCombos.length > 6) return false; if (vboxCombos.length > 6) return false;
return ( return (
<table> <table>

View File

@ -11,7 +11,7 @@ const addState = connect(
info, info,
ws, ws,
instance, instance,
vboxInfo, itemInfo,
vboxHidden, vboxHidden,
player, player,
} = state; } = state;
@ -27,7 +27,7 @@ const addState = connect(
sendUnequip, sendUnequip,
instance, instance,
player, player,
vboxInfo, itemInfo,
vboxHidden, vboxHidden,
}; };
}, },

View File

@ -8,8 +8,8 @@ const shapes = require('./shapes');
const addState = connect( const addState = connect(
function receiveState(state) { function receiveState(state) {
const { activeCryp, player, vboxInfo } = state; const { activeCryp, player, itemInfo } = state;
return { activeCryp, player, vboxInfo }; return { activeCryp, player, itemInfo };
}, },
function receiveDispatch(dispatch) { function receiveDispatch(dispatch) {
@ -38,7 +38,7 @@ function InfoCryp(args) {
const { const {
activeCryp, activeCryp,
player, player,
vboxInfo, itemInfo,
setVboxHidden, setVboxHidden,
setInfo, setInfo,
@ -52,8 +52,8 @@ function InfoCryp(args) {
if (!cryp) return false; if (!cryp) return false;
function setHighlight(type) { function setHighlight(type) {
if (type === 'skill') return setVboxHighlight(vboxInfo.items.filter(v => v.skill).map(v => v.v)); if (type === 'skill') return setVboxHighlight(itemInfo.items.filter(v => v.skill).map(v => v.v));
if (type === 'spec') return setVboxHighlight(vboxInfo.items.filter(v => v.spec).map(v => v.v)); if (type === 'spec') return setVboxHighlight(itemInfo.items.filter(v => v.spec).map(v => v.v));
return false; return false;
} }

View File

@ -8,7 +8,7 @@ const actions = require('../actions');
const addState = connect( const addState = connect(
function receiveState(state) { function receiveState(state) {
const { ws, instance, player, account, vboxHidden, vboxInfo, activeItem, activeCryp } = state; const { ws, instance, player, account, vboxHidden, itemInfo, activeItem, activeCryp } = state;
function sendInstanceReady() { function sendInstanceReady() {
return ws.sendInstanceReady(instance.id); return ws.sendInstanceReady(instance.id);
@ -18,7 +18,7 @@ const addState = connect(
return ws.sendVboxApply(instance.id, crypId, i); return ws.sendVboxApply(instance.id, crypId, i);
} }
return { instance, player, account, sendInstanceReady, sendVboxApply, vboxHidden, vboxInfo, activeItem, activeCryp }; return { instance, player, account, sendInstanceReady, sendVboxApply, vboxHidden, itemInfo, activeItem, activeCryp };
}, },
function receiveDispatch(dispatch) { function receiveDispatch(dispatch) {
@ -57,12 +57,12 @@ function Cryp(props) {
setInfo, setInfo,
setActiveCryp, setActiveCryp,
setVboxHighlight, setVboxHighlight,
vboxInfo, itemInfo,
} = props; } = props;
function setHighlight(type) { function setHighlight(type) {
if (type === 'skill') return setVboxHighlight(vboxInfo.items.filter(v => v.skill).map(v => v.v)); if (type === 'skill') return setVboxHighlight(itemInfo.items.filter(v => v.skill).map(v => v.v));
if (type === 'spec') return setVboxHighlight(vboxInfo.items.filter(v => v.spec).map(v => v.v)); if (type === 'spec') return setVboxHighlight(itemInfo.items.filter(v => v.spec).map(v => v.v));
return false; return false;
} }
@ -74,8 +74,8 @@ function Cryp(props) {
} }
const { vbox } = player; const { vbox } = player;
const skillList = vboxInfo.items.filter(v => v.skill).map(v => v.v); const skillList = itemInfo.items.filter(v => v.skill).map(v => v.v);
const specList = vboxInfo.items.filter(v => v.spec).map(v => v.v); const specList = itemInfo.items.filter(v => v.spec).map(v => v.v);
const skills = range(0, 3).map(i => { const skills = range(0, 3).map(i => {
const skill = cryp.skills[i]; const skill = cryp.skills[i];
@ -194,7 +194,7 @@ function InstanceCryps(props) {
sendVboxApply, sendVboxApply,
vboxHidden, vboxHidden,
vboxInfo, itemInfo,
setVboxHighlight, setVboxHighlight,
} = props; } = props;
@ -202,7 +202,7 @@ function InstanceCryps(props) {
if (instance.phase === 'Lobby') return false; if (instance.phase === 'Lobby') return false;
const cryps = player.cryps.map((c, i) => Cryp({ const cryps = player.cryps.map((c, i) => Cryp({
activeCryp, activeItem, cryp: c, player, sendVboxApply, setInfo, setActiveCryp, vboxInfo, setVboxHighlight, activeCryp, activeItem, cryp: c, player, sendVboxApply, setInfo, setActiveCryp, itemInfo, setVboxHighlight,
})); }));
const classes = `cryp-list ${vboxHidden ? '' : 'hidden'}`; const classes = `cryp-list ${vboxHidden ? '' : 'hidden'}`;

View File

@ -7,13 +7,13 @@ const { convertItem, SPECS } = require('./../utils');
const addState = connect( const addState = connect(
function receiveState(state) { function receiveState(state) {
const { player, vboxInfo, info, ws, instance } = state; const { player, itemInfo, info, ws, instance } = state;
function sendUnequip(crypId, item) { function sendUnequip(crypId, item) {
return ws.sendVboxUnequip(instance.id, crypId, item); return ws.sendVboxUnequip(instance.id, crypId, item);
} }
return { player, vboxInfo, info, sendUnequip }; return { player, itemInfo, info, sendUnequip };
}, },
function receiveDispatch(dispatch) { function receiveDispatch(dispatch) {
@ -38,7 +38,7 @@ function Equipment(props) {
const { const {
player, player,
info, info,
vboxInfo, itemInfo,
sendUnequip, sendUnequip,
setInfo, setInfo,
setActiveItem, setActiveItem,
@ -70,8 +70,8 @@ function Equipment(props) {
const specClass = infoType === 'spec' ? 'specs highlight' : 'specs'; const specClass = infoType === 'spec' ? 'specs highlight' : 'specs';
// const classes = `right ${skill ? '' : 'action'}`; // const classes = `right ${skill ? '' : 'action'}`;
const skillList = vboxInfo.items.filter(v => v.skill).map(v => v.v); const skillList = itemInfo.items.filter(v => v.skill).map(v => v.v);
const specList = vboxInfo.items.filter(v => v.spec).map(v => v.v); const specList = itemInfo.items.filter(v => v.spec).map(v => v.v);
const skills = range(0, 9).map(i => { const skills = range(0, 9).map(i => {

View File

@ -26,7 +26,7 @@ function Vbox(args) {
vboxHidden, vboxHidden,
vboxHighlight, vboxHighlight,
setVboxHighlight, setVboxHighlight,
vboxInfo, itemInfo,
} = args; } = args;
if (!player) return false; if (!player) return false;
@ -39,10 +39,10 @@ function Vbox(args) {
const combinerValues = newCombiner.map(cv => player.vbox.bound[cv]).filter(cv => cv); const combinerValues = newCombiner.map(cv => player.vbox.bound[cv]).filter(cv => cv);
const filteredCombos = vboxInfo.combos const filteredCombos = itemInfo.combos
.filter(combo => combinerValues.every(u => combo.units.includes(u))); .filter(combo => combinerValues.every(u => combo.units.includes(u)));
const comboValues = vboxInfo.items.filter(v => { const comboValues = itemInfo.items.filter(v => {
if (!filteredCombos.some(c => c.units.includes(v.v))) return false; if (!filteredCombos.some(c => c.units.includes(v.v))) return false;
if (!['Red', 'Green', 'Blue'].includes(v.v) && combinerValues.includes(v.v)) return false; if (!['Red', 'Green', 'Blue'].includes(v.v) && combinerValues.includes(v.v)) return false;
return true; return true;

View File

@ -17,7 +17,7 @@ const addState = connect(
info, info,
vboxHidden, vboxHidden,
vboxHighlight, vboxHighlight,
vboxInfo, itemInfo,
} = state; } = state;
function sendVboxApply(i) { function sendVboxApply(i) {
@ -48,7 +48,7 @@ const addState = connect(
activeItem, activeItem,
activeCryp, activeCryp,
info, info,
vboxInfo, itemInfo,
vboxHidden, vboxHidden,
vboxHighlight, vboxHighlight,
sendVboxAccept, sendVboxAccept,

View File

@ -37,7 +37,7 @@ function registerEvents(store) {
crypAnimations(); crypAnimations();
function setPing(ping) { function setPing(ping) {
store.dispatch(actions.setPing(ping)); store.dispatch(actions.setPing(ping));
} }
function setCryps(cryps) { function setCryps(cryps) {
@ -158,8 +158,8 @@ function registerEvents(store) {
console.log('EVENT ->', 'crypStatusUpdate', { id, skill, target }); console.log('EVENT ->', 'crypStatusUpdate', { id, skill, target });
} }
function setVboxInfo(v) { function setItemInfo(v) {
return store.dispatch(actions.setVboxInfo(v)); return store.dispatch(actions.setItemInfo(v));
} }
// events.on('SET_PLAYER', setInstance); // events.on('SET_PLAYER', setInstance);
@ -220,7 +220,7 @@ function registerEvents(store) {
setZone, setZone,
setPing, setPing,
setScores, setScores,
setVboxInfo, setItemInfo,
}; };
} }

View File

@ -33,6 +33,6 @@ module.exports = {
showLog: createReducer(false, actions.SET_SHOW_LOG), showLog: createReducer(false, actions.SET_SHOW_LOG),
vboxHidden: createReducer(false, actions.SET_VBOX_HIDDEN), vboxHidden: createReducer(false, actions.SET_VBOX_HIDDEN),
vboxHighlight: createReducer([], actions.SET_VBOX_HIGHLIGHT), vboxHighlight: createReducer([], actions.SET_VBOX_HIGHLIGHT),
vboxInfo: createReducer({ combos: [], items: [] }, actions.SET_VBOX_INFO), itemInfo: createReducer({ combos: [], items: [] }, actions.SET_VBOX_INFO),
ws: createReducer(null, actions.SET_WS), ws: createReducer(null, actions.SET_WS),
}; };

View File

@ -114,8 +114,8 @@ function createSocket(events) {
send({ method: 'player_vbox_reclaim', params: { instance_id: instanceId, index } }); send({ method: 'player_vbox_reclaim', params: { instance_id: instanceId, index } });
} }
function sendVboxInfo() { function sendItemInfo() {
send({ method: 'vbox_info', params: {} }); send({ method: 'item_info', params: {} });
} }
function sendGameSkill(gameId, crypId, targetCrypId, skill) { function sendGameSkill(gameId, crypId, targetCrypId, skill) {
@ -177,7 +177,7 @@ function createSocket(events) {
function accountInstanceList(res) { function accountInstanceList(res) {
const [struct, playerList] = res; const [struct, playerList] = res;
sendVboxInfo(); sendItemInfo();
events.setInstanceList(playerList); events.setInstanceList(playerList);
} }
@ -228,9 +228,9 @@ function createSocket(events) {
clearTimeout(instanceStateTimeout); clearTimeout(instanceStateTimeout);
} }
function vboxInfo(response) { function itemInfo(response) {
const [structName, info] = response; const [structName, info] = response;
events.setVboxInfo(info); events.setItemInfo(info);
} }
function pong() { function pong() {
@ -255,7 +255,7 @@ function createSocket(events) {
zone_state: zoneState, zone_state: zoneState,
zone_close: res => console.log(res), zone_close: res => console.log(res),
instance_state: instanceState, instance_state: instanceState,
vbox_info: vboxInfo, item_info: itemInfo,
pong, pong,
}; };
@ -367,7 +367,7 @@ function createSocket(events) {
sendVboxCombine, sendVboxCombine,
sendVboxDiscard, sendVboxDiscard,
sendVboxUnequip, sendVboxUnequip,
sendVboxInfo, sendItemInfo,
startInstanceStateTimeout, startInstanceStateTimeout,
startGameStateTimeout, startGameStateTimeout,
connect, connect,

View File

@ -11,7 +11,7 @@ use account::{Account};
use rpc::{CrypSpawnParams}; use rpc::{CrypSpawnParams};
use skill::{Skill, Cooldown, Effect, Cast, Category, Immunity, Disable, Event}; use skill::{Skill, Cooldown, Effect, Cast, Category, Immunity, Disable, Event};
use spec::{Spec}; use spec::{Spec};
use vbox::Item; use item::{Item};
#[derive(Debug,Clone,Serialize,Deserialize)] #[derive(Debug,Clone,Serialize,Deserialize)]
pub struct Colours { pub struct Colours {

View File

@ -18,8 +18,8 @@ use account::Account;
use player::{Player, player_create, player_get, player_global_update}; use player::{Player, player_create, player_get, player_global_update};
use cryp::{Cryp, cryp_get}; use cryp::{Cryp, cryp_get};
use mob::{instance_mobs}; use mob::{instance_mobs};
use game::{Game, Phase, game_get, game_write, game_instance_new}; use game::{Game, Phase, game_get, game_write};
use vbox::{Item}; use item::{Item};
use rpc::{RpcResult}; use rpc::{RpcResult};
use names::{name}; use names::{name};

View File

@ -1,266 +1,446 @@
use serde_cbor::{from_slice, to_vec}; use skill::{Skill};
use uuid::Uuid; use spec::{Spec};
use cryp::{Colours};
use postgres::transaction::Transaction; #[derive(Debug,Copy,Clone,Serialize,Deserialize,PartialEq,PartialOrd,Ord,Eq)]
use failure::Error; pub enum Item {
// colours
Blue,
Green,
Red,
// drops // base skills
use rand::prelude::*; Attack,
use rand::{thread_rng}; Block,
use rand::distributions::{LogNormal,WeightedIndex}; Stun,
Buff,
Debuff,
use account::Account; // specs
use rpc::{ItemUseParams}; // Base
use cryp::{Stat, cryp_get, cryp_write}; Damage,
use game::{GameMode}; Life,
use spec::{Spec, SpecType}; Speed,
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] // Lifes Upgrades
pub enum ItemAction { GreenLifeI,
RerollRedDamage, RedLifeI,
RerollBlueDamage, BlueLifeI,
RerollSpeed, GRLI,
RerollGreenLife, GBLI,
RerollRedLife, RBLI,
RerollBlueLife,
RerollEvasion,
SpecRedDamage5, // Damage Upgrades
SpecBlueDamage5, RedDamageI,
SpecRedLife5, BlueDamageI,
SpecBlueLife5, GreenDamageI,
SpecBlueEvasion5, GRDI,
GBDI,
RBDI,
// Speed Upgrades
RedSpeedI,
BlueSpeedI,
GreenSpeedI,
GRSpeedI,
GBSpeedI,
RBSpeedI,
Amplify,
Banish,
Blast,
Chaos,
Clutch,
Corrupt,
Curse,
Decay,
Hostility,
Haste,
Heal,
Hex,
Impurity,
Invert,
Parry,
Purge,
Purify,
Reflect,
Recharge,
Ruin,
Scatter,
Silence,
Slay,
Sleep,
Snare,
Strangle,
Strike,
StrikeII,
StrikeIII,
Siphon,
Taunt,
Throw,
Triage,
TestTouch,
TestStun,
TestBlock,
TestParry,
TestSiphon,
} }
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] pub enum ItemEffect {
pub struct Item { Skill,
// mods: Vec<Mod>, Spec,
id: Uuid,
account: Uuid,
action: ItemAction,
} }
impl Item { impl Item {
pub fn new(action: ItemAction, account_id: Uuid) -> Item { pub fn colours(&self, count: &mut Colours) {
let id = Uuid::new_v4(); let combos = get_combos();
return Item { let combo = combos.iter().find(|c| c.item == *self);
id, match combo {
account: account_id, Some(c) => c.units.iter().for_each(|unit| match unit {
action, Item::Red => count.red += 1,
}; Item::Blue => count.blue += 1,
Item::Green => count.green += 1,
_ => {
let mut combo_count = Colours::new();
unit.colours(&mut combo_count);
count.red += combo_count.red;
count.blue += combo_count.blue;
count.green += combo_count.green;
}
}),
None => (),
}
} }
fn apply(&mut self, tx: &mut Transaction, target: Uuid) -> Result<(), Error> { pub fn cost(&self) -> u16 {
match self.action { match self {
ItemAction::RerollGreenLife => reroll(self, tx, target, Stat::GreenLife), Item::Red => 1,
ItemAction::RerollRedDamage => reroll(self, tx, target, Stat::RedDamage), Item::Green => 1,
ItemAction::RerollBlueDamage => reroll(self, tx, target, Stat::BlueDamage), Item::Blue => 1,
ItemAction::RerollSpeed => reroll(self, tx, target, Stat::Speed),
ItemAction::RerollRedLife => reroll(self, tx, target, Stat::RedLife),
ItemAction::RerollBlueLife => reroll(self, tx, target, Stat::BlueLife),
ItemAction::RerollEvasion => reroll(self, tx, target, Stat::Evasion),
ItemAction::SpecRedDamage5 => spec_add(self, tx, target, SpecType::RedDamage5), Item::Attack => 2,
ItemAction::SpecBlueDamage5 => spec_add(self, tx, target, SpecType::BlueDamage5), Item::Block => 2,
_ => unimplemented!(), Item::Buff => 2,
Item::Debuff => 2,
Item::Stun => 2,
Item::Damage => 3,
Item::Life => 3,
Item::Speed => 3,
_ => {
let combos = get_combos();
let combo = combos.iter().find(|c| c.item == *self)
.unwrap_or_else(|| panic!("unable to find components for {:?}", self));
return combo.units.iter().fold(0, |acc, c| acc + c.cost());
},
}
}
pub fn speed(&self) -> u8 {
match self {
Item::Red => 3,
Item::Green => 2,
Item::Blue => 1,
Item::Attack => 1,
Item::Stun => 2,
Item::Block => 3,
Item::Buff => 4,
Item::Debuff => 4,
_ => {
let combos = get_combos();
let combo = combos.iter().find(|c| c.item == *self)
.unwrap_or_else(|| panic!("unable to find components for {:?}", self));
return combo.units.iter().fold(0, |acc, c| acc + c.speed());
},
}
}
pub fn effect(&self) -> Option<ItemEffect> {
if let Some(_skill) = self.into_skill() {
return Some(ItemEffect::Skill);
}
if let Some(_spec) = self.into_spec() {
return Some(ItemEffect::Spec);
}
return None;
}
pub fn into_skill(&self) -> Option<Skill> {
match self {
Item::Attack => Some(Skill::Attack),
Item::Amplify => Some(Skill::Amplify),
Item::Banish => Some(Skill::Banish),
Item::Blast => Some(Skill::Blast),
Item::Block => Some(Skill::Block),
Item::Chaos => Some(Skill::Chaos),
Item::Curse => Some(Skill::Curse),
Item::Debuff => Some(Skill::Debuff),
Item::Decay => Some(Skill::Decay),
Item::Haste => Some(Skill::Haste),
Item::Heal => Some(Skill::Heal),
Item::Hex => Some(Skill::Hex),
Item::Hostility => Some(Skill::Hostility),
Item::Impurity => Some(Skill::Impurity),
Item::Invert => Some(Skill::Invert),
Item::Parry => Some(Skill::Parry),
Item::Purge => Some(Skill::Purge),
Item::Purify => Some(Skill::Purify),
Item::Recharge => Some(Skill::Recharge),
Item::Reflect => Some(Skill::Reflect),
Item::Ruin => Some(Skill::Ruin),
Item::Scatter => Some(Skill::Scatter),
Item::Silence => Some(Skill::Silence),
Item::Slay => Some(Skill::Slay),
Item::Sleep => Some(Skill::Sleep),
Item::Siphon => Some(Skill::Siphon),
Item::Snare => Some(Skill::Snare),
Item::Strangle => Some(Skill::Strangle),
Item::Stun => Some(Skill::Stun),
Item::Strike => Some(Skill::Strike),
Item::StrikeII => Some(Skill::StrikeII),
Item::StrikeIII => Some(Skill::StrikeIII),
Item::Clutch => Some(Skill::Clutch),
Item::Taunt => Some(Skill::Taunt),
Item::Throw => Some(Skill::Throw),
Item::Corrupt => Some(Skill::Corrupt),
Item::Triage => Some(Skill::Triage),
_ => None,
}
}
pub fn into_spec(&self) -> Option<Spec> {
match *self {
Item::Speed => Some(Spec::Speed),
Item::RedSpeedI => Some(Spec::RedSpeedI),
Item::BlueSpeedI => Some(Spec::BlueSpeedI),
Item::GreenSpeedI => Some(Spec::GreenSpeedI),
Item::GRSpeedI => Some(Spec::GRSpeedI),
Item::GBSpeedI => Some(Spec::GBSpeedI),
Item::RBSpeedI => Some(Spec::RBSpeedI),
Item::Damage => Some(Spec::Damage),
Item::RedDamageI => Some(Spec::RedDamageI),
Item::BlueDamageI => Some(Spec::BlueDamageI),
Item::GreenDamageI => Some(Spec::GreenDamageI),
Item::GRDI => Some(Spec::GRDI),
Item::GBDI => Some(Spec::GBDI),
Item::RBDI => Some(Spec::RBDI),
Item::Life => Some(Spec::Life),
Item::GRLI => Some(Spec::GRLI),
Item::GBLI => Some(Spec::GBLI),
Item::RBLI => Some(Spec::RBLI),
Item::GreenLifeI => Some(Spec::GreenLifeI),
Item::RedLifeI => Some(Spec::RedLifeI),
Item::BlueLifeI => Some(Spec::BlueLifeI),
_ => None,
} }
} }
} }
fn spec_add(item: &mut Item, tx: &mut Transaction, target: Uuid, spec_type: SpecType) -> Result<(), Error> { impl From<Skill> for Item {
let mut cryp = cryp_get(tx, target, item.account)?; fn from(skill: Skill) -> Item {
let spec = Spec::new(spec_type); match skill {
cryp.spec_add(spec)?; Skill::Amplify => Item::Amplify,
cryp_write(cryp, tx)?; Skill::Attack => Item::Attack,
return Ok(()); Skill::Banish => Item::Banish,
} Skill::Blast => Item::Blast,
Skill::Block => Item::Block,
Skill::Chaos => Item::Chaos,
Skill::Curse => Item::Curse,
Skill::Clutch => Item::Clutch,
Skill::Decay => Item::Decay,
Skill::Debuff => Item::Debuff,
Skill::Haste => Item::Haste,
Skill::Hostility => Item::Hostility,
Skill::Heal => Item::Heal,
Skill::Hex => Item::Hex,
Skill::Impurity => Item::Impurity,
Skill::Invert => Item::Invert,
Skill::Parry => Item::Parry,
Skill::Purge => Item::Purge,
Skill::Purify => Item::Purify,
Skill::Recharge => Item::Recharge,
Skill::Reflect => Item::Reflect,
Skill::Ruin => Item::Ruin,
Skill::Scatter => Item::Scatter,
Skill::Silence => Item::Silence,
Skill::Siphon => Item::Siphon,
Skill::Slay => Item::Slay,
Skill::Sleep => Item::Sleep,
Skill::Snare => Item::Snare,
Skill::Strangle => Item::Strangle,
Skill::Strike => Item::Strike,
Skill::StrikeII => Item::StrikeII,
Skill::StrikeIII => Item::StrikeIII,
Skill::Stun => Item::Stun,
Skill::Taunt => Item::Taunt,
Skill::Throw => Item::Throw,
Skill::Triage => Item::Triage,
Skill::Corrupt => Item::Corrupt,
fn reroll(item: &mut Item, tx: &mut Transaction, target: Uuid, stat: Stat) -> Result<(), Error> { Skill::TestTouch => Item::TestTouch,
let mut cryp = cryp_get(tx, target, item.account)?; Skill::TestStun => Item::TestStun,
cryp.roll_stat(stat); Skill::TestBlock => Item::TestBlock,
cryp_write(cryp, tx)?; Skill::TestParry => Item::TestParry,
return Ok(()); Skill::TestSiphon => Item::TestSiphon,
} _ => panic!("{:?} not implemented as a item", skill),
}
fn mode_drops(mode: GameMode) -> Vec<(ItemAction, usize)> {
match mode {
GameMode::Normal => vec![
(ItemAction::RerollGreenLife, 1),
(ItemAction::RerollRedDamage, 1),
(ItemAction::RerollBlueDamage, 1),
],
GameMode::Pvp => vec![
(ItemAction::RerollSpeed, 1),
],
GameMode::Zone3v2Attack |
GameMode::Zone2v2Caster |
GameMode::Zone3v3MeleeMiniboss => vec![
(ItemAction::RerollEvasion, 1),
(ItemAction::RerollRedLife, 1),
(ItemAction::RerollBlueLife, 1),
],
GameMode::Zone3v3HealerBoss => vec![
(ItemAction::RerollSpeed, 1),
],
// _ => vec![
// (ItemAction::RerollGreenLife, 1),
// (ItemAction::RerollRedDamage, 1),
// (ItemAction::RerollBlueDamage, 1),
// (ItemAction::RerollSpeed, 1),
// (ItemAction::RerollRedLife, 1),
// (ItemAction::RerollBlueLife, 1),
// (ItemAction::RerollEvasion, 1),
// ],
} }
} }
pub fn item_drop(tx: &mut Transaction, account_id: Uuid, mode: GameMode) -> Result<(), Error> { impl From<Spec> for Item {
let mut rng = thread_rng(); fn from(spec: Spec) -> Item {
match spec {
Spec::Speed => Item::Speed,
Spec::RedSpeedI => Item::RedSpeedI,
Spec::BlueSpeedI => Item::BlueSpeedI,
Spec::GreenSpeedI => Item::GreenSpeedI,
Spec::GRSpeedI => Item::GRSpeedI,
Spec::GBSpeedI => Item::GBSpeedI,
Spec::RBSpeedI => Item::RBSpeedI,
let log_normal = LogNormal::new(1.0, 1.0); Spec::Damage => Item::Damage,
let num_drops = log_normal.sample(&mut rng).floor() as u16; Spec::RedDamageI => Item::RedDamageI,
Spec::BlueDamageI => Item::BlueDamageI,
Spec::GreenDamageI => Item::GreenDamageI,
Spec::GRDI => Item::GRDI,
Spec::GBDI => Item::GBDI,
Spec::RBDI => Item::RBDI,
let actions = mode_drops(mode); Spec::Life => Item::Life,
info!("{:?} drops", num_drops); Spec::GRLI => Item::GRLI,
Spec::GBLI => Item::GBLI,
for _i in 0..num_drops { Spec::RBLI => Item::RBLI,
let dist = WeightedIndex::new(actions.iter().map(|item| item.1)).unwrap(); Spec::GreenLifeI => Item::GreenLifeI,
let kind = actions[dist.sample(&mut rng)].0; Spec::RedLifeI => Item::RedLifeI,
let item = Item::new(kind, account_id); Spec::BlueLifeI => Item::BlueLifeI,
// _ => panic!("{:?} not implemented as a item", spec),
info!("{:?} dropped {:?}", account_id, item); }
item_create(item, tx, account_id)?;
} }
Ok(())
} }
pub fn item_create(item: Item, tx: &mut Transaction, account_id: Uuid) -> Result<Item, Error> { #[derive(Debug,Clone,Serialize,Deserialize)]
let item_bytes = to_vec(&item)?; pub struct Combo {
pub item: Item,
let query = " pub units: Vec<Item>,
INSERT INTO items (id, account, data)
VALUES ($1, $2, $3)
RETURNING id, account, data;
";
let result = tx
.query(query, &[&item.id, &account_id, &item_bytes])?;
result.iter().next().expect("no row returned");
return Ok(item);
} }
pub fn item_use(params: ItemUseParams, tx: &mut Transaction, account: &Account) -> Result<(), Error> { pub fn get_combos() -> Vec<Combo> {
let query = " let mut combinations = vec![
SELECT data Combo { units: vec![Item::Buff, Item::Red, Item::Red], item: Item::Taunt },
FROM items Combo { units: vec![Item::Buff, Item::Green, Item::Green], item: Item::Triage },
WHERE id = $1 Combo { units: vec![Item::Buff, Item::Blue, Item::Blue], item: Item::Scatter }, //To be impl
AND account = $2 Combo { units: vec![Item::Buff, Item::Red, Item::Green], item: Item::Haste },
FOR UPDATE; Combo { units: vec![Item::Buff, Item::Green, Item::Blue], item: Item::Impurity },
"; Combo { units: vec![Item::Buff, Item::Red, Item::Blue], item: Item::Amplify }, // Some flavour
let result = tx Combo { units: vec![Item::Debuff, Item::Red, Item::Red], item: Item::Snare },
.query(query, &[&params.item, &account.id])?; Combo { units: vec![Item::Debuff, Item::Green, Item::Green], item: Item::Purge }, // Needs flavour
Combo { units: vec![Item::Debuff, Item::Blue, Item::Blue], item: Item::Silence },
Combo { units: vec![Item::Debuff, Item::Red, Item::Green], item: Item::Curse }, // To be reworked
Combo { units: vec![Item::Debuff, Item::Green, Item::Blue], item: Item::Decay },
Combo { units: vec![Item::Debuff, Item::Red, Item::Blue], item: Item::Invert },
let returned = result.iter().next().expect("no row returned"); Combo { units: vec![Item::Block, Item::Red, Item::Red], item: Item::Parry }, // Add red recharge
Combo { units: vec![Item::Block, Item::Green, Item::Green], item: Item::Purify },
Combo { units: vec![Item::Block, Item::Blue, Item::Blue], item: Item::Corrupt },
Combo { units: vec![Item::Block, Item::Red, Item::Green], item: Item::Clutch },
Combo { units: vec![Item::Block, Item::Green, Item::Blue], item: Item::Reflect },
Combo { units: vec![Item::Block, Item::Red, Item::Blue], item: Item::Recharge },
let item_bytes: Vec<u8> = returned.get(0); Combo { units: vec![Item::Stun, Item::Red, Item::Red], item: Item::Strangle },
let mut item = from_slice::<Item>(&item_bytes)?; Combo { units: vec![Item::Stun, Item::Green, Item::Green], item: Item::Sleep },
Combo { units: vec![Item::Stun, Item::Blue, Item::Blue], item: Item::Ruin },
Combo { units: vec![Item::Stun, Item::Red, Item::Green], item: Item::Throw },
Combo { units: vec![Item::Stun, Item::Green, Item::Blue], item: Item::Hex },
Combo { units: vec![Item::Stun, Item::Red, Item::Blue], item: Item::Banish },
item.apply(tx, params.target)?; Combo { units: vec![Item::Attack, Item::Red, Item::Red], item: Item::Strike },
item_delete(tx, params.item)?; Combo { units: vec![Item::Strike, Item::Strike, Item::Strike], item: Item::StrikeII },
Combo { units: vec![Item::StrikeII, Item::StrikeII, Item::StrikeII], item: Item::StrikeIII },
return Ok(()); Combo { units: vec![Item::Attack, Item::Green, Item::Green], item: Item::Heal },
Combo { units: vec![Item::Attack, Item::Blue, Item::Blue], item: Item::Blast },
Combo { units: vec![Item::Attack, Item::Red, Item::Green], item: Item::Slay },
Combo { units: vec![Item::Attack, Item::Green, Item::Blue], item: Item::Siphon },
Combo { units: vec![Item::Attack, Item::Red, Item::Blue], item: Item::Chaos },
Combo { units: vec![Item::Damage, Item::Red, Item::Red], item: Item::RedDamageI },
Combo { units: vec![Item::Damage, Item::Green, Item::Green], item: Item::GreenDamageI },
Combo { units: vec![Item::Damage, Item::Blue, Item::Blue], item: Item::BlueDamageI },
Combo { units: vec![Item::Damage, Item::Red, Item::Green], item: Item::GRDI },
Combo { units: vec![Item::Damage, Item::Green, Item::Blue], item: Item::GBDI },
Combo { units: vec![Item::Damage, Item::Red, Item::Blue], item: Item::RBDI },
Combo { units: vec![Item::Life, Item::Red, Item::Red], item: Item::RedLifeI },
Combo { units: vec![Item::Life, Item::Green, Item::Green], item: Item::GreenLifeI },
Combo { units: vec![Item::Life, Item::Blue, Item::Blue], item: Item::BlueLifeI },
Combo { units: vec![Item::Life, Item::Red, Item::Green], item: Item::GRLI },
Combo { units: vec![Item::Life, Item::Green, Item::Blue], item: Item::GBLI },
Combo { units: vec![Item::Life, Item::Red, Item::Blue], item: Item::RBLI },
Combo { units: vec![Item::Speed, Item::Red, Item::Red], item: Item::RedSpeedI },
Combo { units: vec![Item::Speed, Item::Green, Item::Green], item: Item::GreenSpeedI },
Combo { units: vec![Item::Speed, Item::Blue, Item::Blue], item: Item::BlueSpeedI },
Combo { units: vec![Item::Speed, Item::Red, Item::Green], item: Item::GRSpeedI },
Combo { units: vec![Item::Speed, Item::Green, Item::Blue], item: Item::GBSpeedI },
Combo { units: vec![Item::Speed, Item::Red, Item::Blue], item: Item::RBSpeedI },
];
combinations.iter_mut().for_each(|set| set.units.sort_unstable());
return combinations;
} }
pub fn item_delete(tx: &mut Transaction, id: Uuid) -> Result<(), Error> { #[derive(Debug,Clone,Serialize,Deserialize)]
let query = " pub struct ItemInfo {
DELETE pub v: Item,
FROM items pub spec: bool,
WHERE id = $1; pub skill: bool,
";
let result = tx
.execute(query, &[&id])?;
if result != 1 {
return Err(format_err!("unable to delete item {:?}", id));
}
// info!("item deleted {:?}", id);
return Ok(());
} }
pub fn items_list(tx: &mut Transaction, account: &Account) -> Result<Vec<Item>, Error> {
let query = "
SELECT data, id
FROM items
WHERE account = $1;
";
let result = tx #[derive(Debug,Clone,Serialize,Deserialize)]
.query(query, &[&account.id])?; pub struct ItemInfoCtr {
pub combos: Vec<Combo>,
let mut items = vec![]; pub items: Vec<ItemInfo>,
for row in result.into_iter() {
let item_bytes: Vec<u8> = row.get(0);
let id = row.get(1);
match from_slice::<Item>(&item_bytes) {
Ok(i) => items.push(i),
Err(_e) => {
item_delete(tx, id)?;
}
};
}
return Ok(items);
} }
// # max damage potion pub fn item_info() -> ItemInfoCtr {
// name let combos = get_combos();
let mut items = combos
.into_iter()
.flat_map(|mut c| {
c.units.push(c.item);
c.units
})
.collect::<Vec<Item>>();
// "MapMonstersCurseEffectOnSelfFinal3": { items.sort_unstable();
// "adds_tags": [], items.dedup();
// "domain": "area",
// "generation_type": "prefix", let items = items
// "generation_weights": [], .into_iter()
// "grants_buff": {}, .map(|v| ItemInfo {
// "grants_effect": {}, v,
// "group": "MapHexproof", spec: v.into_spec().is_some(),
// "is_essence_only": false, skill: v.into_skill().is_some(),
// "name": "Hexwarded", })
// "required_level": 1, .collect::<Vec<ItemInfo>>();
// "spawn_weights": [
// { let combos = get_combos();
// "tag": "top_tier_map",
// "weight": 0 return ItemInfoCtr {
// }, combos,
// { items,
// "tag": "default", };
// "weight": 0 }
// }
// ],
// "stats": [
// {
// "id": "map_item_drop_quantity_+%",
// "max": 15,
// "min": 15
// },
// {
// "id": "map_item_drop_rarity_+%",
// "max": 8,
// "min": 8
// },
// {
// "id": "map_monsters_curse_effect_on_self_+%_final",
// "max": -60,
// "min": -60
// }
// ]
// },

View File

@ -17,17 +17,18 @@ extern crate serde_cbor;
extern crate fern; extern crate fern;
#[macro_use] extern crate log; #[macro_use] extern crate log;
mod account;
mod cryp; mod cryp;
mod game; mod game;
mod instance;
mod item;
mod mob;
mod names;
mod net; mod net;
mod player;
mod rpc;
mod skill; mod skill;
mod spec; mod spec;
mod names;
mod rpc;
mod account;
mod instance;
mod player;
mod mob;
mod util; mod util;
mod vbox; mod vbox;
mod warden; mod warden;

View File

@ -10,9 +10,10 @@ use failure::err_msg;
use account::Account; use account::Account;
use cryp::{Cryp, Colours, cryp_get}; use cryp::{Cryp, Colours, cryp_get};
use vbox::{Vbox, Item, ItemEffect}; use vbox::{Vbox};
use item::{Item, ItemEffect};
use rpc::{PlayerCrypsSetParams}; use rpc::{PlayerCrypsSetParams};
use instance::{Instance, instance_get, instance_update}; use instance::{Instance};
use skill::{Effect}; use skill::{Effect};
const DISCARD_COST: u16 = 5; const DISCARD_COST: u16 = 5;

View File

@ -19,11 +19,11 @@ use cryp::{Cryp, cryp_spawn};
use game::{Game, game_state, game_skill, game_ready}; use game::{Game, game_state, game_skill, game_ready};
use account::{Account, account_create, account_login, account_from_token, account_cryps, account_instances}; use account::{Account, account_create, account_login, account_from_token, account_cryps, account_instances};
use skill::{Skill}; use skill::{Skill};
// use zone::{Zone, zone_create, zone_join, zone_close};
use spec::{Spec}; use spec::{Spec};
use player::{Score, player_mm_cryps_set}; use player::{Score, player_mm_cryps_set};
use instance::{Instance, instance_state, instance_new, instance_ready, instance_join}; use instance::{Instance, instance_state, instance_new, instance_ready, instance_join};
use vbox::{Item, VboxInfo, vbox_accept, vbox_apply, vbox_discard, vbox_combine, vbox_reclaim, vbox_unequip, vbox_info}; use vbox::{vbox_accept, vbox_apply, vbox_discard, vbox_combine, vbox_reclaim, vbox_unequip};
use item::{Item, ItemInfoCtr, item_info};
pub struct Rpc; pub struct Rpc;
@ -97,7 +97,7 @@ impl Rpc {
"player_vbox_reclaim" => Rpc::player_vbox_reclaim(data, &mut tx, account.unwrap(), client), "player_vbox_reclaim" => Rpc::player_vbox_reclaim(data, &mut tx, account.unwrap(), client),
"player_vbox_unequip" => Rpc::player_vbox_unequip(data, &mut tx, account.unwrap(), client), "player_vbox_unequip" => Rpc::player_vbox_unequip(data, &mut tx, account.unwrap(), client),
"vbox_info" => Ok(RpcResponse { method: "vbox_info".to_string(), params: RpcResult::VboxInfo(vbox_info()) }), "item_info" => Ok(RpcResponse { method: "item_info".to_string(), params: RpcResult::ItemInfo(item_info()) }),
_ => Err(format_err!("unknown method - {:?}", v.method)), _ => Err(format_err!("unknown method - {:?}", v.method)),
}; };
@ -405,7 +405,7 @@ pub enum RpcResult {
Account(Account), Account(Account),
CrypList(Vec<Cryp>), CrypList(Vec<Cryp>),
GameState(Game), GameState(Game),
VboxInfo(VboxInfo), ItemInfo(ItemInfoCtr),
InstanceScores(Vec<(String, Score)>), InstanceScores(Vec<(String, Score)>),
// ZoneState(Zone), // ZoneState(Zone),
// ZoneClose(()), // ZoneClose(()),

View File

@ -3,7 +3,7 @@ use uuid::Uuid;
use util::{IntPct}; use util::{IntPct};
use cryp::{Cryp, CrypEffect, EffectMeta, Stat}; use cryp::{Cryp, CrypEffect, EffectMeta, Stat};
use vbox::{Item}; use item::{Item};
use game::{Game}; use game::{Game};

View File

@ -1,5 +1,4 @@
use std::iter; use std::iter;
use uuid::Uuid;
// reclaims // reclaims
use rand::prelude::*; use rand::prelude::*;
@ -13,453 +12,10 @@ use failure::err_msg;
use account::Account; use account::Account;
use rpc::{VboxAcceptParams, VboxDiscardParams, VboxCombineParams, VboxApplyParams, VboxReclaimParams, VboxUnequipParams}; use rpc::{VboxAcceptParams, VboxDiscardParams, VboxCombineParams, VboxApplyParams, VboxReclaimParams, VboxUnequipParams};
use skill::{Skill};
use spec::{Spec};
use instance::{Instance, instance_get, instance_update}; use instance::{Instance, instance_get, instance_update};
use cryp::{Colours}; use cryp::{Colours};
#[derive(Debug,Copy,Clone,Serialize,Deserialize,PartialEq,PartialOrd,Ord,Eq)] use item::*;
pub enum Item {
// colours
Blue,
Green,
Red,
// base skills
Attack,
Block,
Stun,
Buff,
Debuff,
// specs
// Base
Damage,
Life,
Speed,
// Lifes Upgrades
GreenLifeI,
RedLifeI,
BlueLifeI,
GRLI,
GBLI,
RBLI,
// Damage Upgrades
RedDamageI,
BlueDamageI,
GreenDamageI,
GRDI,
GBDI,
RBDI,
// Speed Upgrades
RedSpeedI,
BlueSpeedI,
GreenSpeedI,
GRSpeedI,
GBSpeedI,
RBSpeedI,
Amplify,
Banish,
Blast,
Chaos,
Clutch,
Corrupt,
Curse,
Decay,
Hostility,
Haste,
Heal,
Hex,
Impurity,
Invert,
Parry,
Purge,
Purify,
Reflect,
Recharge,
Ruin,
Scatter,
Silence,
Slay,
Sleep,
Snare,
Strangle,
Strike,
StrikeII,
StrikeIII,
Siphon,
Taunt,
Throw,
Triage,
TestTouch,
TestStun,
TestBlock,
TestParry,
TestSiphon,
}
pub enum ItemEffect {
Skill,
Spec,
}
impl Item {
pub fn colours(&self, count: &mut Colours) {
let combos = get_combos();
let combo = combos.iter().find(|c| c.item == *self);
match combo {
Some(c) => c.units.iter().for_each(|unit| match unit {
Item::Red => count.red += 1,
Item::Blue => count.blue += 1,
Item::Green => count.green += 1,
_ => {
let mut combo_count = Colours::new();
unit.colours(&mut combo_count);
count.red += combo_count.red;
count.blue += combo_count.blue;
count.green += combo_count.green;
}
}),
None => (),
}
}
fn cost(&self) -> u16 {
match self {
Item::Red => 1,
Item::Green => 1,
Item::Blue => 1,
Item::Attack => 2,
Item::Block => 2,
Item::Buff => 2,
Item::Debuff => 2,
Item::Stun => 2,
Item::Damage => 3,
Item::Life => 3,
Item::Speed => 3,
_ => {
let combos = get_combos();
let combo = combos.iter().find(|c| c.item == *self)
.unwrap_or_else(|| panic!("unable to find components for {:?}", self));
return combo.units.iter().fold(0, |acc, c| acc + c.cost());
},
}
}
pub fn speed(&self) -> u8 {
match self {
Item::Red => 3,
Item::Green => 2,
Item::Blue => 1,
Item::Attack => 1,
Item::Stun => 2,
Item::Block => 3,
Item::Buff => 4,
Item::Debuff => 4,
_ => {
let combos = get_combos();
let combo = combos.iter().find(|c| c.item == *self)
.unwrap_or_else(|| panic!("unable to find components for {:?}", self));
return combo.units.iter().fold(0, |acc, c| acc + c.speed());
},
}
}
pub fn effect(&self) -> Option<ItemEffect> {
if let Some(_skill) = self.into_skill() {
return Some(ItemEffect::Skill);
}
if let Some(_spec) = self.into_spec() {
return Some(ItemEffect::Spec);
}
return None;
}
pub fn into_skill(&self) -> Option<Skill> {
match self {
Item::Attack => Some(Skill::Attack),
Item::Amplify => Some(Skill::Amplify),
Item::Banish => Some(Skill::Banish),
Item::Blast => Some(Skill::Blast),
Item::Block => Some(Skill::Block),
Item::Chaos => Some(Skill::Chaos),
Item::Curse => Some(Skill::Curse),
Item::Debuff => Some(Skill::Debuff),
Item::Decay => Some(Skill::Decay),
Item::Haste => Some(Skill::Haste),
Item::Heal => Some(Skill::Heal),
Item::Hex => Some(Skill::Hex),
Item::Hostility => Some(Skill::Hostility),
Item::Impurity => Some(Skill::Impurity),
Item::Invert => Some(Skill::Invert),
Item::Parry => Some(Skill::Parry),
Item::Purge => Some(Skill::Purge),
Item::Purify => Some(Skill::Purify),
Item::Recharge => Some(Skill::Recharge),
Item::Reflect => Some(Skill::Reflect),
Item::Ruin => Some(Skill::Ruin),
Item::Scatter => Some(Skill::Scatter),
Item::Silence => Some(Skill::Silence),
Item::Slay => Some(Skill::Slay),
Item::Sleep => Some(Skill::Sleep),
Item::Siphon => Some(Skill::Siphon),
Item::Snare => Some(Skill::Snare),
Item::Strangle => Some(Skill::Strangle),
Item::Stun => Some(Skill::Stun),
Item::Strike => Some(Skill::Strike),
Item::StrikeII => Some(Skill::StrikeII),
Item::StrikeIII => Some(Skill::StrikeIII),
Item::Clutch => Some(Skill::Clutch),
Item::Taunt => Some(Skill::Taunt),
Item::Throw => Some(Skill::Throw),
Item::Corrupt => Some(Skill::Corrupt),
Item::Triage => Some(Skill::Triage),
_ => None,
}
}
pub fn into_spec(&self) -> Option<Spec> {
match *self {
Item::Speed => Some(Spec::Speed),
Item::RedSpeedI => Some(Spec::RedSpeedI),
Item::BlueSpeedI => Some(Spec::BlueSpeedI),
Item::GreenSpeedI => Some(Spec::GreenSpeedI),
Item::GRSpeedI => Some(Spec::GRSpeedI),
Item::GBSpeedI => Some(Spec::GBSpeedI),
Item::RBSpeedI => Some(Spec::RBSpeedI),
Item::Damage => Some(Spec::Damage),
Item::RedDamageI => Some(Spec::RedDamageI),
Item::BlueDamageI => Some(Spec::BlueDamageI),
Item::GreenDamageI => Some(Spec::GreenDamageI),
Item::GRDI => Some(Spec::GRDI),
Item::GBDI => Some(Spec::GBDI),
Item::RBDI => Some(Spec::RBDI),
Item::Life => Some(Spec::Life),
Item::GRLI => Some(Spec::GRLI),
Item::GBLI => Some(Spec::GBLI),
Item::RBLI => Some(Spec::RBLI),
Item::GreenLifeI => Some(Spec::GreenLifeI),
Item::RedLifeI => Some(Spec::RedLifeI),
Item::BlueLifeI => Some(Spec::BlueLifeI),
_ => None,
}
}
}
impl From<Skill> for Item {
fn from(skill: Skill) -> Item {
match skill {
Skill::Amplify => Item::Amplify,
Skill::Attack => Item::Attack,
Skill::Banish => Item::Banish,
Skill::Blast => Item::Blast,
Skill::Block => Item::Block,
Skill::Chaos => Item::Chaos,
Skill::Curse => Item::Curse,
Skill::Clutch => Item::Clutch,
Skill::Decay => Item::Decay,
Skill::Debuff => Item::Debuff,
Skill::Haste => Item::Haste,
Skill::Hostility => Item::Hostility,
Skill::Heal => Item::Heal,
Skill::Hex => Item::Hex,
Skill::Impurity => Item::Impurity,
Skill::Invert => Item::Invert,
Skill::Parry => Item::Parry,
Skill::Purge => Item::Purge,
Skill::Purify => Item::Purify,
Skill::Recharge => Item::Recharge,
Skill::Reflect => Item::Reflect,
Skill::Ruin => Item::Ruin,
Skill::Scatter => Item::Scatter,
Skill::Silence => Item::Silence,
Skill::Siphon => Item::Siphon,
Skill::Slay => Item::Slay,
Skill::Sleep => Item::Sleep,
Skill::Snare => Item::Snare,
Skill::Strangle => Item::Strangle,
Skill::Strike => Item::Strike,
Skill::StrikeII => Item::StrikeII,
Skill::StrikeIII => Item::StrikeIII,
Skill::Stun => Item::Stun,
Skill::Taunt => Item::Taunt,
Skill::Throw => Item::Throw,
Skill::Triage => Item::Triage,
Skill::Corrupt => Item::Corrupt,
Skill::TestTouch => Item::TestTouch,
Skill::TestStun => Item::TestStun,
Skill::TestBlock => Item::TestBlock,
Skill::TestParry => Item::TestParry,
Skill::TestSiphon => Item::TestSiphon,
_ => panic!("{:?} not implemented as a item", skill),
}
}
}
impl From<Spec> for Item {
fn from(spec: Spec) -> Item {
match spec {
Spec::Speed => Item::Speed,
Spec::RedSpeedI => Item::RedSpeedI,
Spec::BlueSpeedI => Item::BlueSpeedI,
Spec::GreenSpeedI => Item::GreenSpeedI,
Spec::GRSpeedI => Item::GRSpeedI,
Spec::GBSpeedI => Item::GBSpeedI,
Spec::RBSpeedI => Item::RBSpeedI,
Spec::Damage => Item::Damage,
Spec::RedDamageI => Item::RedDamageI,
Spec::BlueDamageI => Item::BlueDamageI,
Spec::GreenDamageI => Item::GreenDamageI,
Spec::GRDI => Item::GRDI,
Spec::GBDI => Item::GBDI,
Spec::RBDI => Item::RBDI,
Spec::Life => Item::Life,
Spec::GRLI => Item::GRLI,
Spec::GBLI => Item::GBLI,
Spec::RBLI => Item::RBLI,
Spec::GreenLifeI => Item::GreenLifeI,
Spec::RedLifeI => Item::RedLifeI,
Spec::BlueLifeI => Item::BlueLifeI,
// _ => panic!("{:?} not implemented as a item", spec),
}
}
}
#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct Combo {
item: Item,
units: Vec<Item>,
}
fn get_combos() -> Vec<Combo> {
let mut combinations = vec![
Combo { units: vec![Item::Buff, Item::Red, Item::Red], item: Item::Taunt },
Combo { units: vec![Item::Buff, Item::Green, Item::Green], item: Item::Triage },
Combo { units: vec![Item::Buff, Item::Blue, Item::Blue], item: Item::Scatter }, //To be impl
Combo { units: vec![Item::Buff, Item::Red, Item::Green], item: Item::Haste },
Combo { units: vec![Item::Buff, Item::Green, Item::Blue], item: Item::Impurity },
Combo { units: vec![Item::Buff, Item::Red, Item::Blue], item: Item::Amplify }, // Some flavour
Combo { units: vec![Item::Debuff, Item::Red, Item::Red], item: Item::Snare },
Combo { units: vec![Item::Debuff, Item::Green, Item::Green], item: Item::Purge }, // Needs flavour
Combo { units: vec![Item::Debuff, Item::Blue, Item::Blue], item: Item::Silence },
Combo { units: vec![Item::Debuff, Item::Red, Item::Green], item: Item::Curse }, // To be reworked
Combo { units: vec![Item::Debuff, Item::Green, Item::Blue], item: Item::Decay },
Combo { units: vec![Item::Debuff, Item::Red, Item::Blue], item: Item::Invert },
Combo { units: vec![Item::Block, Item::Red, Item::Red], item: Item::Parry }, // Add red recharge
Combo { units: vec![Item::Block, Item::Green, Item::Green], item: Item::Purify },
Combo { units: vec![Item::Block, Item::Blue, Item::Blue], item: Item::Corrupt },
Combo { units: vec![Item::Block, Item::Red, Item::Green], item: Item::Clutch },
Combo { units: vec![Item::Block, Item::Green, Item::Blue], item: Item::Reflect },
Combo { units: vec![Item::Block, Item::Red, Item::Blue], item: Item::Recharge },
Combo { units: vec![Item::Stun, Item::Red, Item::Red], item: Item::Strangle },
Combo { units: vec![Item::Stun, Item::Green, Item::Green], item: Item::Sleep },
Combo { units: vec![Item::Stun, Item::Blue, Item::Blue], item: Item::Ruin },
Combo { units: vec![Item::Stun, Item::Red, Item::Green], item: Item::Throw },
Combo { units: vec![Item::Stun, Item::Green, Item::Blue], item: Item::Hex },
Combo { units: vec![Item::Stun, Item::Red, Item::Blue], item: Item::Banish },
Combo { units: vec![Item::Attack, Item::Red, Item::Red], item: Item::Strike },
Combo { units: vec![Item::Strike, Item::Strike, Item::Strike], item: Item::StrikeII },
Combo { units: vec![Item::StrikeII, Item::StrikeII, Item::StrikeII], item: Item::StrikeIII },
Combo { units: vec![Item::Attack, Item::Green, Item::Green], item: Item::Heal },
Combo { units: vec![Item::Attack, Item::Blue, Item::Blue], item: Item::Blast },
Combo { units: vec![Item::Attack, Item::Red, Item::Green], item: Item::Slay },
Combo { units: vec![Item::Attack, Item::Green, Item::Blue], item: Item::Siphon },
Combo { units: vec![Item::Attack, Item::Red, Item::Blue], item: Item::Chaos },
Combo { units: vec![Item::Damage, Item::Red, Item::Red], item: Item::RedDamageI },
Combo { units: vec![Item::Damage, Item::Green, Item::Green], item: Item::GreenDamageI },
Combo { units: vec![Item::Damage, Item::Blue, Item::Blue], item: Item::BlueDamageI },
Combo { units: vec![Item::Damage, Item::Red, Item::Green], item: Item::GRDI },
Combo { units: vec![Item::Damage, Item::Green, Item::Blue], item: Item::GBDI },
Combo { units: vec![Item::Damage, Item::Red, Item::Blue], item: Item::RBDI },
Combo { units: vec![Item::Life, Item::Red, Item::Red], item: Item::RedLifeI },
Combo { units: vec![Item::Life, Item::Green, Item::Green], item: Item::GreenLifeI },
Combo { units: vec![Item::Life, Item::Blue, Item::Blue], item: Item::BlueLifeI },
Combo { units: vec![Item::Life, Item::Red, Item::Green], item: Item::GRLI },
Combo { units: vec![Item::Life, Item::Green, Item::Blue], item: Item::GBLI },
Combo { units: vec![Item::Life, Item::Red, Item::Blue], item: Item::RBLI },
Combo { units: vec![Item::Speed, Item::Red, Item::Red], item: Item::RedSpeedI },
Combo { units: vec![Item::Speed, Item::Green, Item::Green], item: Item::GreenSpeedI },
Combo { units: vec![Item::Speed, Item::Blue, Item::Blue], item: Item::BlueSpeedI },
Combo { units: vec![Item::Speed, Item::Red, Item::Green], item: Item::GRSpeedI },
Combo { units: vec![Item::Speed, Item::Green, Item::Blue], item: Item::GBSpeedI },
Combo { units: vec![Item::Speed, Item::Red, Item::Blue], item: Item::RBSpeedI },
];
combinations.iter_mut().for_each(|set| set.units.sort_unstable());
return combinations;
}
#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct ItemInfo {
pub v: Item,
pub spec: bool,
pub skill: bool,
}
#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct VboxInfo {
pub combos: Vec<Combo>,
pub items: Vec<ItemInfo>,
}
pub fn vbox_info() -> VboxInfo {
let combos = get_combos();
let mut items = combos
.into_iter()
.flat_map(|mut c| {
c.units.push(c.item);
c.units
})
.collect::<Vec<Item>>();
items.sort_unstable();
items.dedup();
let items = items
.into_iter()
.map(|v| ItemInfo {
v,
spec: v.into_spec().is_some(),
skill: v.into_skill().is_some(),
})
.collect::<Vec<ItemInfo>>();
let combos = get_combos();
return VboxInfo {
combos,
items,
};
}
#[derive(Debug,Clone,Serialize,Deserialize)] #[derive(Debug,Clone,Serialize,Deserialize)]
pub struct Vbox { pub struct Vbox {
@ -677,7 +233,7 @@ mod tests {
} }
// #[test] // #[test]
// fn vbox_info_test() { // fn item_info_test() {
// info!("{:#?}", vbox_info()); // info!("{:#?}", item_info());
// } // }
} }