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]]
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 setCryps = value => ({ type: SET_CRYPS, value });
export const SET_VBOX_INFO = 'SET_VBOX_INFO';
export const setVboxInfo = value => ({ type: SET_VBOX_INFO, value });
export const SET_ITEM_INFO = 'SET_ITEM_INFO';
export const setItemInfo = value => ({ type: SET_ITEM_INFO, value });
export const SET_SKIP = 'SET_SKIP';
export const setSkip = value => ({ type: SET_SKIP, value });

View File

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

View File

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

View File

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

View File

@ -8,7 +8,7 @@ const actions = require('../actions');
const addState = connect(
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() {
return ws.sendInstanceReady(instance.id);
@ -18,7 +18,7 @@ const addState = connect(
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) {
@ -57,12 +57,12 @@ function Cryp(props) {
setInfo,
setActiveCryp,
setVboxHighlight,
vboxInfo,
itemInfo,
} = props;
function setHighlight(type) {
if (type === 'skill') return setVboxHighlight(vboxInfo.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 === 'skill') return setVboxHighlight(itemInfo.items.filter(v => v.skill).map(v => v.v));
if (type === 'spec') return setVboxHighlight(itemInfo.items.filter(v => v.spec).map(v => v.v));
return false;
}
@ -74,8 +74,8 @@ function Cryp(props) {
}
const { vbox } = player;
const skillList = vboxInfo.items.filter(v => v.skill).map(v => v.v);
const specList = vboxInfo.items.filter(v => v.spec).map(v => v.v);
const skillList = itemInfo.items.filter(v => v.skill).map(v => v.v);
const specList = itemInfo.items.filter(v => v.spec).map(v => v.v);
const skills = range(0, 3).map(i => {
const skill = cryp.skills[i];
@ -194,7 +194,7 @@ function InstanceCryps(props) {
sendVboxApply,
vboxHidden,
vboxInfo,
itemInfo,
setVboxHighlight,
} = props;
@ -202,7 +202,7 @@ function InstanceCryps(props) {
if (instance.phase === 'Lobby') return false;
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'}`;

View File

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

View File

@ -26,7 +26,7 @@ function Vbox(args) {
vboxHidden,
vboxHighlight,
setVboxHighlight,
vboxInfo,
itemInfo,
} = args;
if (!player) return false;
@ -39,10 +39,10 @@ function Vbox(args) {
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)));
const comboValues = vboxInfo.items.filter(v => {
const comboValues = itemInfo.items.filter(v => {
if (!filteredCombos.some(c => c.units.includes(v.v))) return false;
if (!['Red', 'Green', 'Blue'].includes(v.v) && combinerValues.includes(v.v)) return false;
return true;

View File

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

View File

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

View File

@ -33,6 +33,6 @@ module.exports = {
showLog: createReducer(false, actions.SET_SHOW_LOG),
vboxHidden: createReducer(false, actions.SET_VBOX_HIDDEN),
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),
};

View File

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

View File

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

View File

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

View File

@ -1,266 +1,446 @@
use serde_cbor::{from_slice, to_vec};
use uuid::Uuid;
use skill::{Skill};
use spec::{Spec};
use cryp::{Colours};
use postgres::transaction::Transaction;
use failure::Error;
#[derive(Debug,Copy,Clone,Serialize,Deserialize,PartialEq,PartialOrd,Ord,Eq)]
pub enum Item {
// colours
Blue,
Green,
Red,
// drops
use rand::prelude::*;
use rand::{thread_rng};
use rand::distributions::{LogNormal,WeightedIndex};
// base skills
Attack,
Block,
Stun,
Buff,
Debuff,
use account::Account;
use rpc::{ItemUseParams};
use cryp::{Stat, cryp_get, cryp_write};
use game::{GameMode};
use spec::{Spec, SpecType};
// specs
// Base
Damage,
Life,
Speed,
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
pub enum ItemAction {
RerollRedDamage,
RerollBlueDamage,
RerollSpeed,
RerollGreenLife,
RerollRedLife,
RerollBlueLife,
RerollEvasion,
// Lifes Upgrades
GreenLifeI,
RedLifeI,
BlueLifeI,
GRLI,
GBLI,
RBLI,
SpecRedDamage5,
SpecBlueDamage5,
SpecRedLife5,
SpecBlueLife5,
SpecBlueEvasion5,
// 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,
}
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
pub struct Item {
// mods: Vec<Mod>,
id: Uuid,
account: Uuid,
action: ItemAction,
pub enum ItemEffect {
Skill,
Spec,
}
impl Item {
pub fn new(action: ItemAction, account_id: Uuid) -> Item {
let id = Uuid::new_v4();
return Item {
id,
account: account_id,
action,
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 => (),
}
}
pub 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 {
pub item: Item,
pub units: Vec<Item>,
}
pub 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 ItemInfoCtr {
pub combos: Vec<Combo>,
pub items: Vec<ItemInfo>,
}
pub fn item_info() -> ItemInfoCtr {
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 ItemInfoCtr {
combos,
items,
};
}
fn apply(&mut self, tx: &mut Transaction, target: Uuid) -> Result<(), Error> {
match self.action {
ItemAction::RerollGreenLife => reroll(self, tx, target, Stat::GreenLife),
ItemAction::RerollRedDamage => reroll(self, tx, target, Stat::RedDamage),
ItemAction::RerollBlueDamage => reroll(self, tx, target, Stat::BlueDamage),
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),
ItemAction::SpecBlueDamage5 => spec_add(self, tx, target, SpecType::BlueDamage5),
_ => unimplemented!(),
}
}
}
fn spec_add(item: &mut Item, tx: &mut Transaction, target: Uuid, spec_type: SpecType) -> Result<(), Error> {
let mut cryp = cryp_get(tx, target, item.account)?;
let spec = Spec::new(spec_type);
cryp.spec_add(spec)?;
cryp_write(cryp, tx)?;
return Ok(());
}
fn reroll(item: &mut Item, tx: &mut Transaction, target: Uuid, stat: Stat) -> Result<(), Error> {
let mut cryp = cryp_get(tx, target, item.account)?;
cryp.roll_stat(stat);
cryp_write(cryp, tx)?;
return Ok(());
}
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> {
let mut rng = thread_rng();
let log_normal = LogNormal::new(1.0, 1.0);
let num_drops = log_normal.sample(&mut rng).floor() as u16;
let actions = mode_drops(mode);
info!("{:?} drops", num_drops);
for _i in 0..num_drops {
let dist = WeightedIndex::new(actions.iter().map(|item| item.1)).unwrap();
let kind = actions[dist.sample(&mut rng)].0;
let item = Item::new(kind, account_id);
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> {
let item_bytes = to_vec(&item)?;
let query = "
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> {
let query = "
SELECT data
FROM items
WHERE id = $1
AND account = $2
FOR UPDATE;
";
let result = tx
.query(query, &[&params.item, &account.id])?;
let returned = result.iter().next().expect("no row returned");
let item_bytes: Vec<u8> = returned.get(0);
let mut item = from_slice::<Item>(&item_bytes)?;
item.apply(tx, params.target)?;
item_delete(tx, params.item)?;
return Ok(());
}
pub fn item_delete(tx: &mut Transaction, id: Uuid) -> Result<(), Error> {
let query = "
DELETE
FROM items
WHERE id = $1;
";
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
.query(query, &[&account.id])?;
let mut items = vec![];
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
// name
// "MapMonstersCurseEffectOnSelfFinal3": {
// "adds_tags": [],
// "domain": "area",
// "generation_type": "prefix",
// "generation_weights": [],
// "grants_buff": {},
// "grants_effect": {},
// "group": "MapHexproof",
// "is_essence_only": false,
// "name": "Hexwarded",
// "required_level": 1,
// "spawn_weights": [
// {
// "tag": "top_tier_map",
// "weight": 0
// },
// {
// "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;
#[macro_use] extern crate log;
mod account;
mod cryp;
mod game;
mod instance;
mod item;
mod mob;
mod names;
mod net;
mod player;
mod rpc;
mod skill;
mod spec;
mod names;
mod rpc;
mod account;
mod instance;
mod player;
mod mob;
mod util;
mod vbox;
mod warden;

View File

@ -10,9 +10,10 @@ use failure::err_msg;
use account::Account;
use cryp::{Cryp, Colours, cryp_get};
use vbox::{Vbox, Item, ItemEffect};
use vbox::{Vbox};
use item::{Item, ItemEffect};
use rpc::{PlayerCrypsSetParams};
use instance::{Instance, instance_get, instance_update};
use instance::{Instance};
use skill::{Effect};
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 account::{Account, account_create, account_login, account_from_token, account_cryps, account_instances};
use skill::{Skill};
// use zone::{Zone, zone_create, zone_join, zone_close};
use spec::{Spec};
use player::{Score, player_mm_cryps_set};
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;
@ -97,7 +97,7 @@ impl Rpc {
"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),
"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)),
};
@ -405,7 +405,7 @@ pub enum RpcResult {
Account(Account),
CrypList(Vec<Cryp>),
GameState(Game),
VboxInfo(VboxInfo),
ItemInfo(ItemInfoCtr),
InstanceScores(Vec<(String, Score)>),
// ZoneState(Zone),
// ZoneClose(()),

View File

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

View File

@ -1,5 +1,4 @@
use std::iter;
use uuid::Uuid;
// reclaims
use rand::prelude::*;
@ -13,453 +12,10 @@ use failure::err_msg;
use account::Account;
use rpc::{VboxAcceptParams, VboxDiscardParams, VboxCombineParams, VboxApplyParams, VboxReclaimParams, VboxUnequipParams};
use skill::{Skill};
use spec::{Spec};
use instance::{Instance, instance_get, instance_update};
use cryp::{Colours};
#[derive(Debug,Copy,Clone,Serialize,Deserialize,PartialEq,PartialOrd,Ord,Eq)]
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,
};
}
use item::*;
#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct Vbox {
@ -677,7 +233,7 @@ mod tests {
}
// #[test]
// fn vbox_info_test() {
// info!("{:#?}", vbox_info());
// fn item_info_test() {
// info!("{:#?}", item_info());
// }
}