Merge branch 'combos'
This commit is contained in:
commit
9b68fd0a09
@ -28,8 +28,8 @@ function registerEvents(registry, events, tutorial) {
|
||||
registry.set('activeSkill', skill);
|
||||
}
|
||||
|
||||
function setItems(items) {
|
||||
registry.set('itemList', items);
|
||||
function setVbox(items) {
|
||||
registry.set('vbox', items);
|
||||
}
|
||||
|
||||
function setZone(zone) {
|
||||
@ -177,7 +177,7 @@ function registerEvents(registry, events, tutorial) {
|
||||
setActiveSkill,
|
||||
setCryps,
|
||||
setGame,
|
||||
setItems,
|
||||
setVbox,
|
||||
setWs,
|
||||
setGameList,
|
||||
setZone,
|
||||
|
||||
@ -85,9 +85,9 @@ class CrypImage extends Phaser.GameObjects.Image {
|
||||
scene.add.text(nameX, nameY, cryp.name, TEXT.NORMAL).setOrigin(team, 0);
|
||||
// Add cryp stat bars
|
||||
this.health = scene.add.existing(new StatBar(scene, this, 'HP'));
|
||||
this.armour = scene.add.existing(new StatBar(scene, this, 'Armour'));
|
||||
this.red_shield = scene.add.existing(new StatBar(scene, this, 'Red Shield'));
|
||||
this.blue_shield = scene.add.existing(new StatBar(scene, this, 'Blue Shield'));
|
||||
this.evasion = scene.add.existing(new StatBar(scene, this, 'Evasion'));
|
||||
this.spellShield = scene.add.existing(new StatBar(scene, this, 'Spell Shield'));
|
||||
|
||||
this.effects = scene.add.existing(new Effects(scene, team, iter));
|
||||
this.statusText = scene.add.text(statusX, statusY, '', TEXT.NORMAL);
|
||||
@ -116,9 +116,9 @@ class CrypImage extends Phaser.GameObjects.Image {
|
||||
|
||||
reduceDefense(amount, type) {
|
||||
if (type === 'PhysDmg') {
|
||||
this.armour.takeDamage(amount);
|
||||
} else if (type === 'SpellDmg') {
|
||||
this.spellShield.takeDamage(amount);
|
||||
this.red_shield.takeDamage(amount);
|
||||
} else if (type === 'BlueDmg') {
|
||||
this.blue_shield.takeDamage(amount);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -17,8 +17,8 @@ const itemListWidth = () => Math.floor(CANVAS_WIDTH * 0.5);
|
||||
const itemListHeight = () => Math.floor(CANVAS_HEIGHT * 0.5);
|
||||
const itemListX = () => 0;
|
||||
const itemListY = () => Math.floor(CANVAS_HEIGHT * 0.5);
|
||||
const itemBlockWidth = () => Math.floor(itemListWidth() * 0.1);
|
||||
const itemBlockHeight = () => Math.floor(itemListHeight() * 0.16);
|
||||
const itemBlockWidth = () => Math.floor(itemListWidth() * 0.075);
|
||||
const itemBlockHeight = () => Math.floor(itemListHeight() * 0.12);
|
||||
|
||||
const menuNavigationWidth = () => Math.floor(CANVAS_WIDTH * 0.5);
|
||||
const menuNavigationHeight = () => Math.floor(CANVAS_HEIGHT * 0.3);
|
||||
@ -162,31 +162,31 @@ module.exports = {
|
||||
[ { name: 'Amplify',
|
||||
description: 'increase the magic damage dealt by a cryp' },
|
||||
{ name: 'Attack',
|
||||
description: 'a fast physical attack with phys dmg' },
|
||||
description: 'a fast attack with red damage' },
|
||||
{ name: 'Banish',
|
||||
description:
|
||||
'target cryp is prevented from casting any skills and taking any damage' },
|
||||
{ name: 'Blast',
|
||||
description: 'blast the target with magic damage' },
|
||||
{ name: 'Block',
|
||||
description: 'decreases incoming physical damage for 1T' },
|
||||
description: 'decreases incoming red damage for 1T' },
|
||||
{ name: 'Curse',
|
||||
description: 'target cryp takes increased magic damage' },
|
||||
{ name: 'Decay',
|
||||
description:
|
||||
'afflict a cryp with a spell damage based damage over time debuff' },
|
||||
{ name: 'Drain',
|
||||
description: 'drain hp from target cryp with a spell damage based debuff' },
|
||||
'afflict a cryp with a blue damage based damage over time debuff' },
|
||||
{ name: 'Siphon',
|
||||
description: 'siphon hp from target cryp with a blue damage based debuff' },
|
||||
{ name: 'Empower',
|
||||
description: 'increase the physical damage dealt by a cryp' },
|
||||
description: 'increase the red damage dealt by a cryp' },
|
||||
{ name: 'Haste',
|
||||
description: 'magical skill that increases speed of target cryp' },
|
||||
{ name: 'Heal', description: 'heal a cryp with spell dmg' },
|
||||
{ name: 'Heal', description: 'heal a cryp with blue damage' },
|
||||
{ name: 'Hex',
|
||||
description:
|
||||
'magical based skill that prevents target cryp from using any skills' },
|
||||
{ name: 'Parry',
|
||||
description: 'prevents all physical damage for 1T' },
|
||||
description: 'prevents all red damage for 1T' },
|
||||
{ name: 'Purge',
|
||||
description: 'remove magical buffs from target cryp' },
|
||||
{ name: 'Purify',
|
||||
@ -198,14 +198,14 @@ module.exports = {
|
||||
{ name: 'Slow',
|
||||
description: 'magical skill that reduces speed of target cryp' },
|
||||
{ name: 'Snare',
|
||||
description: 'prevents physical skills from being used for 2T' },
|
||||
description: 'prevents red skills from being used for 2T' },
|
||||
{ name: 'Stun',
|
||||
description:
|
||||
'physical skill that prevents target cryp from using any skills' },
|
||||
'red skill that prevents target cryp from using any skills' },
|
||||
{ name: 'Throw',
|
||||
description: 'stuns and makes the target take increased physical damage' },
|
||||
description: 'stuns and makes the target take increased red damage' },
|
||||
{ name: 'Triage',
|
||||
description: 'grants a spell dmg based healing over time buff' }
|
||||
description: 'grants a blue damage based healing over time buff' }
|
||||
]
|
||||
},
|
||||
};
|
||||
|
||||
@ -29,7 +29,7 @@ function renderCryps() {
|
||||
},
|
||||
},
|
||||
scene: [
|
||||
Background,
|
||||
// Background,
|
||||
Header,
|
||||
],
|
||||
};
|
||||
|
||||
@ -24,22 +24,23 @@ class StatBar extends Phaser.GameObjects.Graphics {
|
||||
super(scene);
|
||||
this.crypObj = cryp;
|
||||
this.type = type;
|
||||
console.log(type);
|
||||
|
||||
if (type === 'HP') {
|
||||
this.val = this.crypObj.cryp.hp.base;
|
||||
this.max = this.crypObj.cryp.stamina.base;
|
||||
this.max = this.crypObj.cryp.hp.base;
|
||||
this.margin = 0;
|
||||
} else if (type === 'Armour') {
|
||||
this.val = this.crypObj.cryp.armour.base;
|
||||
this.max = this.crypObj.cryp.armour.base;
|
||||
} else if (type === 'Red Shield') {
|
||||
this.val = this.crypObj.cryp.red_shield.base;
|
||||
this.max = this.crypObj.cryp.red_shield.base;
|
||||
this.margin = 1;
|
||||
} else if (type === 'Blue Shield') {
|
||||
this.val = this.crypObj.cryp.blue_shield.base;
|
||||
this.max = this.crypObj.cryp.blue_shield.base;
|
||||
this.margin = 2;
|
||||
} else if (type === 'Evasion') {
|
||||
this.val = this.crypObj.cryp.evasion.base;
|
||||
this.max = this.crypObj.cryp.evasion.base;
|
||||
this.margin = 2;
|
||||
} else if (type === 'Spell Shield') {
|
||||
this.val = this.crypObj.cryp.spell_shield.base;
|
||||
this.max = this.crypObj.cryp.spell_shield.base;
|
||||
this.margin = 3;
|
||||
}
|
||||
const { statTextX, statTextY } = statTextCoord(cryp.team, cryp.iter, this.margin);
|
||||
|
||||
@ -5,23 +5,36 @@ const {
|
||||
COLOURS,
|
||||
} = require('../constants');
|
||||
|
||||
function FindColour(item) {
|
||||
// Future add skills and use a constants lookup file ??
|
||||
switch (item) {
|
||||
case 'Green': return 0x61B329;
|
||||
case 'Red': return 0xCC3333;
|
||||
case 'Blue': return 0x6633FF;
|
||||
default: return 0x222222;
|
||||
}
|
||||
}
|
||||
|
||||
class Item extends Phaser.GameObjects.Container {
|
||||
constructor(scene, action, count, x, y, width, height) {
|
||||
constructor(scene, item, index, x, y, width, height) {
|
||||
super(scene, x, y);
|
||||
|
||||
this.state = 'deselect';
|
||||
this.action = action;
|
||||
this.scene = scene;
|
||||
|
||||
this.item = item;
|
||||
this.index = index;
|
||||
this.origX = x;
|
||||
this.origY = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
this.colour = FindColour(item);
|
||||
this.box = scene.add
|
||||
.rectangle(0, 0, width, height, 0x222222);
|
||||
.rectangle(0, 0, width, height, this.colour);
|
||||
|
||||
this.text = scene.add
|
||||
// .text(0, 0, `${action} x${count}`, TEXT.NORMAL)
|
||||
.text(0, 0, `x${count}`, TEXT.NORMAL)
|
||||
.text(0, 0, `${item}`, TEXT.NORMAL)
|
||||
.setOrigin(0.5, 0.5);
|
||||
|
||||
this.add(this.box);
|
||||
@ -31,10 +44,15 @@ class Item extends Phaser.GameObjects.Container {
|
||||
this.setInteractive();
|
||||
}
|
||||
|
||||
changeOrigin(x, y) {
|
||||
this.origX = x + this.width / 2;
|
||||
this.origY = y + this.height / 2;
|
||||
}
|
||||
|
||||
clickHandler() {
|
||||
this.scene.activeItem = this;
|
||||
// Set the main context to display the item info
|
||||
this.scene.registry.set('itemInfo', this.action);
|
||||
this.scene.registry.set('itemInfo', this.item);
|
||||
this.select();
|
||||
}
|
||||
|
||||
@ -42,7 +60,7 @@ class Item extends Phaser.GameObjects.Container {
|
||||
this.scene.children.list.forEach((item) => {
|
||||
if (item.state === 'select') item.deselect();
|
||||
});
|
||||
this.box.setFillStyle(COLOURS.SELECT);
|
||||
// this.box.setFillStyle(COLOURS.SELECT);
|
||||
this.state = 'select';
|
||||
}
|
||||
|
||||
@ -50,12 +68,12 @@ class Item extends Phaser.GameObjects.Container {
|
||||
this.scene.children.list.forEach((item) => {
|
||||
if (item.state === 'select') item.deselect();
|
||||
});
|
||||
this.box.setFillStyle(0xff0000);
|
||||
this.box.setFillStyle(0x222222);
|
||||
this.state = 'activate';
|
||||
}
|
||||
|
||||
deselect() {
|
||||
this.box.setFillStyle(0x222222);
|
||||
this.box.setFillStyle(this.colour);
|
||||
this.state = 'deselect';
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,15 +16,34 @@ const ITEM_WIDTH = ITEM_LIST.itemWidth();
|
||||
const ITEM_HEIGHT = ITEM_LIST.itemHeight();
|
||||
|
||||
const INV_X = X + ITEM_WIDTH * 0.325;
|
||||
const INV_Y = Y + ITEM_HEIGHT * 1.5;
|
||||
const INV_Y = Y + ITEM_HEIGHT;
|
||||
const INV_ROWS = 3;
|
||||
const INV_COLUMNS = 5;
|
||||
const INV_COLUMNS = 3;
|
||||
|
||||
const COMB_X = INV_X + ITEM_WIDTH * 6.75;
|
||||
const COMB_X = INV_X + ITEM_WIDTH * 5.75;
|
||||
const COMB_Y = INV_Y;
|
||||
const COMB_ROWS = 2;
|
||||
const COMB_COLUMNS = 2;
|
||||
|
||||
const BOX_X = X + ITEM_WIDTH * 2;
|
||||
const BOX_Y = Y + ITEM_HEIGHT * 5;
|
||||
const BOX_ROWS = 3;
|
||||
const BOX_COLUMNS = 6;
|
||||
|
||||
|
||||
const drawVbox = (graphics) => {
|
||||
const boxDrawX = BOX_X - ITEM_WIDTH * 0.05;
|
||||
const boxDrawY = BOX_Y - ITEM_HEIGHT * 0.05;
|
||||
for (let i = 0; i <= BOX_COLUMNS; i += 1) {
|
||||
const x = boxDrawX + i * ITEM_WIDTH * 1.1;
|
||||
graphics.lineBetween(x, boxDrawY, x, boxDrawY + ITEM_HEIGHT * 1.1 * BOX_ROWS);
|
||||
}
|
||||
for (let i = 0; i <= BOX_ROWS; i += 1) {
|
||||
const y = boxDrawY + i * ITEM_HEIGHT * 1.1;
|
||||
graphics.lineBetween(boxDrawX, y, boxDrawX + ITEM_WIDTH * 1.1 * BOX_COLUMNS, y);
|
||||
}
|
||||
};
|
||||
|
||||
const drawInventory = (graphics) => {
|
||||
const invDrawX = INV_X - ITEM_WIDTH * 0.05;
|
||||
const invDrawY = INV_Y - ITEM_HEIGHT * 0.05;
|
||||
@ -55,16 +74,40 @@ class CombinerHitBox extends Phaser.GameObjects.Rectangle {
|
||||
constructor(scene, x, y, i) {
|
||||
super(scene, x, y, ITEM_WIDTH, ITEM_HEIGHT, 0x000000);
|
||||
this.setOrigin(0);
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.slot = i;
|
||||
this.item = false;
|
||||
this.itemSelect = () => this.setFillStyle(0x222222);
|
||||
this.itemDeselect = () => this.setFillStyle(0x000000);
|
||||
}
|
||||
|
||||
allocate(item) {
|
||||
if (this.item) this.deallocate();
|
||||
item.setPosition(this.x + item.width / 2, this.y + item.height / 2);
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
deallocate() {
|
||||
if (this.item) this.item.setPosition(this.item.origX, this.item.origY);
|
||||
this.item = false;
|
||||
}
|
||||
}
|
||||
|
||||
class DeleteHitBox extends Phaser.GameObjects.Rectangle {
|
||||
constructor(scene, x, y) {
|
||||
super(scene, x, y, ITEM_WIDTH * 1.25, ITEM_HEIGHT * 1.25, 0x222222);
|
||||
this.setOrigin(0);
|
||||
this.itemSelect = () => this.setFillStyle(0xff0000);
|
||||
this.itemDeselect = () => this.setFillStyle(0x222222);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const itemCheckHitbox = (scene, pointer) => {
|
||||
const { list } = scene.scene.get('MenuCrypList').children;
|
||||
const hitboxes = list.filter(c => c.cryp)
|
||||
.concat(scene.children.list.filter(c => c instanceof CombinerHitBox));
|
||||
.concat(scene.children.list.filter(c => c instanceof CombinerHitBox || c instanceof DeleteHitBox));
|
||||
|
||||
let found;
|
||||
for (let i = 0; i < hitboxes.length; i += 1) {
|
||||
@ -84,77 +127,165 @@ class ItemList extends Phaser.Scene {
|
||||
}
|
||||
|
||||
updateData(parent, key, data) {
|
||||
if (key === 'itemList') {
|
||||
if (key === 'vbox') {
|
||||
this.registry.events.off('changedata', this.updateData, this);
|
||||
this.registry.events.off('setdata', this.updateData, this);
|
||||
this.scene.restart(data);
|
||||
}
|
||||
}
|
||||
|
||||
create(itemList) {
|
||||
if (!itemList) return false;
|
||||
create(vbox) {
|
||||
this.registry.events.on('changedata', this.updateData, this);
|
||||
this.registry.events.on('setdata', this.updateData, this);
|
||||
this.addStatic();
|
||||
this.addItems(itemList);
|
||||
this.addClickHandlers(itemList);
|
||||
return this;
|
||||
}
|
||||
if (!vbox.bound) return false;
|
||||
this.combinerItems = this.registry.get('combinerItems');
|
||||
if (!this.combinerItems || vbox.bound.length < this.registry.get('boundLength')) {
|
||||
this.combinerItems = [-1, -1, -1];
|
||||
}
|
||||
this.registry.set('boundLength', vbox.bound.length);
|
||||
const ws = this.registry.get('ws');
|
||||
|
||||
addStatic() {
|
||||
// Static Elements
|
||||
const graphics = this.add.graphics();
|
||||
graphics.lineStyle(5, 0x808080, 1.0);
|
||||
drawCombiner(graphics);
|
||||
drawInventory(graphics);
|
||||
this.add.text(X + WIDTH / 4, Y + HEIGHT / 8, 'Inventory', TEXT.HEADER);
|
||||
this.add.text(X + WIDTH * 3 / 4, Y + HEIGHT / 8, 'Combiner', TEXT.HEADER);
|
||||
}
|
||||
drawVbox(graphics);
|
||||
|
||||
addItems(itemList) {
|
||||
const actions = countBy(itemList, i => i.action);
|
||||
this.add.text(X + WIDTH * 0.1, Y, 'Inventory', TEXT.HEADER);
|
||||
this.add.text(X + WIDTH * 0.47, Y, 'Combiner', TEXT.HEADER);
|
||||
this.add.text(X + WIDTH * 0.35, Y + HEIGHT / 2, 'Varibox', TEXT.HEADER);
|
||||
|
||||
for (let i = 0; i < (COMB_COLUMNS * COMB_ROWS); i += 1) {
|
||||
const ITEM_X = ITEM_WIDTH * 1.1 * (i % COMB_COLUMNS) + INV_X + ITEM_WIDTH * 6.75;
|
||||
const ITEM_Y = ITEM_HEIGHT * 1.1 * Math.floor(i / COMB_COLUMNS) + INV_Y;
|
||||
const reroll = this.add
|
||||
.rectangle(WIDTH * 0.01, Y + HEIGHT * 0.775, ITEM_WIDTH * 1.25, ITEM_HEIGHT * 1.25, 0x222222)
|
||||
.setInteractive()
|
||||
.setOrigin(0)
|
||||
.on('pointerdown', () => this.registry.get('ws').sendVboxDiscard(vbox.game));
|
||||
this.add.text(reroll.getCenter().x, reroll.getCenter().y, 'Reroll', TEXT.HEADER)
|
||||
.setOrigin(0.5, 0.5);
|
||||
|
||||
const combine = this.add
|
||||
.rectangle(ITEM_WIDTH * 1.1 + COMB_X, ITEM_HEIGHT * 1.1 + COMB_Y, ITEM_WIDTH, ITEM_HEIGHT, 0x222222)
|
||||
.setInteractive()
|
||||
.setOrigin(0)
|
||||
.on('pointerdown', () => {
|
||||
ws.sendVboxCombine(vbox.game, this.combinerItems);
|
||||
this.combinerItems = [-1, -1, -1];
|
||||
this.children.list.filter(obj => obj instanceof CombinerHitBox).forEach(cBox => cBox.deallocate());
|
||||
});
|
||||
this.add.text(combine.getCenter().x, combine.getCenter().y, 'C', TEXT.HEADER)
|
||||
.setOrigin(0.5, 0.5);
|
||||
|
||||
for (let i = 0; i < 3; i += 1) {
|
||||
const ITEM_X = ITEM_WIDTH * 1.1 * (i % COMB_COLUMNS) + COMB_X;
|
||||
const ITEM_Y = ITEM_HEIGHT * 1.1 * Math.floor(i / COMB_COLUMNS) + COMB_Y;
|
||||
this.add.existing(new CombinerHitBox(this, ITEM_X, ITEM_Y, i));
|
||||
}
|
||||
const del = this.add.existing(new DeleteHitBox(this, WIDTH * 0.01, Y + HEIGHT * 0.6));
|
||||
this.add.text(del.getCenter().x, del.getCenter().y, 'Del', TEXT.HEADER)
|
||||
.setOrigin(0.5, 0.5);
|
||||
|
||||
Object.keys(actions).forEach((action, i) => {
|
||||
// Generate Items
|
||||
vbox.bound.forEach((action, i) => {
|
||||
const ITEM_X = ITEM_WIDTH * 1.1 * (i % INV_COLUMNS) + INV_X + ITEM_WIDTH * 0.5;
|
||||
const ITEM_Y = ITEM_HEIGHT * 1.1 * Math.floor(i / INV_COLUMNS) + INV_Y + ITEM_HEIGHT * 0.5;
|
||||
const itemBox = new Item(this, action, actions[action], ITEM_X, ITEM_Y, ITEM_WIDTH, ITEM_HEIGHT);
|
||||
const itemBox = new Item(this, action, i, ITEM_X, ITEM_Y, ITEM_WIDTH, ITEM_HEIGHT);
|
||||
this.input.setDraggable(itemBox);
|
||||
this.add.existing(itemBox);
|
||||
});
|
||||
}
|
||||
|
||||
addClickHandlers(itemList) {
|
||||
const ws = this.registry.get('ws');
|
||||
this.input.on('dragstart', (pointer, box) => {
|
||||
if (!(box instanceof Item)) return false;
|
||||
box.clickHandler();
|
||||
vbox.free.forEach((action, i) => {
|
||||
const ITEM_X = ITEM_WIDTH * 1.1 * (i % BOX_COLUMNS) + BOX_X + ITEM_WIDTH * 0.5;
|
||||
const ITEM_Y = ITEM_HEIGHT * 1.1 * Math.floor(i / BOX_COLUMNS) + BOX_Y + ITEM_HEIGHT * 0.5;
|
||||
const itemBox = new Item(this, action, i, ITEM_X, ITEM_Y, ITEM_WIDTH, ITEM_HEIGHT);
|
||||
itemBox
|
||||
.setInteractive()
|
||||
.on('pointerdown', () => {
|
||||
ws.sendVboxAccept(vbox.game, i);
|
||||
});
|
||||
this.add.existing(itemBox);
|
||||
});
|
||||
|
||||
// Restore previous combiner item slots
|
||||
this.combinerItems.forEach((index, i) => {
|
||||
if (index === -1) return false;
|
||||
const item = this.children.list.filter(obj => obj instanceof Item).find(it => it.index === index);
|
||||
const hitBox = this.children.list.filter(obj => obj instanceof CombinerHitBox).find(hb => hb.slot === i);
|
||||
hitBox.allocate(item);
|
||||
return true;
|
||||
});
|
||||
|
||||
this.input.on('drag', (pointer, box, dragX, dragY) => {
|
||||
if (!(box instanceof Item)) return false;
|
||||
box.setPosition(dragX, dragY);
|
||||
// allocation functions
|
||||
const allocate = (item, hitBox) => {
|
||||
hitBox.allocate(item);
|
||||
this.combinerItems[hitBox.slot] = item.index;
|
||||
this.registry.set('combinerItems', this.combinerItems);
|
||||
};
|
||||
|
||||
const deallocate = (item) => {
|
||||
const clearIndex = this.combinerItems.indexOf(item.index);
|
||||
if (clearIndex !== -1) {
|
||||
this.children.list.filter(obj => obj instanceof CombinerHitBox)
|
||||
.forEach((cBox) => {
|
||||
if (cBox.item === item) cBox.deallocate();
|
||||
});
|
||||
this.combinerItems[clearIndex] = -1;
|
||||
}
|
||||
item.setPosition(item.origX, item.origY);
|
||||
};
|
||||
|
||||
const findUnallocated = () => {
|
||||
for (let i = 0; i <= 2; i += 1) {
|
||||
if (this.combinerItems[i] === -1) {
|
||||
return this.children.list.filter(obj => obj instanceof CombinerHitBox).find(hb => hb.slot === i);
|
||||
}
|
||||
} return false;
|
||||
};
|
||||
|
||||
// Add Handlers
|
||||
this.input.on('dragstart', (pointer, item) => {
|
||||
if (!(item instanceof Item)) return false;
|
||||
item.clickHandler();
|
||||
return true;
|
||||
});
|
||||
|
||||
this.input.on('drag', (pointer, item, dragX, dragY) => {
|
||||
if (!(item instanceof Item)) return false;
|
||||
item.setPosition(dragX, dragY);
|
||||
const hitBox = itemCheckHitbox(this, pointer);
|
||||
if (hitBox) hitBox.itemSelect();
|
||||
return true;
|
||||
});
|
||||
|
||||
this.input.on('dragend', (pointer, box) => {
|
||||
if (!(box instanceof Item)) return false;
|
||||
box.deselect();
|
||||
this.input.on('dragend', (pointer, item) => {
|
||||
if (!(item instanceof Item)) return false;
|
||||
|
||||
item.deselect();
|
||||
// Allocate to combiner if clicked without movement form inventory (return 0)
|
||||
if (!Math.hypot(item.x - item.origX, item.y - item.origY)) {
|
||||
const cBox = findUnallocated();
|
||||
if (cBox) allocate(item, cBox);
|
||||
return true;
|
||||
}
|
||||
// Check for hitboxes
|
||||
const hitBox = itemCheckHitbox(this, pointer);
|
||||
box.setPosition(box.origX, box.origY);
|
||||
if (!hitBox) return false;
|
||||
if (hitBox instanceof CombinerHitBox) console.log(`Moved item into slot ${hitBox.slot}`);
|
||||
else ws.sendItemUse(itemList.find(li => li.action === box.action).id, hitBox.cryp.id);
|
||||
hitBox.itemDeselect();
|
||||
if (hitBox) {
|
||||
hitBox.itemDeselect();
|
||||
// Allocate to specific combiner slot
|
||||
if (hitBox instanceof CombinerHitBox) {
|
||||
allocate(item, hitBox);
|
||||
return true;
|
||||
}
|
||||
// Allocate to cryp hitbox
|
||||
if (hitBox instanceof DeleteHitBox) ws.sendVboxDrop(vbox.game, item.index);
|
||||
else ws.sendVboxApply(vbox.game, hitBox.cryp.id, item.index);
|
||||
}
|
||||
// If the item hasn't been allocated deallocate the item
|
||||
// Scene will restart if there is vbox change
|
||||
deallocate(item);
|
||||
return true;
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
cleanUp() {
|
||||
|
||||
@ -113,10 +113,10 @@ class MenuCrypList extends Phaser.Scene {
|
||||
.setOrigin(0.5, 0.5));
|
||||
const CRYP_STATS = [
|
||||
cryp.stamina,
|
||||
cryp.armour,
|
||||
cryp.spell_shield,
|
||||
cryp.phys_dmg,
|
||||
cryp.spell_dmg,
|
||||
cryp.red_shield,
|
||||
cryp.blue_shield,
|
||||
cryp.red_damage,
|
||||
cryp.blue_damage,
|
||||
cryp.speed,
|
||||
];
|
||||
CRYP_STATS.forEach((stat, j) => crypStat(stat, j, crypInfo));
|
||||
|
||||
@ -25,6 +25,7 @@ const MAIN_MENU_SCENES = [
|
||||
'ItemInfo',
|
||||
];
|
||||
|
||||
const NULL_UUID = '00000000-0000-0000-0000-000000000000';
|
||||
|
||||
class Menu extends Phaser.Scene {
|
||||
constructor() {
|
||||
@ -37,7 +38,7 @@ class Menu extends Phaser.Scene {
|
||||
|
||||
// When we load the menu request the latest items
|
||||
// Item list will restart when the data comes in
|
||||
this.registry.get('ws').sendAccountItems();
|
||||
this.registry.get('ws').sendVboxState(NULL_UUID);
|
||||
|
||||
this.scene.manager.add('MenuCrypList', MenuCrypList, true);
|
||||
this.scene.manager.add('MenuNavigation', MenuNavigation, true);
|
||||
|
||||
@ -2,79 +2,79 @@ const passiveNodes = [
|
||||
{ x: 860, y: 1011, id: 'CMED1', alloc: false, text: '5% Increased Speed for Chaos Slow skills, 5% Increased Slow Effect'},
|
||||
{ x: 905, y: 970, id: 'CSTAT7', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 940, y: 917.5, id: 'CSTAT8', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 950, y: 1172.5, id: 'CMED2', alloc: false, text: '5% Increased Speed for Damaging Spells, 5% Increased Speed for Healing Skills'},
|
||||
{ x: 955, y: 1120, id: 'CSDMG1', alloc: false, text: '+5% Increased Spell Damage'},
|
||||
{ x: 965, y: 1082.5, id: 'CSDMG2', alloc: false, text: '+5% Increased Spell Damage'},
|
||||
{ x: 950, y: 1172.5, id: 'CMED2', alloc: false, text: '5% Increased Speed for Damaging Blues, 5% Increased Speed for Healing Skills'},
|
||||
{ x: 955, y: 1120, id: 'CSDMG1', alloc: false, text: '+5% Increased Blue Damage'},
|
||||
{ x: 965, y: 1082.5, id: 'CSDMG2', alloc: false, text: '+5% Increased Blue Damage'},
|
||||
{ x: 970, y: 872.5, id: 'CSTAT9', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 975, y: 1012.5, id: 'CSTAT6', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 995, y: 1062.5, id: 'CSDMG3', alloc: false, text: '+5% Increased Spell Damage'},
|
||||
{ x: 995, y: 1062.5, id: 'CSDMG3', alloc: false, text: '+5% Increased Blue Damage'},
|
||||
{ x: 1000, y: 1150, id: 'CHEAL1', alloc: false, text: '+5% Increased Healing'},
|
||||
{ x: 1005, y: 812.5, id: 'CMED20', alloc: false, text: '5% Increased Speed for Healing skills, 5% Increased Stamina'},
|
||||
{ x: 1024.5, y: 1122.5, id: 'CHEAL2', alloc: false, text: '+5% Increased Healing'},
|
||||
{ x: 1036.5, y: 896.5, id: 'CMED19', alloc: false, text: '5% Increased Speed for Healing skills, 5% Increased Stamina'},
|
||||
{ x: 1036.5, y: 1042.5, id: 'CMED18', alloc: false, text: '5% Increased Speed for Damaging Spells, 5% Increased Speed for Healing Skills'},
|
||||
{ x: 1036.5, y: 1042.5, id: 'CMED18', alloc: false, text: '5% Increased Speed for Damaging Blues, 5% Increased Speed for Healing Skills'},
|
||||
{ x: 1036.5, y: 1082.5, id: 'CHEAL3', alloc: false, text: '+5% Increased Healing'},
|
||||
{ x: 1041.5, y: 772.5, id: 'CSTAT10', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 1055, y: 1327.5, id: 'CMED3', alloc: false, text: '5% Increased Speed for Damaging Spells, 5% Increased Speed for Banish Skills'},
|
||||
{ x: 1055, y: 1327.5, id: 'CMED3', alloc: false, text: '5% Increased Speed for Damaging Blues, 5% Increased Speed for Banish Skills'},
|
||||
{ x: 1066.5, y: 939.5, id: 'CHEAL5', alloc: false, text: '+5% Increased Healing'},
|
||||
{ x: 1067.5, y: 995, id: 'CHEAL4', alloc: false, text: '+5% Increased Healing'},
|
||||
{ x: 1070, y: 1250, id: 'CSTAT4', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 1072.5, y: 840.5, id: 'CHEAL8', alloc: false, text: '+5% Increased Healing'},
|
||||
{ x: 1087.5, y: 700, id: 'CSTAT11', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 1097.5, y: 1052.5, id: 'CSDMG4', alloc: false, text: '+5% Increased Spell Damage'},
|
||||
{ x: 1097.5, y: 1052.5, id: 'CSDMG4', alloc: false, text: '+5% Increased Blue Damage'},
|
||||
{ x: 1102.5, y: 1140, id: 'CSTAT5', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 1102.5, y: 917.5, id: 'CHEAL6', alloc: false, text: '+5% Increased Healing'},
|
||||
{ x: 1115, y: 1332.5, id: 'CSTAT1', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 1115, y: 875, id: 'CHEAL7', alloc: false, text: '+5% Increased Healing'},
|
||||
{ x: 1130, y: 640, id: 'CSTAT12', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 1145, y: 1287.5, id: 'CSTAT3', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 1145, y: 1057.5, id: 'CSDMG5', alloc: false, text: '+5% Increased Spell Damage'},
|
||||
{ x: 1145, y: 1057.5, id: 'CSDMG5', alloc: false, text: '+5% Increased Blue Damage'},
|
||||
{ x: 1175, y: 1332.5, id: 'CSTAT2', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 1180, y: 1247.5, id: 'CMED10', alloc: false, text: '5% Increased Speed for Banish Spells, 5% Increased Stamina'},
|
||||
{ x: 1180, y: 1247.5, id: 'CMED10', alloc: false, text: '5% Increased Speed for Banish Blues, 5% Increased Stamina'},
|
||||
{ x: 1180, y: 950, id: 'CMED14', alloc: false, text: '5% Increased Speed for Chaos Slow skills, 5% Increased Speed for Banish Skills'},
|
||||
{ x: 1195, y: 875, id: 'CHEAL9', alloc: false, text: '+5% Increased Healing'},
|
||||
{ x: 1196.5, y: 635, id: 'CMED21', alloc: false, text: '5% Increased Effect of Slow, 5% Increased Stamina'},
|
||||
{ x: 1205, y: 1062.5, id: 'CSDMG6', alloc: false, text: '+5% Increased Spell Damage'},
|
||||
{ x: 1205, y: 1062.5, id: 'CSDMG6', alloc: false, text: '+5% Increased Blue Damage'},
|
||||
{ x: 1212.5, y: 1200, id: 'CHEAL14', alloc: false, text: '+5% Increased Healing'},
|
||||
{ x: 1231.5, y: 590, id: 'CSTAT14', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 1235, y: 772.5, id: 'CHEAL12', alloc: false, text: '+5% Increased Healing'},
|
||||
{ x: 1240, y: 1225, id: 'CPHYS1', alloc: false, text: '+2% Reduced Physical Damage Taken'},
|
||||
{ x: 1240, y: 1322.5, id: 'CMED4', alloc: false, text: '5% Increased Speed for Damaging Spells, 5% Increased Stamina'},
|
||||
{ x: 1240, y: 1322.5, id: 'CMED4', alloc: false, text: '5% Increased Speed for Damaging Blues, 5% Increased Stamina'},
|
||||
{ x: 1258.5, y: 1107.5, id: 'CHEAL15', alloc: false, text: '+5% Increased Healing'},
|
||||
{ x: 1260, y: 917.5, id: 'CHEAL10', alloc: false, text: '+5% Increased Healing'},
|
||||
{ x: 1263, y: 520, id: 'CLRG4', alloc: false, text: 'Damaging spells have a 20% chance to inflict slow'},
|
||||
{ x: 1273.5, y: 1057.5, id: 'CMED13', alloc: false, text: '5% Increased Speed for Banish Spells, 5% Increased Speed for Damaging Spells'},
|
||||
{ x: 1275, y: 1167.5, id: 'CMED11', alloc: false, text: '5% Increased Speed for Banish Spells, 5% Increased Stamina'},
|
||||
{ x: 1275, y: 947.5, id: 'CMED15', alloc: false, text: '5% Increased Speed for Chaos Slow skills, 5% Increased Speed for Damaging Spells'},
|
||||
{ x: 1277.5, y: 872.5, id: 'CMED16', alloc: false, text: '5% Increased Speed for Damaging Spells, 5% Increased Speed for Healing Skills'},
|
||||
{ x: 1263, y: 520, id: 'CLRG4', alloc: false, text: 'Damaging blues have a 20% chance to inflict slow'},
|
||||
{ x: 1273.5, y: 1057.5, id: 'CMED13', alloc: false, text: '5% Increased Speed for Banish Blues, 5% Increased Speed for Damaging Blues'},
|
||||
{ x: 1275, y: 1167.5, id: 'CMED11', alloc: false, text: '5% Increased Speed for Banish Blues, 5% Increased Stamina'},
|
||||
{ x: 1275, y: 947.5, id: 'CMED15', alloc: false, text: '5% Increased Speed for Chaos Slow skills, 5% Increased Speed for Damaging Blues'},
|
||||
{ x: 1277.5, y: 872.5, id: 'CMED16', alloc: false, text: '5% Increased Speed for Damaging Blues, 5% Increased Speed for Healing Skills'},
|
||||
{ x: 1278.5, y: 812.5, id: 'CHEAL11', alloc: false, text: '+5% Increased Healing'},
|
||||
{ x: 1280, y: 732.5, id: 'CHEAL13', alloc: false, text: '+5% Increased Healing'},
|
||||
{ x: 1281.5, y: 1002.5, id: 'CSDMG7', alloc: false, text: '+5% Increased Spell Damage'},
|
||||
{ x: 1281.5, y: 1002.5, id: 'CSDMG7', alloc: false, text: '+5% Increased Blue Damage'},
|
||||
{ x: 1284, y: 640, id: 'CSTAT15', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 1298.5, y: 1107.5, id: 'CPHYS4', alloc: false, text: '+2% Reduced Physical Damage Taken'},
|
||||
{ x: 1302.5, y: 917.5, id: 'CSDMG8', alloc: false, text: '+5% Increased Spell Damage'},
|
||||
{ x: 1302.5, y: 917.5, id: 'CSDMG8', alloc: false, text: '+5% Increased Blue Damage'},
|
||||
{ x: 1305, y: 1307.5, id: 'CPHYS2', alloc: false, text: '+2% Reduced Physical Damage Taken'},
|
||||
{ x: 1306, y: 1347.5, id: 'CSDMG10', alloc: false, text: '+5% Increased Spell Damage'},
|
||||
{ x: 1306, y: 1347.5, id: 'CSDMG10', alloc: false, text: '+5% Increased Blue Damage'},
|
||||
{ x: 1315, y: 762.5, id: 'CMED17', alloc: false, text: '5% Increased Speed for Healing skills, 5% Increased Stamina'},
|
||||
{ x: 1326.5, y: 590, id: 'CSTAT16', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 1346.5, y: 635, id: 'CMED22', alloc: false, text: '5% Increased Effect of Slow, 5% Increased Stamina'},
|
||||
{ x: 1348.5, y: 535, id: 'CSTAT13', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 1355, y: 1322.5, id: 'CMED5', alloc: false, text: '5% Increased Speed for Damaging Spells, 5% Increased Stamina'},
|
||||
{ x: 1360, y: 1002.5, id: 'CSDMG9', alloc: false, text: '+5% Increased Spell Damage'},
|
||||
{ x: 1355, y: 1322.5, id: 'CMED5', alloc: false, text: '5% Increased Speed for Damaging Blues, 5% Increased Stamina'},
|
||||
{ x: 1360, y: 1002.5, id: 'CSDMG9', alloc: false, text: '+5% Increased Blue Damage'},
|
||||
{ x: 1399.5, y: 1107.5, id: 'CPHYS5', alloc: false, text: '+2% Reduced Physical Damage Taken'},
|
||||
{ x: 1400, y: 807.5, id: 'CMED24', alloc: false, text: '5% Increased Speed for Damaging Spells, 5% Increased Speed for Healing Skills'},
|
||||
{ x: 1400, y: 807.5, id: 'CMED24', alloc: false, text: '5% Increased Speed for Damaging Blues, 5% Increased Speed for Healing Skills'},
|
||||
{ x: 1409.5, y: 1312.5, id: 'CPHYS3', alloc: false, text: '+2% Reduced Physical Damage Taken'},
|
||||
{ x: 1410, y: 1347.5, id: 'CSDMG11', alloc: false, text: '+5% Increased Spell Damage'},
|
||||
{ x: 1410, y: 532.5, id: 'CMED23', alloc: false, text: '5% Increased Speed for Banish Spells, 5% Increased Effect of Slow'},
|
||||
{ x: 1410, y: 1347.5, id: 'CSDMG11', alloc: false, text: '+5% Increased Blue Damage'},
|
||||
{ x: 1410, y: 532.5, id: 'CMED23', alloc: false, text: '5% Increased Speed for Banish Blues, 5% Increased Effect of Slow'},
|
||||
{ x: 1420, y: 732.5, id: 'CSTAT19', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 1430, y: 1205, id: 'CPHYS7', alloc: false, text: '+2% Reduced Physical Damage Taken'},
|
||||
{ x: 1447.5, y: 765, id: 'CMED25', alloc: false, text: '5% Increased Speed for Damaging Spells, 5% Increased Speed for Healing Skills'},
|
||||
{ x: 1452.5, y: 1322.5, id: 'CMED6', alloc: false, text: '5% Increased Speed for Damaging Spells, 5% Increased Stamina'},
|
||||
{ x: 1447.5, y: 765, id: 'CMED25', alloc: false, text: '5% Increased Speed for Damaging Blues, 5% Increased Speed for Healing Skills'},
|
||||
{ x: 1452.5, y: 1322.5, id: 'CMED6', alloc: false, text: '5% Increased Speed for Damaging Blues, 5% Increased Stamina'},
|
||||
{ x: 1455, y: 1267.5, id: 'CSTAT33', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 1455, y: 1147.5, id: 'CMED12', alloc: false, text: '5% Increased Speed for Banish Spells, 5% Increased Stamina'},
|
||||
{ x: 1455, y: 1147.5, id: 'CMED12', alloc: false, text: '5% Increased Speed for Banish Blues, 5% Increased Stamina'},
|
||||
{ x: 1455, y: 1042.5, id: 'CSTAT35', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 1457.5, y: 975, id: 'CSTAT37', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 1462.5, y: 825, id: 'CLRG3', alloc: false, text: '20% critical strike chance for spells'},
|
||||
{ x: 1462.5, y: 825, id: 'CLRG3', alloc: false, text: '20% critical strike chance for blues'},
|
||||
{ x: 1485, y: 640, id: 'CSTAT17', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 1500, y: 1110, id: 'CPHYS6', alloc: false, text: '+2% Reduced Physical Damage Taken'},
|
||||
{ x: 1505, y: 1242.5, id: 'CSTAT32', alloc: false, text: '+2 Chaos Stat'},
|
||||
@ -85,8 +85,8 @@ const passiveNodes = [
|
||||
{ x: 1555, y: 732.5, id: 'CSTAT18', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 1597.5, y: 827.5, id: 'CSTAT21', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 1607.5, y: 1277.5, id: 'CSTAT30', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 1612.5, y: 1137.5, id: 'CLRG1', alloc: false, text: 'When you take physical damage there is a 20% chance to heal for 150% of physical damage taken'},
|
||||
{ x: 1612.5, y: 955, id: 'CLRG2', alloc: false, text: 'Your healing spells have a 20% chance to increase ally speed by 100%'},
|
||||
{ x: 1612.5, y: 1137.5, id: 'CLRG1', alloc: false, text: 'When you take red damage there is a 20% chance to heal for 150% of red damage taken'},
|
||||
{ x: 1612.5, y: 955, id: 'CLRG2', alloc: false, text: 'Your healing blues have a 20% chance to increase ally speed by 100%'},
|
||||
{ x: 1657.5, y: 822.5, id: 'CSTAT22', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 1657.5, y: 1312.5, id: 'CSTAT29', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 1685, y: 1187.5, id: 'CSTAT27', alloc: false, text: '+2 Chaos Stat'},
|
||||
@ -94,7 +94,7 @@ const passiveNodes = [
|
||||
{ x: 1690, y: 1117.5, id: 'CSTAT26', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 1705, y: 960, id: 'CSTAT24', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 1712.5, y: 850, id: 'CMED9', alloc: false, text: '5% Increased Speed for Healing skills, 5% Increased Stamina'},
|
||||
{ x: 1717.5, y: 1267.5, id: 'CMED7', alloc: false, text: '5% Increased Speed for Damaging Spells, 5% Increased Stamina'},
|
||||
{ x: 1717.5, y: 1267.5, id: 'CMED7', alloc: false, text: '5% Increased Speed for Damaging Blues, 5% Increased Stamina'},
|
||||
{ x: 1725, y: 1222.5, id: 'CSTAT28', alloc: false, text: '+2 Chaos Stat'},
|
||||
{ x: 1727.5, y: 1062.5, id: 'CMED8', alloc: false, text: '5% Increased Speed for Chaos Slow skills, 5% Increased Speed for Banish Skills'},
|
||||
{ x: 1737.5, y: 917.5, id: 'CSTAT23', alloc: false, text: '+2 Chaos Stat'},
|
||||
|
||||
@ -66,11 +66,11 @@ class StatSheet extends Phaser.Scene {
|
||||
|
||||
const CRYP_STATS = [
|
||||
cryp.stamina,
|
||||
cryp.armour,
|
||||
cryp.spell_shield,
|
||||
cryp.red_shield,
|
||||
cryp.blue_shield,
|
||||
cryp.evasion,
|
||||
cryp.phys_dmg,
|
||||
cryp.spell_dmg,
|
||||
cryp.red_damage,
|
||||
cryp.blue_damage,
|
||||
cryp.speed,
|
||||
];
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
const toast = require('izitoast');
|
||||
const cbor = require('borc');
|
||||
|
||||
|
||||
const SOCKET_URL = process.env.NODE_ENV === 'production' ? 'wss://cryps.gg/ws' : 'ws://localhost:40000';
|
||||
|
||||
function errorToast(err) {
|
||||
@ -44,10 +45,6 @@ function createSocket(events) {
|
||||
send({ method: 'account_cryps', params: {} });
|
||||
}
|
||||
|
||||
function sendAccountItems() {
|
||||
send({ method: 'account_items', params: {} });
|
||||
}
|
||||
|
||||
function sendAccountZone() {
|
||||
send({ method: 'account_zone', params: {} });
|
||||
}
|
||||
@ -88,6 +85,31 @@ function createSocket(events) {
|
||||
send({ method: 'cryp_unspec', params: { id, spec } });
|
||||
}
|
||||
|
||||
function sendVboxState(gameId) {
|
||||
send({ method: 'vbox_state', params: { game_id: gameId } });
|
||||
}
|
||||
|
||||
function sendVboxAccept(gameId, i) {
|
||||
send({ method: 'vbox_accept', params: { game_id: gameId, index: i } });
|
||||
}
|
||||
|
||||
function sendVboxApply(gameId, crypId, index) {
|
||||
send({ method: 'vbox_apply', params: { game_id: gameId, cryp_id: crypId, index } });
|
||||
}
|
||||
|
||||
function sendVboxDiscard(gameId) {
|
||||
send({ method: 'vbox_discard', params: { game_id: gameId } });
|
||||
}
|
||||
|
||||
function sendVboxCombine(gameId, indices) {
|
||||
send({ method: 'vbox_combine', params: { game_id: gameId, indices } });
|
||||
}
|
||||
|
||||
|
||||
function sendVboxDrop(gameId, index) {
|
||||
send({ method: 'vbox_drop', params: { game_id: gameId, index } });
|
||||
}
|
||||
|
||||
|
||||
function sendPressR() {
|
||||
send({ method: 'press_r', params: { } });
|
||||
@ -110,10 +132,6 @@ function createSocket(events) {
|
||||
events.setActiveSkill(null);
|
||||
}
|
||||
|
||||
function sendItemUse(item, target) {
|
||||
send({ method: 'item_use', params: { item, target } });
|
||||
}
|
||||
|
||||
function sendZoneCreate() {
|
||||
send({ method: 'zone_create', params: {} });
|
||||
}
|
||||
@ -136,7 +154,7 @@ function createSocket(events) {
|
||||
account = login;
|
||||
events.setAccount(login);
|
||||
sendAccountCryps();
|
||||
sendGameJoinableList();
|
||||
// sendGameJoinableList();
|
||||
}
|
||||
|
||||
function accountCryps(response) {
|
||||
@ -162,16 +180,17 @@ function createSocket(events) {
|
||||
const [structName, game] = response;
|
||||
}
|
||||
|
||||
function accountItems(response) {
|
||||
const [structName, items] = response;
|
||||
events.setItems(items);
|
||||
}
|
||||
|
||||
function zoneState(response) {
|
||||
const [structName, zone] = response;
|
||||
events.setZone(zone);
|
||||
}
|
||||
|
||||
function vboxState(response) {
|
||||
const [structName, vbox] = response;
|
||||
console.log(vbox);
|
||||
events.setVbox(vbox);
|
||||
}
|
||||
|
||||
// -------------
|
||||
// Setup
|
||||
// -------------
|
||||
@ -188,11 +207,10 @@ function createSocket(events) {
|
||||
account_login: accountLogin,
|
||||
account_create: accountLogin,
|
||||
account_cryps: accountCryps,
|
||||
account_items: accountItems,
|
||||
zone_create: res => console.log(res),
|
||||
zone_state: zoneState,
|
||||
zone_close: res => console.log(res),
|
||||
|
||||
vbox_state: vboxState,
|
||||
};
|
||||
|
||||
function errHandler(error) {
|
||||
@ -268,7 +286,6 @@ function createSocket(events) {
|
||||
sendAccountCreate,
|
||||
sendAccountDemo,
|
||||
sendAccountCryps,
|
||||
sendAccountItems,
|
||||
sendAccountZone,
|
||||
sendGameState,
|
||||
sendGamePve,
|
||||
@ -280,11 +297,16 @@ function createSocket(events) {
|
||||
sendCrypSpawn,
|
||||
sendCrypLearn,
|
||||
sendCrypForget,
|
||||
sendItemUse,
|
||||
sendSpecForget,
|
||||
sendZoneCreate,
|
||||
sendZoneJoin,
|
||||
sendZoneClose,
|
||||
sendVboxState,
|
||||
sendVboxAccept,
|
||||
sendVboxApply,
|
||||
sendVboxDrop,
|
||||
sendVboxCombine,
|
||||
sendVboxDiscard,
|
||||
connect,
|
||||
};
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ This homepage shows your cryps, joinable online games, PVE options and your item
|
||||
If you have no cryps yet, press SPAWN and give your cryp a name to create one.
|
||||
Once you have made a cryp, click on them to visit their stat page and teach them some SKILLS.
|
||||
The stat page also has descriptions of each skill and their effects.
|
||||
cryps have 3 basic stats: stamina, physical damage and magic damage.
|
||||
cryps have 3 basic stats: stamina, red damage and magic damage.
|
||||
Toggle whether a cryp is selected for your team by clicking the coloured stripes next to the cryp or press 1,2,3.
|
||||
Once you have a team ready press the New PVE Game button to start playing.
|
||||
`;
|
||||
@ -29,7 +29,7 @@ A cryps battle has two main phases. This first phase is called the SKILL PHASE.
|
||||
Your cryps are positioned on the left, your opponent's are on the right.
|
||||
In the centre are your cryps' SKILLS, grayed out SKILLS are currently ON COOLDOWN.
|
||||
A skill's cooldown reduces on every turn that cryp does not use a skill with a cooldown.
|
||||
For the moment, drag ATTACK onto the opponent team to have your cryps attack them with physical damage.
|
||||
For the moment, drag ATTACK onto the opponent team to have your cryps attack them with red damage.
|
||||
`;
|
||||
|
||||
// const TARGET_PHASE_MESSAGE = `
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
exports.up = async knex => {
|
||||
return knex.schema.createTable('items', table => {
|
||||
table.uuid('id').primary();
|
||||
table.uuid('account').notNullable()
|
||||
table.foreign('account')
|
||||
.references('id')
|
||||
.inTable('accounts')
|
||||
.onDelete('CASCADE');
|
||||
table.binary('data').notNullable();
|
||||
table.index('id');
|
||||
table.index('account');
|
||||
});
|
||||
};
|
||||
|
||||
exports.down = async () => {};
|
||||
36
ops/migrations/20190216123550_vbox.js
Normal file
36
ops/migrations/20190216123550_vbox.js
Normal file
@ -0,0 +1,36 @@
|
||||
const NULL_UUID = '00000000-0000-0000-0000-000000000000';
|
||||
|
||||
exports.up = async knex => {
|
||||
await knex.schema.createTable('vbox', table => {
|
||||
table.timestamps();
|
||||
table.uuid('id').primary();
|
||||
table.uuid('account').notNullable()
|
||||
table.uuid('game').notNullable()
|
||||
table.binary('data').notNullable();
|
||||
|
||||
table.foreign('game')
|
||||
.references('id')
|
||||
.inTable('games')
|
||||
.onDelete('CASCADE');
|
||||
|
||||
table.foreign('account')
|
||||
.references('id')
|
||||
.inTable('accounts')
|
||||
.onDelete('CASCADE');
|
||||
|
||||
table.index('id');
|
||||
table.index('account');
|
||||
table.unique(['account', 'game']);
|
||||
});
|
||||
|
||||
// not really sure if this is a good idea
|
||||
await knex('games').insert({
|
||||
id: NULL_UUID,
|
||||
data: 'INVALID',
|
||||
joinable: false,
|
||||
});
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
exports.down = async () => {};
|
||||
@ -11,9 +11,6 @@
|
||||
"author": "",
|
||||
"license": "UNLICENSED",
|
||||
"dependencies": {
|
||||
"ascii-tree": "^0.3.0",
|
||||
"cli-ascii-tree": "0.0.4",
|
||||
"inquirer": "^6.2.0",
|
||||
"knex": "^0.15.2",
|
||||
"pg": "^7.4.3"
|
||||
}
|
||||
|
||||
@ -55,43 +55,43 @@ Debuff `Base enemy debuff - reduce enemy speed`
|
||||
|
||||
# Nature Type (red) #
|
||||
|
||||
Bite - (Attack + 3R) Deal significant `Red` damage
|
||||
Strangle - (Stun + 3R) - Applies stun and physical dot
|
||||
Regenerate - (Buff + 3R) Restore red defense for target ally
|
||||
Snare - (Debuff + 3R) Disable enemy red skills for (3?) turns
|
||||
Parry - (Block + 3R) Avoid all damage for this turn
|
||||
Bite - (Attack RR) Deal significant `Red` damage
|
||||
Strangle - (Stun RR) - Applies stun and physical dot
|
||||
Regenerate - (Buff RR) Restore red defense for target ally
|
||||
Snare - (Debuff RR) Disable enemy red skills for (3?) turns
|
||||
Parry - (Block RR) Avoid all damage for this turn
|
||||
|
||||
# Destruction Type (blue) #
|
||||
|
||||
Blast - (Attack + 3B) Deal significant `Blue` damage
|
||||
Ruin - (Stun + 3B) - AOE stun on the enemy team for remaind of turn
|
||||
Amplify - (Buff + 3B) Increased blue damage dealt by target ally
|
||||
Curse - (Debuff + 3B) Decrease damage dealt by target enemy
|
||||
Plague Shield - (Block + 3B) Apply dot debuff to attackers
|
||||
Blast - (Attack BB) Deal significant `Blue` damage
|
||||
Ruin - (Stun BB) - AOE stun on the enemy team for remaind of turn
|
||||
Amplify - (Buff BB) Increased blue damage dealt by target ally
|
||||
Curse - (Debuff BB) Decrease damage dealt by target enemy
|
||||
Plague Shield - (Block BB) Apply dot debuff to attackers
|
||||
|
||||
# Non-Violence Type (green) #
|
||||
|
||||
Heal - (Attack + 3G) Heal ally for X
|
||||
Throw - (Stun + 3G) - Disable target and increase damage taken
|
||||
Triage - (Buff + 3G) Buff which heals ally for X over Y turns
|
||||
Purge - (Debuff + 3G) - Remove all enemy target buffs
|
||||
Reflect - (Block + 3G) - Will use targetted attacks on source
|
||||
Heal - (Attack GG) Heal ally for X
|
||||
Throw - (Stun GG) - Disable target and increase damage taken
|
||||
Triage - (Buff GG) Buff which heals ally for X over Y turns
|
||||
Purge - (Debuff GG) - Remove all enemy target buffs
|
||||
Reflect - (Block GG) - Will use targetted attacks on source
|
||||
|
||||
# Chaos Type (red / blue) #
|
||||
|
||||
Bannish - (Attack + 1R + 2B) - deal `Hybrid Red & Blue` + enemy can't attack or be attacked 3 turns
|
||||
Hex - (Stun + 2R + 1B) - enemy stunned for 3 turns
|
||||
Haste - (Buff + 2R + 1B) - significantly increase ally speed
|
||||
Slow - (Debuff + 1R + 2B) - significantly decrease enemy speed
|
||||
Taunt - (Block + 2B + 1R) - Redirect all enemy targetted skills
|
||||
Bannish - (Attack RB) - deal `Hybrid Red & Blue` + enemy can't attack or be attacked 3 turns
|
||||
Hex - (Stun RB) - enemy stunned for 3 turns
|
||||
Haste - (Buff RB) - significantly increase ally speed
|
||||
Slow - (Debuff RB) - significantly decrease enemy speed
|
||||
Taunt - (Block RB) - Redirect all enemy targetted skills
|
||||
|
||||
# Purity Type (red / green) #
|
||||
|
||||
Slay - (Attack + 1G + 2R) - deal `Red` damage. Bonus damage if the target has blue defense
|
||||
Slay - (Attack + 1G + 1R) - deal `Red` damage. Bonus damage if the target has blue defense
|
||||
Silence - (Stun + 2G + 1R) - enemy can't use blue skills for 3 turns
|
||||
Purify - (Buff + 2G + 1R) - remove all debuffs from target
|
||||
Empower - (Buff + 1G + 2R) - Increased red damage dealt by target ally
|
||||
???? - (Debuff + 1R + 2B) - ???
|
||||
Empower - (Buff + 1G + 1R) - Increased red damage dealt by target ally
|
||||
???? - (Debuff RB) - ???
|
||||
Shield - (Block + 2G + 1R) - Take no blue damage for the next 3 turns
|
||||
|
||||
# Technology Type (green / blue) type - ??? maybe rework and rename #
|
||||
|
||||
@ -6,16 +6,16 @@
|
||||
Rare `Increased Stamina`
|
||||
|
||||
Common `Increased Evasion rating`
|
||||
Common `Increased Spell Shield rating`
|
||||
Common `Increased Armour rating`
|
||||
Common `Increased Blue Shield rating`
|
||||
Common `Increased RedShield rating`
|
||||
Common `Increased Healing done`
|
||||
Common `Increased Healing received`
|
||||
Common `Increased Spell Damage`
|
||||
Common `Increased Physical Damage`
|
||||
Common `Increased Blue Damage`
|
||||
Common `Increased Red Damage`
|
||||
|
||||
Uncommon `Reduced hp loss penalty to evade chance`
|
||||
Uncommon `Increased base evasion chance per X evasion rating`
|
||||
Uncommon `Increased % mitigation from armour`
|
||||
Uncommon `Increased % mitigation from red_shield`
|
||||
Uncommon `Increased % mitigation from spell shield`
|
||||
Uncommon `Increased damage over time`
|
||||
|
||||
@ -30,11 +30,11 @@ Rare `25% hex for blast`
|
||||
Rare `cooldown reduction`
|
||||
Rare `effect duration`
|
||||
|
||||
Rare `increased phys dmg, 0 spell damage`
|
||||
Rare `increased spell dmg, 0 phys damage`
|
||||
Rare `increased phys damage, 0 spell damage`
|
||||
Rare `increased spell damage, 0 phys damage`
|
||||
|
||||
Rare `increased phys dmg, silenced`
|
||||
Rare `increased spell dmg, snared`
|
||||
Rare `increased phys damage, silenced`
|
||||
Rare `increased spell damage, snared`
|
||||
|
||||
Rare `increased speed, increased durations`
|
||||
Rare `increased speed, increased cooldowns`
|
||||
|
||||
@ -21,11 +21,11 @@ resolve phase:
|
||||
2.2 <- attack (normal resolve)
|
||||
1.1 <- hexed (no skills for the rest of this turn and next)
|
||||
|
||||
## Dmg Chart
|
||||
## Damage Chart
|
||||
|
||||
| Physical | Magic | Modifiers |
|
||||
| Red | Magic | Modifiers |
|
||||
| ------ | ------ | ------ |
|
||||
| dmg | dmg | speed |
|
||||
| damage | damage | speed |
|
||||
| evasion | resistance | cooldowns |
|
||||
| reduction | absorption? | durations |
|
||||
|
||||
|
||||
166
server/SPECS.md
Executable file
166
server/SPECS.md
Executable file
@ -0,0 +1,166 @@
|
||||
### Specs ###
|
||||
|
||||
Numbers are placeholder
|
||||
`Specs get a bonus dependent on the total of Red / Green / Blue in team skills`
|
||||
|
||||
# Example to meet 5 red tag bonus
|
||||
In your team Cryp #1 has `Strike`, Cryp #2 has `Slay` and `Heal`, Cryp #3 has `Snare`
|
||||
- RR skill `Strike` contributes 2 red tags to the total red tags (2 total)
|
||||
- RG skill `Slay` contributes 1 red tag to the total red tags (3 total)
|
||||
- GG skill `Heal` contirubes 0 red tags to the total red tags (3 total)
|
||||
- RR skill `Snare` contirubes 2 red tags to the total red tags (5 total)
|
||||
|
||||
# Specs also have `Class points`
|
||||
Basic specs (Damage / Health / Defense) will generate class points
|
||||
Advanced specs (Skill Specific Damage, Cooldown reduction, Increased durations, etc) will consume class points
|
||||
|
||||
### Generic Specs
|
||||
|
||||
(Base white skills not upgraded count as have 1 tag basic ?)
|
||||
|
||||
# Basic Damage
|
||||
`Base` -> 10% inc basic damage
|
||||
`Bonus` -> 3 basic tags -> +10% // 6 basic tags -> +15% // 12 basic tags -> +25%
|
||||
Maximum 60% inc basic damage
|
||||
|
||||
# Basic % Life
|
||||
`Base` -> 5% inc life
|
||||
`Bonus` -> 3 basic tags -> +5% // 6 basic tags -> +10% // 12 basic tags -> +15%
|
||||
Maximum 35% inc life
|
||||
|
||||
# Basic Speed
|
||||
`Base` -> 5% inc speed
|
||||
`Bonus` -> 3 basic tags -> +10% // 6 basic tags -> +15% // 12 basic tags -> +20%
|
||||
Maximum 50% inc speed
|
||||
|
||||
# Basic Class Spec
|
||||
`Base` -> +2 all class points
|
||||
`Bonus` -> 3 basic tags -> +2 // 6 basic tags -> +4 // 12 basic tags -> +6
|
||||
Maximum +14 all class points
|
||||
|
||||
# Basic Duration
|
||||
|
||||
### Increased Damage Combos ###
|
||||
|
||||
Generate by combining `Generic Spec (Basic Damage)` with respective RGB
|
||||
|
||||
# Red Damage (Dmg + RR)
|
||||
Add 5 `Nature` Class Points
|
||||
`Base` -> 10% inc red dmg
|
||||
`Bonus` 5 red tags -> +10% // 10 red tags -> +15% // 20 red tags -> +25%
|
||||
Maximum +60% red damage
|
||||
|
||||
# Blue Damage (Dmg + BB) #
|
||||
Add 5 `Destruction` Class Points
|
||||
`Base` -> 10% inc blue dmg
|
||||
`Bonus` 5 blue tags -> +10% // 10 blue tags -> +15% // 20 blue tags -> +25%
|
||||
Maximum +60% blue damage
|
||||
|
||||
# Healing (Dmg + GG) #
|
||||
Add 5 `Non-Violence` Class Points
|
||||
`Base` -> 10% inc healing
|
||||
`Bonus` 5 green tags -> +10% // 10 green tags -> +15% // 20 green tags -> +25%
|
||||
Maximum +60% inc healing
|
||||
|
||||
# Red damage and healing (Dmg + RG)
|
||||
Add 5 `Purity` Class Points
|
||||
`Base` -> 5% inc red damage and 5% inc healing
|
||||
`Bonus` (2R + 2G tags) -> +5% + 5% // (5R + 5G tags) -> +10% + 10% % // (10R + 10G) tags -> +15% + 15%
|
||||
Maximum +35% inc red damage and 35% inc healing
|
||||
|
||||
# Red and blue damage (Dmg + RB)
|
||||
Add 5 `Chaos` Class Points
|
||||
`Base` -> 5% inc red damage and 5% inc healing
|
||||
`Bonus` (2 red + 2 green tags) -> +5% + 5% // (5 red + 5 green tags) -> +10% + 10% % // 20 green tags -> +15% + 15%
|
||||
Maximum +35% inc damage and 35% inc healing
|
||||
|
||||
# Blue damage and healing (Dmg + BG)
|
||||
Add 5 `??????` Class Points
|
||||
`Base` -> 5% inc blue damage and 5% inc healing
|
||||
`Bonus` (2B + 2G tags) -> +5% + 5% // (5B + 5G tags) -> +10% + 10% % // (10B + 10G) tags -> +15% + 15%
|
||||
Maximum +35% inc blue damage and 35% inc healing
|
||||
|
||||
### Increased Life Combos ###
|
||||
|
||||
Generate by combining `Generic Spec (Basic Life)` with respective RGB
|
||||
|
||||
# Increased % Red Shield (Basic %HP + 2R)
|
||||
Add 5 Nature Class Points
|
||||
`Base` -> 10% inc red shield
|
||||
`Bonus` 5 red tags -> +10% // 10 red tags -> +15% // 20 red tags -> +20%
|
||||
Maximum +55% inc red shield
|
||||
|
||||
# Increased % Red Shield and Life (Basic %HP + 1R1G)
|
||||
Add 5 Purity Class Points
|
||||
`Base` -> 5% inc red shield and 5% inc life
|
||||
`Bonus` (2R + 2G tags) -> +5% + 5% // (5R + 5G tags) -> +10% + 10% % // (10R + 10G) tags -> +15% + 15%
|
||||
Maximum +35% inc red shield and 35% inc life
|
||||
|
||||
# Increased % Blue Shield (Basic %HP + 2B)
|
||||
Add 5 Destruction Class Points
|
||||
`Base` -> 10% inc red shield
|
||||
`Bonus` 5 blue tags -> +10% // 10 blue tags -> +15% // 20 blue tags -> +20%
|
||||
Maximum +55% inc blue shield
|
||||
|
||||
# Increased % Blue Shield and Life (Basic %HP + 1B1G)
|
||||
Add 5 ??? Class Points
|
||||
`Base` -> 5% inc red shield and 5% inc life
|
||||
`Bonus` (2B + 2G tags) -> +5% + 5% // (5B + 5G tags) -> +10% + 10% % // (10B + 10G) tags -> +15% + 15%
|
||||
Maximum +35% inc blue shield and 35% inc life
|
||||
|
||||
# Increased % Life (Basic %HP + 2G)
|
||||
Add 5 Non-Violence Class Points
|
||||
`Base` -> 10% inc hp
|
||||
`Bonus` 5 green tags -> +10% // 10 green tags -> +15% // 20 green tags -> +20%
|
||||
Maximum +55% inc hp
|
||||
|
||||
# Increased % Blue and Red Shield (Basic %HP + 1B1R)
|
||||
Add 5 Chaos Class Points
|
||||
`Base` -> 5% inc red shield and 5% inc life
|
||||
`Bonus` (2B + 2R tags) -> +5% + 5% // (5B + 5R tags) -> +10% + 10% % // (10B + 10R) tags -> +15% + 15%
|
||||
Maximum +35% inc blue shield and 35% inc red shield
|
||||
|
||||
## Upgraded Attack Spec Combos
|
||||
|
||||
# Increased Strike Damage (Combine Strike + Red Damage Spec x 2)
|
||||
Consumes 15 Nature Class Points
|
||||
`Base` -> 15% increased strike damage
|
||||
`Bonus` 5 red tags -> +15% // 10 red tags -> +20% // 20 red tags -> +30%
|
||||
Maximum 80% increased strike damage
|
||||
|
||||
# Improved Heal (Combine Heal + Healing Spec x 2)
|
||||
Consumes 15 Non-Violence Class Points
|
||||
`Base` -> 15% increased heal healing
|
||||
`Bonus` 5 green tags -> +15% // green red tags -> +20% // green red tags -> +30%
|
||||
Maximum 80% increased heal healing
|
||||
|
||||
# Increased Blast Damage (Combine Blast + Blue Spec x 2)
|
||||
Consumes 15 Destruction Class Points
|
||||
`Base` -> 15% increased blast damage
|
||||
`Bonus` 5 blue tags -> +15% // 10 blue tags -> +20% // 20 blue tags -> +30%
|
||||
Maximum 80% increased blast damage
|
||||
|
||||
# Increased Slay Damage (Combine Slay + Red Damage Spec + Healing Spec)
|
||||
Consumes 15 Purity Class Points
|
||||
`Base` -> 15% increased slay damage
|
||||
`Bonus` (2R + 2G) tags -> +15% // (5R + 5G) tags -> +20% // (10R + 10G) tags -> +30%
|
||||
Maximum 80% increased slay damage
|
||||
|
||||
# Increased Banish Damage (Combine Slay + Red Damage Spec + Blue Damage Spec)
|
||||
Consumes 15 Chaos Class Points
|
||||
`Base` -> 15% increased slay damage
|
||||
`Bonus` (2R + 2B) tags -> +15% // (5R + 5B) tags -> +20% // (10R + 10B) tags -> +30%
|
||||
Maximum 80% increased banish damage
|
||||
|
||||
## Other Combos
|
||||
|
||||
# Increased % Red Speed (Basic Speed + 2R)
|
||||
Add 5 Nature Class Points
|
||||
`Base` -> 15% inc red speed
|
||||
`Bonus` 5 red tags -> +15% // 10 red tags -> +20% // 20 red tags -> +25%
|
||||
Maximum 80% inc red speed
|
||||
|
||||
# Nature Affinity (Basic Class spec + 2R)
|
||||
`Base` -> 10 Nature Class Points
|
||||
`Bonus` 5 red tags -> +10 // 10 red tags -> +15 // 20 red tags -> +20
|
||||
Maximum 45 Nature Class Points
|
||||
@ -30,7 +30,7 @@
|
||||
* phys is faster and chaotic
|
||||
* spells are slow and reliable
|
||||
* defensives are implicit
|
||||
* armour is restored, not gained
|
||||
* red_shield is restored, not gained
|
||||
* players can feel aggressive
|
||||
|
||||
# ask sam
|
||||
@ -56,38 +56,6 @@ taunt
|
||||
|
||||
## NOW
|
||||
|
||||
inventory + drops table
|
||||
id
|
||||
data
|
||||
game
|
||||
|
||||
drops_buy(game_id, index)
|
||||
drops_get()
|
||||
inventory_get()
|
||||
|
||||
reduce balance
|
||||
move drop into inventory
|
||||
|
||||
drops_update()
|
||||
inventory_update()
|
||||
|
||||
-> inventory
|
||||
|
||||
inventory_combine(game_id, [indices])
|
||||
inventory_get()
|
||||
|
||||
new item =
|
||||
match base item
|
||||
match modifiers
|
||||
|
||||
update inventory[base_index]
|
||||
|
||||
inventory_update()
|
||||
|
||||
-> inventory
|
||||
|
||||
|
||||
|
||||
## SOON
|
||||
* clean up categories
|
||||
* why is the text fucked?
|
||||
|
||||
@ -45,14 +45,14 @@ pub enum Stat {
|
||||
Hp,
|
||||
Speed,
|
||||
Stamina,
|
||||
PhysicalDamage,
|
||||
PhysicalDamageTaken,
|
||||
SpellDamage,
|
||||
SpellDamageTaken,
|
||||
RedDamage,
|
||||
RedDamageTaken,
|
||||
BlueDamage,
|
||||
BlueDamageTaken,
|
||||
Healing,
|
||||
HealingTaken,
|
||||
Armour,
|
||||
SpellShield,
|
||||
RedShield,
|
||||
BlueShield,
|
||||
Evasion,
|
||||
}
|
||||
|
||||
@ -136,13 +136,13 @@ pub struct CrypRecover {
|
||||
pub struct Cryp {
|
||||
pub id: Uuid,
|
||||
pub account: Uuid,
|
||||
pub phys_dmg: CrypStat,
|
||||
pub spell_dmg: CrypStat,
|
||||
pub red_damage: CrypStat,
|
||||
pub red_shield: CrypStat,
|
||||
pub blue_shield: CrypStat,
|
||||
pub blue_damage: CrypStat,
|
||||
pub speed: CrypStat,
|
||||
pub stamina: CrypStat,
|
||||
pub hp: CrypStat,
|
||||
pub armour: CrypStat,
|
||||
pub spell_shield: CrypStat,
|
||||
pub evasion: CrypStat,
|
||||
pub xp: u64,
|
||||
pub lvl: u8,
|
||||
@ -164,13 +164,13 @@ impl Cryp {
|
||||
return Cryp {
|
||||
id,
|
||||
account: id,
|
||||
phys_dmg: CrypStat { base: 0, value: 0, stat: Stat::PhysicalDamage },
|
||||
spell_dmg: CrypStat { base: 0, value: 0, stat: Stat::SpellDamage },
|
||||
red_damage: CrypStat { base: 0, value: 0, stat: Stat::RedDamage },
|
||||
red_shield: CrypStat { base: 0, value: 0, stat: Stat::RedShield },
|
||||
blue_damage: CrypStat { base: 0, value: 0, stat: Stat::BlueDamage },
|
||||
blue_shield: CrypStat { base: 0, value: 0, stat: Stat::BlueShield },
|
||||
speed: CrypStat { base: 0, value: 0, stat: Stat::Speed },
|
||||
stamina: CrypStat { base: 0, value: 0, stat: Stat::Stamina },
|
||||
hp: CrypStat { base: 0, value: 0, stat: Stat::Hp },
|
||||
armour: CrypStat { base: 0, value: 0, stat: Stat::Armour },
|
||||
spell_shield: CrypStat { base: 0, value: 0, stat: Stat::SpellShield },
|
||||
evasion: CrypStat { base: 0, value: 0, stat: Stat::Evasion },
|
||||
lvl: 0,
|
||||
xp: 0,
|
||||
@ -238,15 +238,15 @@ impl Cryp {
|
||||
let evasion_max = 5;
|
||||
|
||||
match stat {
|
||||
Stat::PhysicalDamage => self.phys_dmg.set(rng.gen_range(stat_min, stat_max), &self.specs),
|
||||
Stat::SpellDamage => self.spell_dmg.set(rng.gen_range(stat_min, stat_max), &self.specs),
|
||||
Stat::RedDamage => self.red_damage.set(rng.gen_range(stat_min, stat_max), &self.specs),
|
||||
Stat::BlueDamage => self.blue_damage.set(rng.gen_range(stat_min, stat_max), &self.specs),
|
||||
Stat::Speed => self.speed.set(rng.gen_range(stat_min, stat_max), &self.specs),
|
||||
Stat::Stamina => {
|
||||
self.stamina.set(rng.gen_range(stam_min, stam_max), &self.specs);
|
||||
self.hp.set(self.stamina.base, &self.specs)
|
||||
},
|
||||
Stat::SpellShield => self.spell_shield.set(rng.gen_range(stat_min, stat_max), &self.specs),
|
||||
Stat::Armour => self.armour.set(rng.gen_range(stat_min, stat_max), &self.specs),
|
||||
Stat::BlueShield => self.blue_shield.set(rng.gen_range(stat_min, stat_max), &self.specs),
|
||||
Stat::RedShield => self.red_shield.set(rng.gen_range(stat_min, stat_max), &self.specs),
|
||||
Stat::Evasion => self.evasion.set(rng.gen_range(evasion_min, evasion_max), &self.specs),
|
||||
_ => panic!("{:?} not a rollable stat", stat),
|
||||
};
|
||||
@ -262,8 +262,8 @@ impl Cryp {
|
||||
|
||||
self.xp = xp;
|
||||
|
||||
self.roll_stat(Stat::PhysicalDamage);
|
||||
self.roll_stat(Stat::SpellDamage);
|
||||
self.roll_stat(Stat::RedDamage);
|
||||
self.roll_stat(Stat::BlueDamage);
|
||||
self.roll_stat(Stat::Speed);
|
||||
self.roll_stat(Stat::Stamina);
|
||||
|
||||
@ -306,7 +306,7 @@ impl Cryp {
|
||||
return Ok(self.recalculate_stats());
|
||||
}
|
||||
|
||||
pub fn spec_remove(mut self, spec: Spec) -> Result<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 spec.level {
|
||||
@ -324,18 +324,18 @@ impl Cryp {
|
||||
},
|
||||
};
|
||||
|
||||
Ok(self)
|
||||
Ok(self.recalculate_stats())
|
||||
}
|
||||
|
||||
|
||||
fn recalculate_stats(&mut self) -> &mut Cryp {
|
||||
self.stamina.recalculate(&self.specs);
|
||||
self.hp.recalculate(&self.specs);
|
||||
self.phys_dmg.recalculate(&self.specs);
|
||||
self.spell_dmg.recalculate(&self.specs);
|
||||
self.red_damage.recalculate(&self.specs);
|
||||
self.red_shield.recalculate(&self.specs);
|
||||
self.blue_damage.recalculate(&self.specs);
|
||||
self.blue_shield.recalculate(&self.specs);
|
||||
self.evasion.recalculate(&self.specs);
|
||||
self.armour.recalculate(&self.specs);
|
||||
self.spell_shield.recalculate(&self.specs);
|
||||
self.speed.recalculate(&self.specs);
|
||||
|
||||
self
|
||||
@ -468,24 +468,24 @@ impl Cryp {
|
||||
// }
|
||||
|
||||
// Stats
|
||||
pub fn phys_dmg(&self) -> u64 {
|
||||
let phys_dmg_mods = self.effects.iter()
|
||||
.filter(|e| e.effect.modifications().contains(&Stat::PhysicalDamage))
|
||||
pub fn red_damage(&self) -> u64 {
|
||||
let red_damage_mods = self.effects.iter()
|
||||
.filter(|e| e.effect.modifications().contains(&Stat::RedDamage))
|
||||
.map(|cryp_effect| cryp_effect.effect)
|
||||
.collect::<Vec<Effect>>();
|
||||
|
||||
let modified_phys_dmg = phys_dmg_mods.iter().fold(self.phys_dmg.value, |acc, m| m.apply(acc));
|
||||
return modified_phys_dmg;
|
||||
let modified_red_damage = red_damage_mods.iter().fold(self.red_damage.value, |acc, m| m.apply(acc));
|
||||
return modified_red_damage;
|
||||
}
|
||||
|
||||
pub fn spell_dmg(&self) -> u64 {
|
||||
let spell_dmg_mods = self.effects.iter()
|
||||
.filter(|e| e.effect.modifications().contains(&Stat::SpellDamage))
|
||||
pub fn blue_damage(&self) -> u64 {
|
||||
let blue_damage_mods = self.effects.iter()
|
||||
.filter(|e| e.effect.modifications().contains(&Stat::BlueDamage))
|
||||
.map(|cryp_effect| cryp_effect.effect)
|
||||
.collect::<Vec<Effect>>();
|
||||
|
||||
let modified_spell_dmg = spell_dmg_mods.iter().fold(self.spell_dmg.value, |acc, m| m.apply(acc));
|
||||
return modified_spell_dmg;
|
||||
let modified_blue_damage = blue_damage_mods.iter().fold(self.blue_damage.value, |acc, m| m.apply(acc));
|
||||
return modified_blue_damage;
|
||||
}
|
||||
|
||||
pub fn skill_speed(&self, s: Skill) -> u64 {
|
||||
@ -518,7 +518,7 @@ impl Cryp {
|
||||
ResolutionResult::Healing {
|
||||
amount: 0,
|
||||
overhealing: 0,
|
||||
category: Category::PhysHeal,
|
||||
category: Category::RedHeal,
|
||||
immunity: immunity.clone(),
|
||||
};
|
||||
}
|
||||
@ -546,12 +546,12 @@ impl Cryp {
|
||||
return ResolutionResult::Healing {
|
||||
amount: healing,
|
||||
overhealing,
|
||||
category: Category::PhysHeal,
|
||||
category: Category::RedHeal,
|
||||
immunity,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deal_phys_dmg(&mut self, skill: Skill, amount: u64) -> ResolutionResult {
|
||||
pub fn deal_red_damage(&mut self, skill: Skill, amount: u64) -> ResolutionResult {
|
||||
let immunity = self.immune(skill);
|
||||
let immune = immunity.immune;
|
||||
|
||||
@ -559,29 +559,29 @@ impl Cryp {
|
||||
return ResolutionResult::Damage {
|
||||
amount: 0,
|
||||
mitigation: 0,
|
||||
category: Category::PhysDmg,
|
||||
category: Category::RedDamage,
|
||||
immunity,
|
||||
};
|
||||
}
|
||||
|
||||
let phys_dmg_mods = self.effects.iter()
|
||||
.filter(|e| e.effect.modifications().contains(&Stat::PhysicalDamageTaken))
|
||||
let red_damage_mods = self.effects.iter()
|
||||
.filter(|e| e.effect.modifications().contains(&Stat::RedDamageTaken))
|
||||
.map(|cryp_effect| cryp_effect.effect)
|
||||
.collect::<Vec<Effect>>();
|
||||
|
||||
// println!("{:?}", phys_dmg_mods);
|
||||
// println!("{:?}", red_damage_mods);
|
||||
|
||||
let modified_dmg = phys_dmg_mods.iter().fold(amount, |acc, m| m.apply(acc));
|
||||
let modified_damage = red_damage_mods.iter().fold(amount, |acc, m| m.apply(acc));
|
||||
|
||||
// calculate amount of damage armour will not absorb
|
||||
// eg 50 armour 25 dmg -> 0 remainder 25 mitigation
|
||||
// 50 armour 100 dmg -> 50 remainder 50 mitigation
|
||||
// 50 armour 5 dmg -> 0 remainder 5 mitigation
|
||||
let remainder = modified_dmg.saturating_sub(self.armour.value);
|
||||
let mitigation = modified_dmg.saturating_sub(remainder);
|
||||
// calculate amount of damage red_shield will not absorb
|
||||
// eg 50 red_shield 25 damage -> 0 remainder 25 mitigation
|
||||
// 50 red_shield 100 damage -> 50 remainder 50 mitigation
|
||||
// 50 red_shield 5 damage -> 0 remainder 5 mitigation
|
||||
let remainder = modified_damage.saturating_sub(self.red_shield.value);
|
||||
let mitigation = modified_damage.saturating_sub(remainder);
|
||||
|
||||
// reduce armour by mitigation amount
|
||||
self.armour.reduce(mitigation);
|
||||
// reduce red_shield by mitigation amount
|
||||
self.red_shield.reduce(mitigation);
|
||||
|
||||
// deal remainder to hp
|
||||
self.hp.reduce(remainder);
|
||||
@ -589,12 +589,12 @@ impl Cryp {
|
||||
return ResolutionResult::Damage {
|
||||
amount: remainder,
|
||||
mitigation,
|
||||
category: Category::PhysDmg,
|
||||
category: Category::RedDamage,
|
||||
immunity,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deal_spell_dmg(&mut self, skill: Skill, amount: u64) -> ResolutionResult {
|
||||
pub fn deal_blue_damage(&mut self, skill: Skill, amount: u64) -> ResolutionResult {
|
||||
let immunity = self.immune(skill);
|
||||
let immune = immunity.immune;
|
||||
|
||||
@ -602,29 +602,29 @@ impl Cryp {
|
||||
return ResolutionResult::Damage {
|
||||
amount: 0,
|
||||
mitigation: 0,
|
||||
category: Category::SpellDmg,
|
||||
category: Category::BlueDamage,
|
||||
immunity,
|
||||
};
|
||||
}
|
||||
|
||||
let spell_dmg_mods = self.effects.iter()
|
||||
.filter(|e| e.effect.modifications().contains(&Stat::SpellDamageTaken))
|
||||
let blue_damage_mods = self.effects.iter()
|
||||
.filter(|e| e.effect.modifications().contains(&Stat::BlueDamageTaken))
|
||||
.map(|cryp_effect| cryp_effect.effect)
|
||||
.collect::<Vec<Effect>>();
|
||||
|
||||
// println!("{:?}", spell_dmg_mods);
|
||||
// println!("{:?}", blue_damage_mods);
|
||||
|
||||
let modified_dmg = spell_dmg_mods.iter().fold(amount, |acc, m| m.apply(acc));
|
||||
let remainder = modified_dmg.saturating_sub(self.armour.value);
|
||||
let mitigation = modified_dmg.saturating_sub(remainder);
|
||||
let modified_damage = blue_damage_mods.iter().fold(amount, |acc, m| m.apply(acc));
|
||||
let remainder = modified_damage.saturating_sub(self.blue_shield.value);
|
||||
let mitigation = modified_damage.saturating_sub(remainder);
|
||||
|
||||
self.armour.reduce(mitigation);
|
||||
self.blue_shield.reduce(mitigation);
|
||||
self.hp.reduce(remainder);
|
||||
|
||||
return ResolutionResult::Damage {
|
||||
amount: remainder,
|
||||
mitigation,
|
||||
category: Category::SpellDmg,
|
||||
category: Category::BlueDamage,
|
||||
immunity,
|
||||
};
|
||||
}
|
||||
@ -734,7 +734,7 @@ pub fn cryp_forget(params: CrypForgetParams, tx: &mut Transaction, account: &Acc
|
||||
|
||||
pub fn cryp_unspec(params: CrypUnspecParams, tx: &mut Transaction, account: &Account) -> Result<Cryp, Error> {
|
||||
let mut cryp = cryp_get(tx, params.id, account.id)?;
|
||||
cryp = cryp.spec_remove(params.spec)?;
|
||||
cryp.spec_remove(params.spec)?;
|
||||
return cryp_write(cryp, tx);
|
||||
}
|
||||
|
||||
|
||||
@ -11,7 +11,6 @@ use account::Account;
|
||||
use rpc::{GameStateParams, GameSkillParams, GamePveParams, GamePvpParams, GameJoinParams};
|
||||
use cryp::{Cryp, cryp_get};
|
||||
use skill::{Skill, Cast, ResolutionResult};
|
||||
use item::{item_drop};
|
||||
use zone::{node_finish};
|
||||
use mob::{generate_mob_team};
|
||||
|
||||
@ -685,12 +684,6 @@ pub fn game_update(game: &Game, tx: &mut Transaction) -> Result<(), Error> {
|
||||
result.iter().next().ok_or(format_err!("game {:?} could not be written", game))?;
|
||||
|
||||
if game.finished() {
|
||||
if let Some(t) = game.winner() {
|
||||
if !t.id.is_nil() {
|
||||
item_drop(tx, t.id, game.mode)?;
|
||||
}
|
||||
}
|
||||
|
||||
// check for zone update
|
||||
if let Some((z, i)) = game.zone {
|
||||
node_finish(game, z, i, tx)?;
|
||||
@ -854,7 +847,7 @@ mod tests {
|
||||
.learn(Skill::TestTouch)
|
||||
.learn(Skill::TestBlock)
|
||||
.learn(Skill::TestParry)
|
||||
.learn(Skill::TestDrain)
|
||||
.learn(Skill::TestSiphon)
|
||||
.learn(Skill::Empower)
|
||||
.learn(Skill::Stun)
|
||||
.learn(Skill::Block)
|
||||
@ -868,7 +861,7 @@ mod tests {
|
||||
.learn(Skill::TestTouch)
|
||||
.learn(Skill::TestBlock)
|
||||
.learn(Skill::TestParry)
|
||||
.learn(Skill::TestDrain)
|
||||
.learn(Skill::TestSiphon)
|
||||
.learn(Skill::Empower)
|
||||
.learn(Skill::Stun)
|
||||
.learn(Skill::Block)
|
||||
@ -1014,12 +1007,12 @@ mod tests {
|
||||
let x_cryp = x_team.cryps[0].clone();
|
||||
let y_cryp = y_team.cryps[0].clone();
|
||||
|
||||
game.team_by_id(y_team.id).cryp_by_id(y_cryp.id).unwrap().phys_dmg.force(u64::max_value());
|
||||
game.team_by_id(y_team.id).cryp_by_id(y_cryp.id).unwrap().red_damage.force(u64::max_value());
|
||||
game.team_by_id(y_team.id).cryp_by_id(y_cryp.id).unwrap().speed.force(u64::max_value());
|
||||
|
||||
// just in case
|
||||
// remove all mitigation
|
||||
game.team_by_id(x_team.id).cryp_by_id(x_cryp.id).unwrap().armour.force(0);
|
||||
game.team_by_id(x_team.id).cryp_by_id(x_cryp.id).unwrap().red_shield.force(0);
|
||||
|
||||
let _x_stun_id = game.add_skill(x_team.id, x_cryp.id, Some(y_cryp.id), Skill::TestStun).unwrap();
|
||||
game.add_skill(y_team.id, y_cryp.id, Some(x_cryp.id), Skill::Attack).unwrap();
|
||||
@ -1088,7 +1081,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn drain_test() {
|
||||
fn siphon_test() {
|
||||
let mut game = create_test_game();
|
||||
|
||||
let x_team = game.teams[0].clone();
|
||||
@ -1097,7 +1090,7 @@ mod tests {
|
||||
let x_cryp = x_team.cryps[0].clone();
|
||||
let y_cryp = y_team.cryps[0].clone();
|
||||
|
||||
let _x_drain_id = game.add_skill(x_team.id, x_cryp.id, Some(y_cryp.id), Skill::TestDrain).unwrap();
|
||||
let _x_siphon_id = game.add_skill(x_team.id, x_cryp.id, Some(y_cryp.id), Skill::TestSiphon).unwrap();
|
||||
let _y_touch_id = game.add_skill(y_team.id, y_cryp.id, Some(x_cryp.id), Skill::TestTouch).unwrap();
|
||||
|
||||
game.resolve_phase_start();
|
||||
@ -1107,7 +1100,7 @@ mod tests {
|
||||
|
||||
game.resolve_phase_start();
|
||||
|
||||
assert!(game.resolved.iter().any(|r| r.skill == Skill::DrainTick));
|
||||
assert!(game.resolved.iter().any(|r| r.skill == Skill::SiphonTick));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@ -938,7 +938,7 @@ mod tests {
|
||||
.learn(Skill::TestTouch)
|
||||
.learn(Skill::TestBlock)
|
||||
.learn(Skill::TestParry)
|
||||
.learn(Skill::TestDrain)
|
||||
.learn(Skill::TestSiphon)
|
||||
.learn(Skill::Empower)
|
||||
.learn(Skill::Block)
|
||||
.create();
|
||||
@ -950,7 +950,7 @@ mod tests {
|
||||
.learn(Skill::TestTouch)
|
||||
.learn(Skill::TestBlock)
|
||||
.learn(Skill::TestParry)
|
||||
.learn(Skill::TestDrain)
|
||||
.learn(Skill::TestSiphon)
|
||||
.learn(Skill::Empower)
|
||||
.learn(Skill::Block)
|
||||
.create();
|
||||
@ -1104,7 +1104,7 @@ mod tests {
|
||||
let x_cryp = x_team.cryps[0].clone();
|
||||
let y_cryp = y_team.cryps[0].clone();
|
||||
|
||||
game.team_by_id(y_team.id).cryp_by_id(y_cryp.id).unwrap().phys_dmg.set(u64::max_value());
|
||||
game.team_by_id(y_team.id).cryp_by_id(y_cryp.id).unwrap().red_damage.set(u64::max_value());
|
||||
|
||||
let x_stun_id = game.add_skill(x_team.id, x_cryp.id, Some(y_team.id), Skill::TestStun).unwrap();
|
||||
let y_attack_id = game.add_skill(y_team.id, y_cryp.id, Some(x_team.id), Skill::Attack).unwrap();
|
||||
@ -1194,7 +1194,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn drain_test() {
|
||||
fn siphon_test() {
|
||||
let mut game = create_test_game();
|
||||
|
||||
let x_team = game.teams[0].clone();
|
||||
@ -1203,13 +1203,13 @@ mod tests {
|
||||
let x_cryp = x_team.cryps[0].clone();
|
||||
let y_cryp = y_team.cryps[0].clone();
|
||||
|
||||
let x_drain_id = game.add_skill(x_team.id, x_cryp.id, Some(y_team.id), Skill::TestDrain).unwrap();
|
||||
let x_siphon_id = game.add_skill(x_team.id, x_cryp.id, Some(y_team.id), Skill::TestSiphon).unwrap();
|
||||
let y_touch_id = game.add_skill(y_team.id, y_cryp.id, Some(x_team.id), Skill::TestTouch).unwrap();
|
||||
|
||||
game.target_phase_start();
|
||||
|
||||
game.add_target(x_team.id, x_cryp.id, y_touch_id).unwrap();
|
||||
game.add_target(y_team.id, y_cryp.id, x_drain_id).unwrap();
|
||||
game.add_target(y_team.id, y_cryp.id, x_siphon_id).unwrap();
|
||||
|
||||
game.resolve_phase_start();
|
||||
|
||||
@ -1218,7 +1218,7 @@ mod tests {
|
||||
|
||||
game.target_phase_start();
|
||||
|
||||
assert!(game.resolved.iter().any(|r| r.skill == Skill::DrainTick));
|
||||
assert!(game.resolved.iter().any(|r| r.skill == Skill::SiphonTick));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@ -17,19 +17,19 @@ use spec::{Spec, SpecType};
|
||||
|
||||
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
||||
pub enum ItemAction {
|
||||
RerollPhysDamage,
|
||||
RerollSpellDamage,
|
||||
RerollRedDamage,
|
||||
RerollBlueDamage,
|
||||
RerollSpeed,
|
||||
RerollStamina,
|
||||
RerollArmour,
|
||||
RerollSpellShield,
|
||||
RerollRedShield,
|
||||
RerollBlueShield,
|
||||
RerollEvasion,
|
||||
|
||||
SpecPhysDmg5,
|
||||
SpecSpellDmg5,
|
||||
SpecArmour5,
|
||||
SpecSpellShield5,
|
||||
SpecSpellEvasion5,
|
||||
SpecRedDamage5,
|
||||
SpecBlueDamage5,
|
||||
SpecRedShield5,
|
||||
SpecBlueShield5,
|
||||
SpecBlueEvasion5,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
||||
@ -44,24 +44,24 @@ impl Item {
|
||||
pub fn new(action: ItemAction, account_id: Uuid) -> Item {
|
||||
let id = Uuid::new_v4();
|
||||
return Item {
|
||||
id,
|
||||
account: account_id,
|
||||
action,
|
||||
id,
|
||||
account: account_id,
|
||||
action,
|
||||
};
|
||||
}
|
||||
|
||||
fn apply(&mut self, tx: &mut Transaction, target: Uuid) -> Result<(), Error> {
|
||||
match self.action {
|
||||
ItemAction::RerollStamina => reroll(self, tx, target, Stat::Stamina),
|
||||
ItemAction::RerollPhysDamage => reroll(self, tx, target, Stat::PhysicalDamage),
|
||||
ItemAction::RerollSpellDamage => reroll(self, tx, target, Stat::SpellDamage),
|
||||
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::RerollArmour => reroll(self, tx, target, Stat::Armour),
|
||||
ItemAction::RerollSpellShield => reroll(self, tx, target, Stat::SpellShield),
|
||||
ItemAction::RerollRedShield => reroll(self, tx, target, Stat::RedShield),
|
||||
ItemAction::RerollBlueShield => reroll(self, tx, target, Stat::BlueShield),
|
||||
ItemAction::RerollEvasion => reroll(self, tx, target, Stat::Evasion),
|
||||
|
||||
ItemAction::SpecPhysDmg5 => spec_add(self, tx, target, SpecType::PhysDamage5),
|
||||
ItemAction::SpecSpellDmg5 => spec_add(self, tx, target, SpecType::SpellDamage5),
|
||||
ItemAction::SpecRedDamage5 => spec_add(self, tx, target, SpecType::RedDamage5),
|
||||
ItemAction::SpecBlueDamage5 => spec_add(self, tx, target, SpecType::BlueDamage5),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
@ -86,8 +86,8 @@ fn mode_drops(mode: GameMode) -> Vec<(ItemAction, usize)> {
|
||||
match mode {
|
||||
GameMode::Normal => vec![
|
||||
(ItemAction::RerollStamina, 1),
|
||||
(ItemAction::RerollPhysDamage, 1),
|
||||
(ItemAction::RerollSpellDamage, 1),
|
||||
(ItemAction::RerollRedDamage, 1),
|
||||
(ItemAction::RerollBlueDamage, 1),
|
||||
],
|
||||
GameMode::Pvp => vec![
|
||||
(ItemAction::RerollSpeed, 1),
|
||||
@ -96,19 +96,19 @@ fn mode_drops(mode: GameMode) -> Vec<(ItemAction, usize)> {
|
||||
GameMode::Zone2v2Caster |
|
||||
GameMode::Zone3v3MeleeMiniboss => vec![
|
||||
(ItemAction::RerollEvasion, 1),
|
||||
(ItemAction::RerollArmour, 1),
|
||||
(ItemAction::RerollSpellShield, 1),
|
||||
(ItemAction::RerollRedShield, 1),
|
||||
(ItemAction::RerollBlueShield, 1),
|
||||
],
|
||||
GameMode::Zone3v3HealerBoss => vec![
|
||||
(ItemAction::RerollSpeed, 1),
|
||||
],
|
||||
// _ => vec![
|
||||
// (ItemAction::RerollStamina, 1),
|
||||
// (ItemAction::RerollPhysDamage, 1),
|
||||
// (ItemAction::RerollSpellDamage, 1),
|
||||
// (ItemAction::RerollRedDamage, 1),
|
||||
// (ItemAction::RerollBlueDamage, 1),
|
||||
// (ItemAction::RerollSpeed, 1),
|
||||
// (ItemAction::RerollArmour, 1),
|
||||
// (ItemAction::RerollSpellShield, 1),
|
||||
// (ItemAction::RerollRedShield, 1),
|
||||
// (ItemAction::RerollBlueShield, 1),
|
||||
// (ItemAction::RerollEvasion, 1),
|
||||
// ],
|
||||
}
|
||||
|
||||
@ -26,10 +26,12 @@ mod spec;
|
||||
// mod passives;
|
||||
mod rpc;
|
||||
mod account;
|
||||
mod item;
|
||||
// mod item;
|
||||
mod zone;
|
||||
mod mob;
|
||||
|
||||
mod vbox;
|
||||
|
||||
use dotenv::dotenv;
|
||||
use net::{start};
|
||||
|
||||
|
||||
@ -18,10 +18,10 @@ use net::Db;
|
||||
use cryp::{Cryp, cryp_spawn, cryp_learn, cryp_forget, cryp_unspec};
|
||||
use game::{Game, game_state, game_pve, game_pvp, game_join, game_joinable_list, game_skill};
|
||||
use account::{Account, account_create, account_login, account_from_token, account_cryps, account_zone};
|
||||
use item::{Item, ItemAction, items_list, item_use, item_create};
|
||||
use skill::{Skill};
|
||||
use zone::{Zone, zone_create, zone_join, zone_close};
|
||||
use spec::{Spec};
|
||||
use vbox::{Vbox, vbox_state, vbox_accept, vbox_apply, vbox_discard, vbox_combine, vbox_drop};
|
||||
|
||||
pub struct Rpc;
|
||||
|
||||
@ -76,11 +76,14 @@ impl Rpc {
|
||||
"zone_join" => Rpc::zone_join(data, &mut tx, account.unwrap(), client),
|
||||
"zone_close" => Rpc::zone_close(data, &mut tx, account.unwrap(), client),
|
||||
"account_cryps" => Rpc::account_cryps(data, &mut tx, account.unwrap(), client),
|
||||
"account_items" => Rpc::account_items(data, &mut tx, account.unwrap(), client),
|
||||
"account_zone" => Rpc::account_zone(data, &mut tx, account.unwrap(), client),
|
||||
"item_use" => Rpc::item_use(data, &mut tx, account.unwrap(), client),
|
||||
|
||||
"press_r" => Rpc::press_r(data, &mut tx, account.unwrap(), client),
|
||||
"vbox_state" => Rpc::vbox_state(data, &mut tx, account.unwrap(), client),
|
||||
"vbox_accept" => Rpc::vbox_accept(data, &mut tx, account.unwrap(), client),
|
||||
"vbox_apply" => Rpc::vbox_apply(data, &mut tx, account.unwrap(), client),
|
||||
"vbox_drop" => Rpc::vbox_drop(data, &mut tx, account.unwrap(), client),
|
||||
"vbox_combine" => Rpc::vbox_combine(data, &mut tx, account.unwrap(), client),
|
||||
"vbox_discard" => Rpc::vbox_discard(data, &mut tx, account.unwrap(), client),
|
||||
|
||||
_ => Err(format_err!("unknown method - {:?}", v.method)),
|
||||
};
|
||||
@ -251,8 +254,6 @@ impl Rpc {
|
||||
Ok(cryp_list)
|
||||
}
|
||||
|
||||
|
||||
|
||||
fn account_create(data: Vec<u8>, tx: &mut Transaction, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
match from_slice::<AccountCreateMsg>(&data) {
|
||||
Ok(v) => Ok(RpcResponse {
|
||||
@ -290,7 +291,7 @@ impl Rpc {
|
||||
let cryp = cryp_spawn(CrypSpawnParams { name }, tx, &account)?;
|
||||
cryp_learn(CrypLearnParams { id: cryp.id, skill: Skill::Decay }, tx, &account)?;
|
||||
cryp_learn(CrypLearnParams { id: cryp.id, skill: Skill::Blast }, tx, &account)?;
|
||||
cryp_learn(CrypLearnParams { id: cryp.id, skill: Skill::Drain }, tx, &account)?;
|
||||
cryp_learn(CrypLearnParams { id: cryp.id, skill: Skill::Siphon }, tx, &account)?;
|
||||
|
||||
let name: String = iter::repeat(()).map(|()| rng.sample(Alphanumeric)).take(8).collect();
|
||||
let cryp = cryp_spawn(CrypSpawnParams { name }, tx, &account)?;
|
||||
@ -314,13 +315,6 @@ impl Rpc {
|
||||
})
|
||||
}
|
||||
|
||||
fn account_items(_data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
Ok(RpcResponse {
|
||||
method: "account_items".to_string(),
|
||||
params: RpcResult::ItemList(items_list(tx, &account)?)
|
||||
})
|
||||
}
|
||||
|
||||
fn account_zone(_data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
Ok(RpcResponse {
|
||||
method: "zone_state".to_string(),
|
||||
@ -328,49 +322,6 @@ impl Rpc {
|
||||
})
|
||||
}
|
||||
|
||||
fn press_r(_data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
for action in [
|
||||
ItemAction::RerollPhysDamage,
|
||||
ItemAction::RerollSpellDamage,
|
||||
ItemAction::RerollSpeed,
|
||||
ItemAction::RerollStamina,
|
||||
ItemAction::RerollArmour,
|
||||
ItemAction::RerollSpellShield,
|
||||
ItemAction::RerollEvasion,
|
||||
ItemAction::SpecPhysDmg5,
|
||||
ItemAction::SpecSpellDmg5,
|
||||
].into_iter() {
|
||||
let item = Item::new(*action, account.id);
|
||||
item_create(item, tx, account.id)?;
|
||||
}
|
||||
|
||||
let res = RpcResponse {
|
||||
method: "account_items".to_string(),
|
||||
params: RpcResult::ItemList(items_list(tx, &account)?)
|
||||
};
|
||||
|
||||
return Ok(res);
|
||||
}
|
||||
|
||||
|
||||
fn item_use(data: Vec<u8>, tx: &mut Transaction, account: Account, client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
let msg = from_slice::<ItemUseMsg>(&data).or(Err(err_msg("invalid params")))?;
|
||||
|
||||
item_use(msg.params, tx, &account)?;
|
||||
|
||||
Rpc::send_msg(client, RpcResponse {
|
||||
method: "account_items".to_string(),
|
||||
params: RpcResult::ItemList(items_list(tx, &account)?)
|
||||
})?;
|
||||
|
||||
let cryps_list = RpcResponse {
|
||||
method: "account_cryps".to_string(),
|
||||
params: RpcResult::CrypList(account_cryps(tx, &account)?)
|
||||
};
|
||||
|
||||
return Ok(cryps_list);
|
||||
}
|
||||
|
||||
fn zone_create(_data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
// let _msg = from_slice::<ZoneCreateMsg>(&data).or(Err(err_msg("invalid params")))?;
|
||||
|
||||
@ -404,6 +355,77 @@ impl Rpc {
|
||||
return Ok(response);
|
||||
}
|
||||
|
||||
fn vbox_state(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
let msg = from_slice::<VboxStateMsg>(&data).or(Err(err_msg("invalid params")))?;
|
||||
|
||||
let response = RpcResponse {
|
||||
method: "vbox_state".to_string(),
|
||||
params: RpcResult::VboxState(vbox_state(msg.params, tx, &account)?)
|
||||
};
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
|
||||
fn vbox_accept(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
let msg = from_slice::<VboxAcceptMsg>(&data).or(Err(err_msg("invalid params")))?;
|
||||
|
||||
let response = RpcResponse {
|
||||
method: "vbox_state".to_string(),
|
||||
params: RpcResult::VboxState(vbox_accept(msg.params, tx, &account)?)
|
||||
};
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
|
||||
fn vbox_discard(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
let msg = from_slice::<VboxDiscardMsg>(&data).or(Err(err_msg("invalid params")))?;
|
||||
|
||||
let response = RpcResponse {
|
||||
method: "vbox_state".to_string(),
|
||||
params: RpcResult::VboxState(vbox_discard(msg.params, tx, &account)?)
|
||||
};
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
|
||||
|
||||
fn vbox_combine(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
let msg = from_slice::<VboxCombineMsg>(&data).or(Err(err_msg("invalid params")))?;
|
||||
|
||||
let response = RpcResponse {
|
||||
method: "vbox_state".to_string(),
|
||||
params: RpcResult::VboxState(vbox_combine(msg.params, tx, &account)?)
|
||||
};
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
|
||||
fn vbox_apply(data: Vec<u8>, tx: &mut Transaction, account: Account, client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
let msg = from_slice::<VboxApplyMsg>(&data).or(Err(err_msg("invalid params")))?;
|
||||
|
||||
let response = RpcResponse {
|
||||
method: "vbox_state".to_string(),
|
||||
params: RpcResult::VboxState(vbox_apply(msg.params, tx, &account)?)
|
||||
};
|
||||
|
||||
Rpc::send_msg(client, RpcResponse {
|
||||
method: "account_cryps".to_string(),
|
||||
params: RpcResult::CrypList(account_cryps(tx, &account)?)
|
||||
})?;
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
|
||||
fn vbox_drop(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
let msg = from_slice::<VboxDropMsg>(&data).or(Err(err_msg("invalid params")))?;
|
||||
|
||||
let response = RpcResponse {
|
||||
method: "vbox_state".to_string(),
|
||||
params: RpcResult::VboxState(vbox_drop(msg.params, tx, &account)?)
|
||||
};
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
@ -422,10 +444,10 @@ pub enum RpcResult {
|
||||
CrypList(Vec<Cryp>),
|
||||
GameState(Game),
|
||||
GameJoinableList(Vec<Game>),
|
||||
ItemList(Vec<Item>),
|
||||
ItemUse(()),
|
||||
ZoneState(Zone),
|
||||
ZoneClose(()),
|
||||
|
||||
VboxState(Vbox),
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
@ -589,24 +611,6 @@ struct AccountCrypsMsg {
|
||||
params: (),
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
struct ItemListMsg {
|
||||
method: String,
|
||||
params: (),
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
struct ItemUseMsg {
|
||||
method: String,
|
||||
params: ItemUseParams,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
pub struct ItemUseParams {
|
||||
pub item: Uuid,
|
||||
pub target: Uuid,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
struct ZoneCreateMsg {
|
||||
method: String,
|
||||
@ -637,6 +641,76 @@ pub struct ZoneCloseParams {
|
||||
pub zone_id: Uuid,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
struct VboxStateMsg {
|
||||
method: String,
|
||||
params: VboxStateParams,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
pub struct VboxStateParams {
|
||||
pub game_id: Uuid,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
struct VboxAcceptMsg {
|
||||
method: String,
|
||||
params: VboxAcceptParams,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
pub struct VboxAcceptParams {
|
||||
pub game_id: Uuid,
|
||||
pub index: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
struct VboxDiscardMsg {
|
||||
method: String,
|
||||
params: VboxDiscardParams,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
pub struct VboxDiscardParams {
|
||||
pub game_id: Uuid,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
struct VboxCombineMsg {
|
||||
method: String,
|
||||
params: VboxCombineParams,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
pub struct VboxCombineParams {
|
||||
pub game_id: Uuid,
|
||||
pub indices: Vec<usize>,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
struct VboxApplyMsg {
|
||||
method: String,
|
||||
params: VboxApplyParams,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
pub struct VboxApplyParams {
|
||||
pub game_id: Uuid,
|
||||
pub cryp_id: Uuid,
|
||||
pub index: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
struct VboxDropMsg {
|
||||
method: String,
|
||||
params: VboxDropParams,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
pub struct VboxDropParams {
|
||||
pub game_id: Uuid,
|
||||
pub index: usize,
|
||||
}
|
||||
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
|
||||
@ -125,9 +125,9 @@ pub enum Effect {
|
||||
Triage,
|
||||
Decay,
|
||||
Regen,
|
||||
Drain,
|
||||
Siphon,
|
||||
|
||||
SpeedDrain,
|
||||
SpeedSiphon,
|
||||
SpeedIncrease,
|
||||
|
||||
Ko,
|
||||
@ -137,13 +137,13 @@ impl Effect {
|
||||
pub fn immune(&self, skill: Skill) -> bool {
|
||||
match self {
|
||||
Effect::Parry => match skill.category() {
|
||||
Category::Spell => false,
|
||||
Category::Physical => true,
|
||||
Category::Blue => false,
|
||||
Category::Red => true,
|
||||
_ => false,
|
||||
},
|
||||
Effect::Shield => match skill.category() {
|
||||
Category::Spell => true,
|
||||
Category::Physical => false,
|
||||
Category::Blue => true,
|
||||
Category::Red => false,
|
||||
_ => false,
|
||||
},
|
||||
Effect::Banish => true,
|
||||
@ -157,18 +157,18 @@ impl Effect {
|
||||
Effect::Hex => true,
|
||||
Effect::Banish => true,
|
||||
Effect::Silence => match skill.category() {
|
||||
Category::Spell => true,
|
||||
Category::Physical => false,
|
||||
Category::Blue => true,
|
||||
Category::Red => false,
|
||||
_ => false,
|
||||
},
|
||||
Effect::Snare => match skill.category() {
|
||||
Category::Spell => false,
|
||||
Category::Physical => true,
|
||||
Category::Blue => false,
|
||||
Category::Red => true,
|
||||
_ => false,
|
||||
},
|
||||
|
||||
Effect::Ko => match skill.category() {
|
||||
Category::SpellTick => false,
|
||||
Category::BlueTick => false,
|
||||
_ => true,
|
||||
},
|
||||
_ => false,
|
||||
@ -177,12 +177,12 @@ impl Effect {
|
||||
|
||||
pub fn modifications(&self) -> Vec<Stat> {
|
||||
match self {
|
||||
Effect::Empower => vec![Stat::PhysicalDamage],
|
||||
Effect::Vulnerable => vec![Stat::PhysicalDamageTaken],
|
||||
Effect::Block => vec![Stat::PhysicalDamageTaken],
|
||||
Effect::Empower => vec![Stat::RedDamage],
|
||||
Effect::Vulnerable => vec![Stat::RedDamageTaken],
|
||||
Effect::Block => vec![Stat::RedDamageTaken],
|
||||
|
||||
Effect::Amplify => vec![Stat::SpellDamage],
|
||||
Effect::Curse => vec![Stat::SpellDamageTaken],
|
||||
Effect::Amplify => vec![Stat::BlueDamage],
|
||||
Effect::Curse => vec![Stat::BlueDamageTaken],
|
||||
|
||||
Effect::Haste => vec![Stat::Speed],
|
||||
Effect::Slow => vec![Stat::Speed],
|
||||
@ -216,43 +216,43 @@ impl Effect {
|
||||
pub fn category(&self) -> Category {
|
||||
match self {
|
||||
// physical
|
||||
Effect::Stun => Category::PhysDebuff,
|
||||
Effect::Block => Category::PhysBuff,
|
||||
Effect::Parry => Category::PhysBuff,
|
||||
Effect::Bleed => Category::PhysDebuff,
|
||||
Effect::Leech => Category::PhysDebuff,
|
||||
Effect::Airborne => Category::PhysDebuff,
|
||||
Effect::Untouchable => Category::PhysBuff,
|
||||
Effect::Deadly => Category::PhysBuff,
|
||||
Effect::Vulnerable => Category::PhysDebuff,
|
||||
Effect::Fury => Category::PhysBuff,
|
||||
Effect::Blind => Category::PhysDebuff,
|
||||
Effect::Snare => Category::PhysDebuff,
|
||||
Effect::Stun => Category::RedDebuff,
|
||||
Effect::Block => Category::RedBuff,
|
||||
Effect::Parry => Category::RedBuff,
|
||||
Effect::Bleed => Category::RedDebuff,
|
||||
Effect::Leech => Category::RedDebuff,
|
||||
Effect::Airborne => Category::RedDebuff,
|
||||
Effect::Untouchable => Category::RedBuff,
|
||||
Effect::Deadly => Category::RedBuff,
|
||||
Effect::Vulnerable => Category::RedDebuff,
|
||||
Effect::Fury => Category::RedBuff,
|
||||
Effect::Blind => Category::RedDebuff,
|
||||
Effect::Snare => Category::RedDebuff,
|
||||
|
||||
Effect::Empower => Category::PhysBuff,
|
||||
Effect::Empower => Category::RedBuff,
|
||||
|
||||
// magic
|
||||
Effect::Hex => Category::SpellDebuff,
|
||||
Effect::Curse => Category::SpellDebuff,
|
||||
Effect::Banish => Category::SpellDebuff, // todo randomise
|
||||
Effect::Slow => Category::SpellDebuff,
|
||||
Effect::Haste => Category::SpellBuff,
|
||||
Effect::Enslave => Category::SpellDebuff,
|
||||
Effect::Mesmerise => Category::SpellDebuff,
|
||||
Effect::Amplify => Category::SpellBuff,
|
||||
Effect::Silence => Category::SpellDebuff,
|
||||
Effect::Hex => Category::BlueDebuff,
|
||||
Effect::Curse => Category::BlueDebuff,
|
||||
Effect::Banish => Category::BlueDebuff, // todo randomise
|
||||
Effect::Slow => Category::BlueDebuff,
|
||||
Effect::Haste => Category::BlueBuff,
|
||||
Effect::Enslave => Category::BlueDebuff,
|
||||
Effect::Mesmerise => Category::BlueDebuff,
|
||||
Effect::Amplify => Category::BlueBuff,
|
||||
Effect::Silence => Category::BlueDebuff,
|
||||
|
||||
// magic immunity
|
||||
Effect::Shield => Category::SpellBuff,
|
||||
Effect::Shield => Category::BlueBuff,
|
||||
|
||||
// effects over time
|
||||
Effect::Triage => Category::SpellBuff,
|
||||
Effect::Decay => Category::SpellDebuff,
|
||||
Effect::Regen => Category::SpellBuff,
|
||||
Effect::Drain => Category::SpellDebuff,
|
||||
Effect::Triage => Category::BlueBuff,
|
||||
Effect::Decay => Category::BlueDebuff,
|
||||
Effect::Regen => Category::BlueBuff,
|
||||
Effect::Siphon => Category::BlueDebuff,
|
||||
|
||||
Effect::SpeedDrain => Category::SpellDebuff,
|
||||
Effect::SpeedIncrease => Category::SpellBuff,
|
||||
Effect::SpeedSiphon => Category::BlueDebuff,
|
||||
Effect::SpeedIncrease => Category::BlueBuff,
|
||||
|
||||
Effect::Ko => Category::Ko,
|
||||
}
|
||||
@ -283,7 +283,7 @@ impl Effect {
|
||||
|
||||
Effect::Triage => 3,
|
||||
Effect::Decay => 3,
|
||||
Effect::Drain => 2,
|
||||
Effect::Siphon => 2,
|
||||
|
||||
_ => {
|
||||
println!("{:?} does not have a duration", self);
|
||||
@ -296,18 +296,18 @@ impl Effect {
|
||||
|
||||
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
||||
pub enum Category {
|
||||
Physical,
|
||||
PhysHeal,
|
||||
PhysDmg,
|
||||
PhysDebuff,
|
||||
PhysBuff,
|
||||
PhysTick,
|
||||
Spell,
|
||||
SpellDmg,
|
||||
SpellHeal,
|
||||
SpellDebuff,
|
||||
SpellBuff,
|
||||
SpellTick,
|
||||
Red,
|
||||
RedHeal,
|
||||
RedDamage,
|
||||
RedDebuff,
|
||||
RedBuff,
|
||||
RedTick,
|
||||
Blue,
|
||||
BlueDamage,
|
||||
BlueHeal,
|
||||
BlueDebuff,
|
||||
BlueBuff,
|
||||
BlueTick,
|
||||
Ko,
|
||||
}
|
||||
|
||||
@ -318,8 +318,8 @@ pub enum Skill {
|
||||
// -----------------
|
||||
// Nature
|
||||
// -----------------
|
||||
Block, // reduce dmg
|
||||
Parry, // avoid all dmg
|
||||
Block, // reduce damage
|
||||
Parry, // avoid all damage
|
||||
Snare,
|
||||
|
||||
Paralyse,
|
||||
@ -345,7 +345,7 @@ pub enum Skill {
|
||||
Heal,
|
||||
Triage, // hot
|
||||
TriageTick,
|
||||
Throw, // no dmg stun, adds vulnerable
|
||||
Throw, // no damage stun, adds vulnerable
|
||||
Charm,
|
||||
Calm,
|
||||
Rez,
|
||||
@ -360,8 +360,8 @@ pub enum Skill {
|
||||
Amplify,
|
||||
Decay, // dot
|
||||
DecayTick, // dot
|
||||
Drain,
|
||||
DrainTick,
|
||||
Siphon,
|
||||
SiphonTick,
|
||||
Curse,
|
||||
Plague, // aoe dot
|
||||
Ruin, // aoe
|
||||
@ -389,12 +389,12 @@ pub enum Skill {
|
||||
Haste,
|
||||
Slow,
|
||||
|
||||
// used by tests, no cd, no dmg
|
||||
// used by tests, no cd, no damage
|
||||
TestTouch,
|
||||
TestStun,
|
||||
TestBlock,
|
||||
TestParry,
|
||||
TestDrain,
|
||||
TestSiphon,
|
||||
}
|
||||
|
||||
impl Skill {
|
||||
@ -405,8 +405,8 @@ impl Skill {
|
||||
// -----------------
|
||||
// Nature
|
||||
// -----------------
|
||||
Skill::Block => None, // reduce dmg
|
||||
Skill::Parry => None, // avoid all dmg
|
||||
Skill::Block => None, // reduce damage
|
||||
Skill::Parry => None, // avoid all damage
|
||||
Skill::Snare => Some(1),
|
||||
|
||||
Skill::Paralyse => Some(1),
|
||||
@ -431,7 +431,7 @@ impl Skill {
|
||||
Skill::Heal => None,
|
||||
Skill::Triage => None, // hot
|
||||
Skill::TriageTick => None,
|
||||
Skill::Throw => Some(1), // no dmg stun, adds vulnerable
|
||||
Skill::Throw => Some(1), // no damage stun, adds vulnerable
|
||||
Skill::Charm => Some(1),
|
||||
Skill::Calm => None,
|
||||
Skill::Rez => Some(2),
|
||||
@ -443,8 +443,8 @@ impl Skill {
|
||||
Skill::Amplify => Some(1),
|
||||
Skill::Decay => None, // dot
|
||||
Skill::DecayTick => None,
|
||||
Skill::Drain => Some(1),
|
||||
Skill::DrainTick => None,
|
||||
Skill::Siphon => Some(1),
|
||||
Skill::SiphonTick => None,
|
||||
Skill::Curse => Some(1),
|
||||
Skill::Plague => Some(1), // aoe dot
|
||||
Skill::Ruin => Some(2), // aoe
|
||||
@ -478,95 +478,95 @@ impl Skill {
|
||||
Skill::TestTouch => None,
|
||||
Skill::TestStun => None,
|
||||
Skill::TestBlock => None,
|
||||
Skill::TestDrain => None,
|
||||
Skill::TestSiphon => None,
|
||||
Skill::TestParry => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn category(&self) -> Category {
|
||||
match self {
|
||||
Skill::Attack => Category::Physical,
|
||||
Skill::Attack => Category::Red,
|
||||
|
||||
// -----------------
|
||||
// Nature
|
||||
// -----------------
|
||||
Skill::Block => Category::Physical, // reduce dmg
|
||||
Skill::Parry => Category::Physical, // avoid all dmg
|
||||
Skill::Snare => Category::Physical,
|
||||
Skill::Block => Category::Red, // reduce damage
|
||||
Skill::Parry => Category::Red, // avoid all damage
|
||||
Skill::Snare => Category::Red,
|
||||
|
||||
Skill::Paralyse => Category::Physical,
|
||||
Skill::Strangle => Category::Physical,
|
||||
Skill::Paralyse => Category::Red,
|
||||
Skill::Strangle => Category::Red,
|
||||
|
||||
// Strangle
|
||||
|
||||
Skill::Stun => Category::Physical,
|
||||
Skill::Stun => Category::Red,
|
||||
|
||||
// -----------------
|
||||
// Technology
|
||||
// -----------------
|
||||
Skill::Replicate => Category::Physical,
|
||||
Skill::Swarm => Category::Physical,
|
||||
Skill::Orbit => Category::Physical,
|
||||
Skill::Repair => Category::Physical,
|
||||
Skill::Scan => Category::Physical, // track?
|
||||
Skill::Replicate => Category::Red,
|
||||
Skill::Swarm => Category::Red,
|
||||
Skill::Orbit => Category::Red,
|
||||
Skill::Repair => Category::Red,
|
||||
Skill::Scan => Category::Red, // track?
|
||||
|
||||
// -----------------
|
||||
// Preservation
|
||||
// -----------------
|
||||
Skill::Heal => Category::Physical,
|
||||
Skill::Triage => Category::Spell, // hot
|
||||
Skill::TriageTick => Category::SpellTick, // hot
|
||||
Skill::Throw => Category::Physical, // no dmg stun, adds vulnerable
|
||||
Skill::Charm => Category::Spell,
|
||||
Skill::Calm => Category::Physical,
|
||||
Skill::Rez => Category::Spell,
|
||||
Skill::Heal => Category::Red,
|
||||
Skill::Triage => Category::Blue, // hot
|
||||
Skill::TriageTick => Category::BlueTick, // hot
|
||||
Skill::Throw => Category::Red, // no damage stun, adds vulnerable
|
||||
Skill::Charm => Category::Blue,
|
||||
Skill::Calm => Category::Red,
|
||||
Skill::Rez => Category::Blue,
|
||||
|
||||
// -----------------
|
||||
// Destruction
|
||||
// -----------------
|
||||
Skill::Blast => Category::Spell,
|
||||
Skill::Amplify => Category::Spell,
|
||||
Skill::Decay => Category::Spell, // dot
|
||||
Skill::DecayTick => Category::SpellTick, // hot
|
||||
Skill::Drain => Category::Spell,
|
||||
Skill::DrainTick => Category::SpellTick, // hot
|
||||
Skill::Curse => Category::Spell,
|
||||
Skill::Plague => Category::Spell, // aoe dot
|
||||
Skill::Ruin => Category::Spell, // aoe
|
||||
Skill::Blast => Category::Blue,
|
||||
Skill::Amplify => Category::Blue,
|
||||
Skill::Decay => Category::Blue, // dot
|
||||
Skill::DecayTick => Category::BlueTick, // hot
|
||||
Skill::Siphon => Category::Blue,
|
||||
Skill::SiphonTick => Category::BlueTick, // hot
|
||||
Skill::Curse => Category::Blue,
|
||||
Skill::Plague => Category::Blue, // aoe dot
|
||||
Skill::Ruin => Category::Blue, // aoe
|
||||
|
||||
// -----------------
|
||||
// Purity
|
||||
// -----------------
|
||||
// Skill::Precision => 1,
|
||||
Skill::Empower => Category::Physical,
|
||||
Skill::Slay => Category::Physical,
|
||||
Skill::Shield => Category::Spell,
|
||||
Skill::Silence => Category::Spell,
|
||||
Skill::Inquiry => Category::Spell,
|
||||
Skill::Purify => Category::Spell,
|
||||
Skill::Purge => Category::Spell,
|
||||
Skill::Empower => Category::Red,
|
||||
Skill::Slay => Category::Red,
|
||||
Skill::Shield => Category::Blue,
|
||||
Skill::Silence => Category::Blue,
|
||||
Skill::Inquiry => Category::Blue,
|
||||
Skill::Purify => Category::Blue,
|
||||
Skill::Purge => Category::Blue,
|
||||
|
||||
// -----------------
|
||||
// Chaos
|
||||
// -----------------
|
||||
Skill::Banish => Category::Spell,
|
||||
Skill::Hex => Category::Spell,
|
||||
Skill::Fear => Category::Spell,
|
||||
Skill::Taunt => Category::Spell,
|
||||
Skill::Pause => Category::Spell, // extend durations
|
||||
Skill::Banish => Category::Blue,
|
||||
Skill::Hex => Category::Blue,
|
||||
Skill::Fear => Category::Blue,
|
||||
Skill::Taunt => Category::Blue,
|
||||
Skill::Pause => Category::Blue, // extend durations
|
||||
// Skill::Lag => 2, //
|
||||
Skill::Haste => Category::Spell,
|
||||
Skill::Slow => Category::Spell,
|
||||
Skill::Haste => Category::Blue,
|
||||
Skill::Slow => Category::Blue,
|
||||
|
||||
|
||||
// -----------------
|
||||
// Test
|
||||
// -----------------
|
||||
Skill::TestTouch => Category::Physical,
|
||||
Skill::TestStun => Category::Physical,
|
||||
Skill::TestParry => Category::Physical,
|
||||
Skill::TestBlock => Category::Physical,
|
||||
Skill::TestDrain => Category::Spell,
|
||||
Skill::TestTouch => Category::Red,
|
||||
Skill::TestStun => Category::Red,
|
||||
Skill::TestParry => Category::Red,
|
||||
Skill::TestBlock => Category::Red,
|
||||
Skill::TestSiphon => Category::Blue,
|
||||
}
|
||||
}
|
||||
|
||||
@ -574,7 +574,7 @@ impl Skill {
|
||||
match self {
|
||||
Skill::TriageTick => true,
|
||||
Skill::DecayTick => true,
|
||||
Skill::DrainTick => true,
|
||||
Skill::SiphonTick => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -583,10 +583,10 @@ impl Skill {
|
||||
match self {
|
||||
|
||||
// defensive block
|
||||
Skill::Block => 10, // reduce dmg
|
||||
Skill::Parry => 10, // avoid all dmg
|
||||
Skill::Block => 10, // reduce damage
|
||||
Skill::Parry => 10, // avoid all damage
|
||||
Skill::Snare => 10,
|
||||
Skill::Shield => 10, // avoid magic dmg,
|
||||
Skill::Shield => 10, // avoid magic damage,
|
||||
|
||||
// fast phys combat
|
||||
Skill::Attack => 5,
|
||||
@ -607,14 +607,14 @@ impl Skill {
|
||||
|
||||
// general combat
|
||||
Skill::DecayTick => 2, // hot
|
||||
Skill::Drain => 2,
|
||||
Skill::DrainTick => 2, // hot
|
||||
Skill::Siphon => 2,
|
||||
Skill::SiphonTick => 2, // hot
|
||||
Skill::Hex => 2,
|
||||
Skill::Pause => 2, // extend durations
|
||||
Skill::Plague => 2, // aoe dot
|
||||
Skill::Silence => 2,
|
||||
Skill::Stun => 2,
|
||||
Skill::Throw => 2, // no dmg stun, adds vulnerable
|
||||
Skill::Throw => 2, // no damage stun, adds vulnerable
|
||||
Skill::TriageTick => 2, // hot
|
||||
|
||||
Skill::Heal => 1,
|
||||
@ -644,7 +644,7 @@ impl Skill {
|
||||
Skill::TestStun => 5,
|
||||
Skill::TestBlock => 10,
|
||||
Skill::TestParry => 10,
|
||||
Skill::TestDrain => 10,
|
||||
Skill::TestSiphon => 10,
|
||||
}
|
||||
}
|
||||
|
||||
@ -664,7 +664,7 @@ impl Skill {
|
||||
return resolution;
|
||||
}
|
||||
|
||||
match self.category() == Category::Physical {
|
||||
match self.category() == Category::Red {
|
||||
true => {
|
||||
if let Some(evasion) = target.evade(*self) {
|
||||
resolution.results.push(evasion);
|
||||
@ -703,7 +703,7 @@ impl Skill {
|
||||
Skill::Heal => heal(source, target, resolution),
|
||||
Skill::Triage => triage(source, target, resolution), // hot
|
||||
Skill::TriageTick => triage_tick(source, target, resolution), // hot
|
||||
Skill::Throw => throw(source, target, resolution), // no dmg stun, adds vulnerable
|
||||
Skill::Throw => throw(source, target, resolution), // no damage stun, adds vulnerable
|
||||
Skill::Charm => panic!("nyi"), // target casts random spell on teammate
|
||||
Skill::Calm => panic!("nyi"), // physical fear, taunt removal
|
||||
Skill::Rez => panic!("nyi"),
|
||||
@ -712,11 +712,11 @@ impl Skill {
|
||||
// Destruction
|
||||
// -----------------
|
||||
Skill::Blast => blast(source, target, resolution),
|
||||
Skill::Amplify => amplify(source, target, resolution), // increase magic dmg
|
||||
Skill::Amplify => amplify(source, target, resolution), // increase magic damage
|
||||
Skill::Decay => decay(source, target, resolution), // dot
|
||||
Skill::DecayTick => decay_tick(source, target, resolution), // dot
|
||||
Skill::Drain => drain(source, target, resolution),
|
||||
Skill::DrainTick => drain_tick(source, target, resolution), // hot
|
||||
Skill::Siphon => siphon(source, target, resolution),
|
||||
Skill::SiphonTick => siphon_tick(source, target, resolution), // hot
|
||||
Skill::Curse => curse(source, target, resolution),
|
||||
Skill::Plague => panic!("nyi"), // dot that spreads every turn
|
||||
Skill::Ruin => panic!("nyi"), // aoe version of blast
|
||||
@ -725,9 +725,9 @@ impl Skill {
|
||||
// Purity
|
||||
// -----------------
|
||||
// Skill::Precision => panic!("nyi"),
|
||||
Skill::Empower => empower(source, target, resolution), // increased phys dmg
|
||||
Skill::Slay => panic!("nyi"), // phys dmg mult by target magic dmg
|
||||
Skill::Shield => shield(source, target, resolution), // target is immune to magic dmg and fx
|
||||
Skill::Empower => empower(source, target, resolution), // increased phys damage
|
||||
Skill::Slay => panic!("nyi"), // phys damage mult by target magic damage
|
||||
Skill::Shield => shield(source, target, resolution), // target is immune to magic damage and fx
|
||||
Skill::Silence => silence(source, target, resolution), // target cannot cast spells
|
||||
Skill::Inquiry => panic!("nyi"), //
|
||||
Skill::Purify => purify(source, target, resolution), // dispel all debuffs
|
||||
@ -751,7 +751,7 @@ impl Skill {
|
||||
Skill::TestStun => stun(source, target, resolution),
|
||||
Skill::TestBlock => block(source, target, resolution),
|
||||
Skill::TestParry => parry(source, target, resolution),
|
||||
Skill::TestDrain => drain(source, target, resolution),
|
||||
Skill::TestSiphon => siphon(source, target, resolution),
|
||||
}
|
||||
}
|
||||
|
||||
@ -780,8 +780,8 @@ impl Skill {
|
||||
}
|
||||
|
||||
fn attack(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
||||
let amount = cryp.phys_dmg();
|
||||
resolution.results.push(target.deal_phys_dmg(Skill::Attack, amount));
|
||||
let amount = cryp.red_damage();
|
||||
resolution.results.push(target.deal_red_damage(Skill::Attack, amount));
|
||||
return resolution;
|
||||
}
|
||||
|
||||
@ -828,7 +828,7 @@ fn empower(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> R
|
||||
}
|
||||
|
||||
fn heal(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
||||
let amount = cryp.spell_dmg();
|
||||
let amount = cryp.blue_damage();
|
||||
resolution.results.push(target.heal(Skill::Heal, amount));
|
||||
return resolution;
|
||||
}
|
||||
@ -858,14 +858,14 @@ fn triage(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Res
|
||||
}
|
||||
|
||||
fn triage_tick(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
||||
let amount = cryp.spell_dmg().wrapping_div(2);
|
||||
let amount = cryp.blue_damage().wrapping_div(2);
|
||||
resolution.results.push(target.heal(Skill::TriageTick, amount));
|
||||
return resolution;
|
||||
}
|
||||
|
||||
fn blast(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
||||
let amount = cryp.spell_dmg();
|
||||
resolution.results.push(target.deal_spell_dmg(Skill::Blast, amount));
|
||||
let amount = cryp.blue_damage();
|
||||
resolution.results.push(target.deal_blue_damage(Skill::Blast, amount));
|
||||
return resolution;
|
||||
}
|
||||
|
||||
@ -898,8 +898,8 @@ fn decay(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Reso
|
||||
}
|
||||
|
||||
fn decay_tick(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
||||
let amount = cryp.spell_dmg();
|
||||
resolution.results.push(target.deal_spell_dmg(Skill::DecayTick, amount));
|
||||
let amount = cryp.blue_damage();
|
||||
resolution.results.push(target.deal_blue_damage(Skill::DecayTick, amount));
|
||||
return resolution;
|
||||
}
|
||||
|
||||
@ -915,28 +915,28 @@ fn curse(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Res
|
||||
return resolution;;
|
||||
}
|
||||
|
||||
fn drain(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
||||
let drain = CrypEffect {
|
||||
effect: Effect::Drain,
|
||||
duration: Effect::Drain.duration(),
|
||||
tick: Some(Cast::new_tick(cryp, target, Skill::DrainTick)),
|
||||
fn siphon(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
||||
let siphon = CrypEffect {
|
||||
effect: Effect::Siphon,
|
||||
duration: Effect::Siphon.duration(),
|
||||
tick: Some(Cast::new_tick(cryp, target, Skill::SiphonTick)),
|
||||
};
|
||||
resolution.results.push(target.add_effect(Skill::Drain, drain));
|
||||
resolution.results.push(target.add_effect(Skill::Siphon, siphon));
|
||||
return resolution;;
|
||||
}
|
||||
|
||||
fn drain_tick(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
||||
let amount = cryp.spell_dmg();
|
||||
let drain_dmg = target.deal_spell_dmg(Skill::DrainTick, amount);
|
||||
resolution.results.push(drain_dmg.clone());
|
||||
fn siphon_tick(cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Resolution {
|
||||
let amount = cryp.blue_damage();
|
||||
let siphon_damage = target.deal_blue_damage(Skill::SiphonTick, amount);
|
||||
resolution.results.push(siphon_damage.clone());
|
||||
|
||||
match drain_dmg {
|
||||
match siphon_damage {
|
||||
ResolutionResult::Damage { amount, mitigation, category: _, immunity } => {
|
||||
if !immunity.immune {
|
||||
resolution.results.push(cryp.heal(Skill::Heal, amount));
|
||||
}
|
||||
},
|
||||
_ => panic!("drain tick dmg not dealt {:?}", drain_dmg),
|
||||
_ => panic!("siphon tick damage not dealt {:?}", siphon_damage),
|
||||
}
|
||||
|
||||
return resolution;
|
||||
@ -960,7 +960,7 @@ fn purge(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Res
|
||||
|
||||
if !immune {
|
||||
for (i, ce) in target.effects.clone().iter_mut().enumerate() {
|
||||
if ce.effect.category() == Category::SpellBuff {
|
||||
if ce.effect.category() == Category::BlueBuff {
|
||||
target.effects.remove(i);
|
||||
resolution.results.push(ResolutionResult::Removal { effect: ce.effect, immunity: immunity.clone() });
|
||||
}
|
||||
@ -976,7 +976,7 @@ fn purify(_cryp: &mut Cryp, target: &mut Cryp, mut resolution: Resolution) -> Re
|
||||
|
||||
if !immune {
|
||||
for (i, ce) in target.effects.clone().iter_mut().enumerate() {
|
||||
if ce.effect.category() == Category::SpellDebuff {
|
||||
if ce.effect.category() == Category::BlueDebuff {
|
||||
target.effects.remove(i);
|
||||
resolution.results.push(ResolutionResult::Removal { effect: ce.effect, immunity: immunity.clone() });
|
||||
}
|
||||
@ -1011,7 +1011,7 @@ mod tests {
|
||||
.learn(Skill::Heal)
|
||||
.create();
|
||||
|
||||
x.deal_phys_dmg(Skill::Attack, 5);
|
||||
x.deal_red_damage(Skill::Attack, 5);
|
||||
|
||||
heal(&mut y, &mut x, Resolution::new(Skill::Heal));
|
||||
}
|
||||
@ -1051,7 +1051,7 @@ mod tests {
|
||||
.create();
|
||||
|
||||
// ensure it doesn't have 0 pd
|
||||
x.phys_dmg.force(100);
|
||||
x.red_damage.force(100);
|
||||
y.hp.force(500);
|
||||
|
||||
block(&mut y.clone(), &mut y, Resolution::new(Skill::Block));
|
||||
@ -1078,13 +1078,13 @@ mod tests {
|
||||
.create();
|
||||
|
||||
// ensure it doesn't have 0 sd
|
||||
x.spell_dmg.force(50);
|
||||
x.blue_damage.force(50);
|
||||
|
||||
// remove all mitigation
|
||||
y.armour.force(0);
|
||||
y.spell_shield.force(0);
|
||||
y.red_shield.force(0);
|
||||
y.blue_shield.force(0);
|
||||
|
||||
y.deal_phys_dmg(Skill::Attack, 5);
|
||||
y.deal_red_damage(Skill::Attack, 5);
|
||||
let prev_hp = y.hp();
|
||||
|
||||
let res = Resolution::new(Skill::Triage);
|
||||
@ -1118,11 +1118,11 @@ mod tests {
|
||||
.level(8)
|
||||
.create();
|
||||
|
||||
x.spell_dmg.force(50);
|
||||
x.blue_damage.force(50);
|
||||
|
||||
amplify(&mut x.clone(), &mut x, Resolution::new(Skill::Amplify));
|
||||
assert!(x.effects.iter().any(|e| e.effect == Effect::Amplify));
|
||||
assert_eq!(x.spell_dmg(), 100);
|
||||
assert_eq!(x.blue_damage(), 100);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@ -25,30 +25,30 @@ impl Spec {
|
||||
|
||||
pub fn apply(&self, modified: u64, base: u64) -> u64 {
|
||||
match self.spec {
|
||||
SpecType::PhysDamage5 => modified + (base * 5 / 100),
|
||||
SpecType::SpellDamage5 => modified + (base * 5 / 100),
|
||||
SpecType::RedDamage5 => modified + (base * 5 / 100),
|
||||
SpecType::BlueDamage5 => modified + (base * 5 / 100),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug,Copy,Clone,Serialize,Deserialize,PartialEq)]
|
||||
pub enum SpecType {
|
||||
PhysDamage5,
|
||||
SpellDamage5,
|
||||
RedDamage5,
|
||||
BlueDamage5,
|
||||
}
|
||||
|
||||
impl SpecType {
|
||||
fn affects(&self) -> Stat {
|
||||
match *self {
|
||||
SpecType::PhysDamage5 => Stat::PhysicalDamage,
|
||||
SpecType::SpellDamage5 => Stat::SpellDamage,
|
||||
SpecType::RedDamage5 => Stat::RedDamage,
|
||||
SpecType::BlueDamage5 => Stat::BlueDamage,
|
||||
}
|
||||
}
|
||||
|
||||
fn level(&self) -> SpecLevel {
|
||||
match *self {
|
||||
SpecType::PhysDamage5 => SpecLevel::Common,
|
||||
SpecType::SpellDamage5 => SpecLevel::Common,
|
||||
SpecType::RedDamage5 => SpecLevel::Common,
|
||||
SpecType::BlueDamage5 => SpecLevel::Common,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
406
server/src/vbox.rs
Normal file
406
server/src/vbox.rs
Normal file
@ -0,0 +1,406 @@
|
||||
use std::iter;
|
||||
use uuid::Uuid;
|
||||
|
||||
// drops
|
||||
use rand::prelude::*;
|
||||
use rand::{thread_rng};
|
||||
use rand::distributions::{WeightedIndex};
|
||||
|
||||
use serde_cbor::{from_slice, to_vec};
|
||||
|
||||
use postgres::transaction::Transaction;
|
||||
|
||||
use failure::Error;
|
||||
use failure::err_msg;
|
||||
|
||||
use account::Account;
|
||||
use rpc::{VboxStateParams, VboxAcceptParams, VboxDiscardParams, VboxCombineParams, VboxApplyParams, VboxDropParams};
|
||||
use skill::{Skill};
|
||||
use cryp::{cryp_get, cryp_write};
|
||||
|
||||
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
||||
pub enum Var {
|
||||
Blue,
|
||||
Green,
|
||||
Red,
|
||||
|
||||
Attack,
|
||||
Block,
|
||||
Stun,
|
||||
Buff,
|
||||
Debuff,
|
||||
|
||||
Amplify,
|
||||
Banish,
|
||||
Blast,
|
||||
Curse,
|
||||
Empower,
|
||||
Haste,
|
||||
Heal,
|
||||
Hex,
|
||||
Parry,
|
||||
Purge,
|
||||
Purify,
|
||||
Reflect,
|
||||
Ruin,
|
||||
Shield,
|
||||
Silence,
|
||||
Slay,
|
||||
Slow,
|
||||
Snare,
|
||||
Strangle,
|
||||
Strike,
|
||||
Siphon,
|
||||
Survival,
|
||||
Taunt,
|
||||
Throw,
|
||||
Toxic,
|
||||
Triage,
|
||||
}
|
||||
|
||||
impl Var {
|
||||
fn is_base(&self) -> bool {
|
||||
match self {
|
||||
Var::Attack |
|
||||
Var::Block |
|
||||
Var::Stun |
|
||||
Var::Debuff |
|
||||
Var::Buff => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn skill(&self) -> Result<Skill, Error> {
|
||||
match self {
|
||||
Var::Amplify => Ok(Skill::Amplify),
|
||||
Var::Banish => Ok(Skill::Banish),
|
||||
Var::Blast => Ok(Skill::Blast),
|
||||
Var::Curse => Ok(Skill::Curse),
|
||||
Var::Empower => Ok(Skill::Empower),
|
||||
Var::Haste => Ok(Skill::Haste),
|
||||
Var::Heal => Ok(Skill::Heal),
|
||||
Var::Hex => Ok(Skill::Hex),
|
||||
Var::Parry => Ok(Skill::Parry),
|
||||
Var::Purge => Ok(Skill::Purge),
|
||||
Var::Purify => Ok(Skill::Purify),
|
||||
// Var::Reflect => Ok(Skill::Reflect),
|
||||
Var::Ruin => Ok(Skill::Ruin),
|
||||
Var::Shield => Ok(Skill::Shield),
|
||||
Var::Silence => Ok(Skill::Silence),
|
||||
Var::Slay => Ok(Skill::Slay),
|
||||
Var::Slow => Ok(Skill::Slow),
|
||||
Var::Snare => Ok(Skill::Snare),
|
||||
Var::Strangle => Ok(Skill::Strangle),
|
||||
// Var::Strike => Ok(Skill::Strike),
|
||||
// Var::Survival => Ok(Skill::Survival),
|
||||
// Var::Taunt => Ok(Skill::Taunt),
|
||||
Var::Throw => Ok(Skill::Throw),
|
||||
// Var::Toxic => Ok(Skill::Toxic),
|
||||
Var::Triage => Ok(Skill::Triage),
|
||||
_ => Err(err_msg("not a usable var"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
||||
enum ColourCode {
|
||||
RR,
|
||||
GG,
|
||||
BB,
|
||||
RG,
|
||||
BR,
|
||||
GB,
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
pub struct Vbox {
|
||||
pub id: Uuid,
|
||||
pub balance: u16,
|
||||
pub free: Vec<Var>,
|
||||
pub bound: Vec<Var>,
|
||||
pub game: Uuid,
|
||||
pub account: Uuid,
|
||||
}
|
||||
|
||||
impl Vbox {
|
||||
pub fn new(account_id: Uuid, game_id: Uuid) -> Vbox {
|
||||
Vbox {
|
||||
id: Uuid::new_v4(),
|
||||
account: account_id,
|
||||
game: game_id,
|
||||
free: vec![],
|
||||
bound: vec![],
|
||||
balance: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fill(mut self: Vbox) -> Vbox {
|
||||
let vars = vec![
|
||||
(Var::Red, 1),
|
||||
(Var::Green, 1),
|
||||
(Var::Blue, 1),
|
||||
|
||||
(Var::Attack, 1),
|
||||
(Var::Block, 1),
|
||||
(Var::Buff, 1),
|
||||
(Var::Debuff, 1),
|
||||
(Var::Stun, 1),
|
||||
];
|
||||
|
||||
self.free = iter::
|
||||
repeat_with(|| {
|
||||
let mut rng = thread_rng();
|
||||
let dist = WeightedIndex::new(vars.iter().map(|item| item.1)).unwrap();
|
||||
return vars[dist.sample(&mut rng)].0;
|
||||
})
|
||||
.take(8)
|
||||
.collect::<Vec<Var>>();
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn accept(&mut self, i: usize) -> Result<&mut Vbox, Error> {
|
||||
if self.bound.len() >= 9 {
|
||||
return Err(err_msg("too many vars bound"));
|
||||
}
|
||||
|
||||
self.free.get(i).ok_or(format_err!("no var at index {:?}", i))?;
|
||||
self.bound.push(self.free.remove(i));
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn drop(&mut self, i: usize) -> Result<&mut Vbox, Error> {
|
||||
self.bound.get(i).ok_or(format_err!("no var at index {:?}", i))?;
|
||||
self.bound.remove(i);
|
||||
// balance update
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn combine(&mut self, mut indices: Vec<usize>) -> Result<&mut Vbox, Error> {
|
||||
if indices.len() != 3 {
|
||||
return Err(err_msg("exactly 3 indices required"));
|
||||
}
|
||||
|
||||
if !indices.iter().all(|i| self.bound.get(*i).is_some()) {
|
||||
return Err(err_msg("var missing index"));
|
||||
}
|
||||
|
||||
// have to sort the indices and keep track of the iteration
|
||||
// because when removing the elements the array shifts
|
||||
indices.sort();
|
||||
let mut vars = indices
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, index)| {
|
||||
self.bound.remove(*index - i)
|
||||
})
|
||||
.collect::<Vec<Var>>();
|
||||
|
||||
let base_index = vars
|
||||
.iter()
|
||||
.position(|v| v.is_base())
|
||||
.ok_or(err_msg("no base item selected"))?;
|
||||
|
||||
let base = vars.remove(base_index);
|
||||
|
||||
// fold colours into RGB
|
||||
let colours = vars
|
||||
.iter()
|
||||
.fold([0, 0, 0], |mut acc, c| {
|
||||
match c {
|
||||
Var::Red => acc[0] += 1,
|
||||
Var::Green => acc[1] += 1,
|
||||
Var::Blue => acc[2] += 1,
|
||||
_ => (),
|
||||
};
|
||||
acc
|
||||
});
|
||||
|
||||
let colour_code = match colours {
|
||||
[2,0,0] => ColourCode::RR,
|
||||
[0,2,0] => ColourCode::GG,
|
||||
[0,0,2] => ColourCode::BB,
|
||||
[1,1,0] => ColourCode::RG,
|
||||
[0,1,1] => ColourCode::GB,
|
||||
[1,0,1] => ColourCode::BR,
|
||||
_ => return Err(err_msg("not a combo")),
|
||||
};
|
||||
|
||||
let new = match base {
|
||||
Var::Attack => match colour_code {
|
||||
ColourCode::RR => Var::Strike,
|
||||
ColourCode::GG => Var::Heal,
|
||||
ColourCode::BB => Var::Blast,
|
||||
ColourCode::RG => Var::Slay, //
|
||||
ColourCode::GB => return Err(err_msg("unhandled skill combo")),
|
||||
ColourCode::BR => Var::Banish, //
|
||||
},
|
||||
Var::Block => match colour_code {
|
||||
ColourCode::RR => Var::Parry,
|
||||
ColourCode::GG => Var::Reflect,
|
||||
ColourCode::BB => Var::Toxic,
|
||||
ColourCode::RG => Var::Taunt,
|
||||
ColourCode::GB => Var::Shield,
|
||||
ColourCode::BR => return Err(err_msg("unhandled skill combo")),
|
||||
},
|
||||
Var::Buff => match colour_code {
|
||||
ColourCode::RR => Var::Empower,
|
||||
ColourCode::GG => Var::Triage,
|
||||
ColourCode::BB => Var::Amplify,
|
||||
ColourCode::RG => Var::Survival,
|
||||
ColourCode::GB => return Err(err_msg("unhandled skill combo")),
|
||||
ColourCode::BR => Var::Haste,
|
||||
},
|
||||
Var::Debuff => match colour_code {
|
||||
ColourCode::RR => Var::Snare,
|
||||
ColourCode::GG => Var::Purge,
|
||||
ColourCode::BB => Var::Curse,
|
||||
ColourCode::RG => return Err(err_msg("unhandled skill combo")),
|
||||
ColourCode::GB => Var::Siphon,
|
||||
ColourCode::BR => Var::Slow,
|
||||
},
|
||||
Var::Stun => match colour_code {
|
||||
ColourCode::RR => Var::Strangle,
|
||||
ColourCode::GG => Var::Throw,
|
||||
ColourCode::BB => Var::Ruin,
|
||||
ColourCode::RG => return Err(err_msg("unhandled skill combo")),
|
||||
ColourCode::GB => Var::Silence,
|
||||
ColourCode::BR => Var::Hex,
|
||||
},
|
||||
_ => panic!("wrong base {:?}", base),
|
||||
};
|
||||
|
||||
self.bound.push(new);
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vbox_create(vbox: Vbox, tx: &mut Transaction, account: &Account) -> Result<Vbox, Error> {
|
||||
let vbox_bytes = to_vec(&vbox)?;
|
||||
|
||||
let query = "
|
||||
INSERT INTO vbox (id, account, game, data)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
RETURNING id;
|
||||
";
|
||||
|
||||
let result = tx
|
||||
.query(query, &[&vbox.id, &account.id, &vbox.game, &vbox_bytes])?;
|
||||
|
||||
result.iter().next().ok_or(format_err!("no vbox written"))?;
|
||||
|
||||
// println!("{:} wrote vbox", vbox.id);
|
||||
|
||||
return Ok(vbox);
|
||||
}
|
||||
|
||||
pub fn vbox_write(vbox: Vbox, tx: &mut Transaction) -> Result<Vbox, Error> {
|
||||
let vbox_bytes = to_vec(&vbox)?;
|
||||
|
||||
let query = "
|
||||
UPDATE vbox
|
||||
SET data = $1
|
||||
WHERE id = $2
|
||||
RETURNING id, account, data;
|
||||
";
|
||||
|
||||
let result = tx
|
||||
.query(query, &[&vbox_bytes, &vbox.id])?;
|
||||
|
||||
result.iter().next().ok_or(err_msg("no vbox row returned"))?;
|
||||
|
||||
// println!("{:?} wrote vbox", vbox.id);
|
||||
|
||||
return Ok(vbox);
|
||||
}
|
||||
|
||||
|
||||
pub fn vbox_get(tx: &mut Transaction, game_id: Uuid, account: &Account) -> Result<Vbox, Error> {
|
||||
let query = "
|
||||
SELECT *
|
||||
FROM vbox
|
||||
WHERE account = $1
|
||||
AND game = $2;
|
||||
";
|
||||
|
||||
let result = tx
|
||||
.query(query, &[&account.id, &game_id])?;
|
||||
|
||||
let returned = match result.iter().next() {
|
||||
Some(row) => row,
|
||||
None => return Err(err_msg("vbox not found")),
|
||||
};
|
||||
|
||||
// tells from_slice to cast into a cryp
|
||||
let vbox_bytes: Vec<u8> = returned.get("data");
|
||||
let vbox = from_slice::<Vbox>(&vbox_bytes)?;
|
||||
|
||||
return Ok(vbox);
|
||||
}
|
||||
|
||||
pub fn vbox_state(params: VboxStateParams, tx: &mut Transaction, account: &Account) -> Result<Vbox, Error> {
|
||||
match vbox_get(tx, params.game_id, account) {
|
||||
Ok(v) => Ok(v),
|
||||
Err(e) => {
|
||||
println!("{:?}", e);
|
||||
vbox_create(Vbox::new(account.id, params.game_id).fill(), tx, account)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vbox_discard(params: VboxDiscardParams, tx: &mut Transaction, account: &Account) -> Result<Vbox, Error> {
|
||||
let vbox = vbox_get(tx, params.game_id, account)?;
|
||||
return vbox_write(vbox.fill(), tx);
|
||||
}
|
||||
|
||||
pub fn vbox_accept(params: VboxAcceptParams, tx: &mut Transaction, account: &Account) -> Result<Vbox, Error> {
|
||||
let mut vbox = vbox_get(tx, params.game_id, account)?;
|
||||
vbox.accept(params.index)?;
|
||||
return vbox_write(vbox, tx);
|
||||
}
|
||||
|
||||
pub fn vbox_combine(params: VboxCombineParams, tx: &mut Transaction, account: &Account) -> Result<Vbox, Error> {
|
||||
let mut vbox = vbox_get(tx, params.game_id, account)?;
|
||||
vbox.combine(params.indices)?;
|
||||
return vbox_write(vbox, tx);
|
||||
}
|
||||
|
||||
pub fn vbox_drop(params: VboxDropParams, tx: &mut Transaction, account: &Account) -> Result<Vbox, Error> {
|
||||
let mut vbox = vbox_get(tx, params.game_id, account)?;
|
||||
vbox.drop(params.index)?;
|
||||
return vbox_write(vbox, tx);
|
||||
}
|
||||
|
||||
pub fn vbox_apply(params: VboxApplyParams, tx: &mut Transaction, account: &Account) -> Result<Vbox, Error> {
|
||||
let mut vbox = vbox_get(tx, params.game_id, account)?;
|
||||
let mut cryp = cryp_get(tx, params.cryp_id, account.id)?;
|
||||
|
||||
let var = vbox.bound.remove(params.index);
|
||||
|
||||
// done here because i teach them a tonne of skills for tests
|
||||
let max_skills = 4;
|
||||
if cryp.skills.len() >= max_skills {
|
||||
return Err(format_err!("cryp at max skills ({:?})", max_skills));
|
||||
}
|
||||
|
||||
let skill = var.skill()?;
|
||||
cryp = cryp.learn(skill);
|
||||
cryp_write(cryp, tx)?;
|
||||
return vbox_write(vbox, tx);
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn combine_test() {
|
||||
let mut vbox = Vbox::new(Uuid::new_v4(), Uuid::new_v4());
|
||||
vbox.bound = vec![Var::Attack, Var::Green, Var::Green];
|
||||
vbox.combine(vec![1,2,0]).unwrap();
|
||||
assert_eq!(vbox.bound[0], Var::Heal);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user