Merge branch 'warden'
This commit is contained in:
commit
f9dad4cfb5
@ -19,6 +19,7 @@ function GamePanel(props) {
|
||||
setActiveCryp,
|
||||
selectSkillTarget,
|
||||
sendInstanceState,
|
||||
sendGameReady,
|
||||
activeCryp,
|
||||
account,
|
||||
showLog,
|
||||
@ -69,18 +70,23 @@ function GamePanel(props) {
|
||||
onClick={() => toggleLog(!showLog)}>
|
||||
Log
|
||||
</button>
|
||||
<button
|
||||
className="game-back-btn instance-btn instance-ui-btn right"
|
||||
onClick={() => sendGameReady()}>
|
||||
Ready
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
|
||||
function findCryp(id) {
|
||||
const team = game.teams.find(t => t.cryps.find(c => c.id === id));
|
||||
const team = game.players.find(t => t.cryps.find(c => c.id === id));
|
||||
if (team) return team.cryps.find(c => c.id === id);
|
||||
return null;
|
||||
}
|
||||
|
||||
const otherTeams = game.teams.filter(t => t.id !== account.id);
|
||||
const otherTeams = game.players.filter(t => t.id !== account.id);
|
||||
|
||||
const playerTeam = game.teams.find(t => t.id === account.id);
|
||||
const playerTeam = game.players.find(t => t.id === account.id);
|
||||
|
||||
function stackElement(c, i) {
|
||||
let skills = game.stack.filter(s => s.source_cryp_id === c.id).map((s, j) => {
|
||||
|
||||
@ -23,6 +23,10 @@ const addState = connect(
|
||||
return false;
|
||||
}
|
||||
|
||||
function sendGameReady() {
|
||||
ws.sendGameReady(game.id);
|
||||
}
|
||||
|
||||
function sendInstanceState(instanceId) {
|
||||
if (!instanceId) return false;
|
||||
return ws.sendInstanceState(instanceId);
|
||||
@ -42,6 +46,7 @@ const addState = connect(
|
||||
activeCryp,
|
||||
selectSkillTarget,
|
||||
sendInstanceState,
|
||||
sendGameReady,
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
@ -153,15 +153,39 @@ function Info(args) {
|
||||
);
|
||||
}
|
||||
|
||||
function playerRound(id) {
|
||||
if (!instance.rounds.length) return null;
|
||||
return instance.rounds[instance.rounds.length - 1].find(r => r.player_ids.includes(id));
|
||||
}
|
||||
|
||||
function playerText(player) {
|
||||
const round = playerRound(player.id);
|
||||
if (!round) {
|
||||
return player.ready
|
||||
? 'ready'
|
||||
: '';
|
||||
}
|
||||
|
||||
if (round.finished) return 'finished';
|
||||
|
||||
return player.ready
|
||||
? 'ready'
|
||||
: '';
|
||||
}
|
||||
|
||||
function scoreBoard() {
|
||||
const players = instance.players.map((p, i) =>
|
||||
<tr key={i}
|
||||
className={p.ready ? 'ready' : ''}>
|
||||
<td>{p.name}</td>
|
||||
<td>{p.score.wins} / {p.score.losses}</td>
|
||||
<td>{p.ready ? 'ready' : ''}</td>
|
||||
</tr>
|
||||
);
|
||||
const players = instance.players.map((p, i) => {
|
||||
const pText = playerText(p);
|
||||
console.log(pText);
|
||||
return (
|
||||
<tr key={i}
|
||||
className={p.ready ? 'ready' : ''}>
|
||||
<td>{p.name}</td>
|
||||
<td>{p.score.wins} / {p.score.losses}</td>
|
||||
<td>{pText}</td>
|
||||
</tr>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<table>
|
||||
|
||||
@ -67,10 +67,11 @@ class InstanceCreateForm extends Component {
|
||||
<label htmlFor="playerSelect">players</label>
|
||||
<select id="playerSelect"
|
||||
disabled={disabled}
|
||||
value={this.state.players}
|
||||
onChange={this.playersChange}
|
||||
>
|
||||
<option value={1}>pve</option>
|
||||
<option selected value={2}>2</option>
|
||||
<option value={2}>2</option>
|
||||
<option value={4}>4</option>
|
||||
<option value={8}>8</option>
|
||||
<option value={16}>16</option>
|
||||
|
||||
@ -58,14 +58,14 @@ function Menu(args) {
|
||||
|
||||
const instanceJoinHidden = !selectedCryps.every(c => !!c);
|
||||
|
||||
const mmSet = (
|
||||
<button
|
||||
className={'menu-instance-btn left'}
|
||||
disabled={instanceJoinHidden}
|
||||
onClick={() => sendPlayerMmCrypsSet()}>
|
||||
Set Matchmaking Team
|
||||
</button>
|
||||
);
|
||||
// const mmSet = (
|
||||
// <button
|
||||
// className={'menu-instance-btn left'}
|
||||
// disabled={instanceJoinHidden}
|
||||
// onClick={() => sendPlayerMmCrypsSet()}>
|
||||
// Set Matchmaking Team
|
||||
// </button>
|
||||
// );
|
||||
|
||||
return (
|
||||
<section className="menu-instance-list" >
|
||||
@ -85,7 +85,6 @@ function Menu(args) {
|
||||
</tbody>
|
||||
</table>
|
||||
<InstanceCreateForm />
|
||||
{mmSet}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@ -110,7 +110,7 @@ function Vbox(args) {
|
||||
if (boundTimer) {
|
||||
clearTimeout(boundTimer);
|
||||
|
||||
if (reclaiming && i) sendVboxReclaim(i);
|
||||
if (reclaiming && vbox.bound[i]) sendVboxReclaim(i);
|
||||
else if (vbox.bound[i]) {
|
||||
const insert = combiner.findIndex(j => j === null);
|
||||
if (insert === -1) return setCombiner([i, null, null]);
|
||||
@ -128,7 +128,7 @@ function Vbox(args) {
|
||||
}
|
||||
|
||||
function boundClick(e, i) {
|
||||
if (reclaiming && i) sendVboxReclaim(i);
|
||||
if (reclaiming && vbox.bound[i]) sendVboxReclaim(i);
|
||||
else if (vbox.bound[i]) {
|
||||
const insert = combiner.findIndex(j => j === null);
|
||||
if (insert === -1) return setCombiner([i, null, null]);
|
||||
@ -210,6 +210,7 @@ function Vbox(args) {
|
||||
return setReclaiming(!reclaiming);
|
||||
}
|
||||
|
||||
console.log('reclaiminig', reclaiming)
|
||||
const classes = `vbox ${activeVar !== null || activeCryp ? 'hidden' : ''}`;
|
||||
const reclaimClass = `instance-btn instance-ui-btn vbox-btn ${reclaiming ? 'reclaiming' : ''}`;
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@ function setupKeys(store) {
|
||||
key('esc', () => store.dispatch(actions.setReclaiming(false)));
|
||||
key('esc', () => store.dispatch(actions.setActiveSkill(null)));
|
||||
key('esc', () => store.dispatch(actions.setActiveCryp(null)));
|
||||
key('esc', () => store.dispatch(actions.setInfo([null, null])));
|
||||
}
|
||||
|
||||
module.exports = setupKeys;
|
||||
|
||||
@ -74,8 +74,8 @@ function createSocket(events) {
|
||||
send({ method: 'game_state', params: { id } });
|
||||
}
|
||||
|
||||
function sendGameJoin(gameId, crypIds) {
|
||||
send({ method: 'game_join', params: { game_id: gameId, cryp_ids: crypIds } });
|
||||
function sendGameReady(id) {
|
||||
send({ method: 'game_ready', params: { id } });
|
||||
}
|
||||
|
||||
function sendSpecForget(id, spec) {
|
||||
@ -331,7 +331,7 @@ function createSocket(events) {
|
||||
sendAccountInstances,
|
||||
sendAccountZone,
|
||||
sendGameState,
|
||||
sendGameJoin,
|
||||
sendGameReady,
|
||||
sendGameSkill,
|
||||
sendGameTarget,
|
||||
sendCrypSpawn,
|
||||
|
||||
@ -6,6 +6,10 @@ exports.up = async knex => {
|
||||
table.index('id');
|
||||
table.timestamps(true, true);
|
||||
table.binary('data').notNullable();
|
||||
table.boolean('finished')
|
||||
.defaultTo(false)
|
||||
.notNullable()
|
||||
.index();
|
||||
});
|
||||
|
||||
await knex.schema.createTable('instances', async table => {
|
||||
@ -15,7 +19,7 @@ exports.up = async knex => {
|
||||
|
||||
table.binary('data').notNullable();
|
||||
table.boolean('open')
|
||||
.defaultTo(true)
|
||||
.defaultTo(false)
|
||||
.notNullable()
|
||||
.index();
|
||||
});
|
||||
|
||||
@ -10,9 +10,10 @@ serde = "1"
|
||||
serde_derive = "1"
|
||||
serde_cbor = "0.9"
|
||||
|
||||
chrono = { version = "0.4", features = ["serde"] }
|
||||
|
||||
tungstenite = "0.6"
|
||||
bcrypt = "0.2"
|
||||
petgraph = { version = "0.4", features = ["serde-1"] }
|
||||
|
||||
dotenv = "0.9.0"
|
||||
env_logger = "*"
|
||||
|
||||
@ -2,12 +2,12 @@
|
||||
|
||||
Items - Base colours / skills / specs and associated upgrades
|
||||
|
||||
### Sources of money
|
||||
### Sources of money
|
||||
- Start with money and gain income after each battle
|
||||
- Higher income from winning
|
||||
- Higher income from winning
|
||||
|
||||
- Selling items in inventory or equipped on character refunds
|
||||
- Selling from inventory full refund
|
||||
- Selling from inventory full refund
|
||||
- Selling from charcter 50% refund
|
||||
|
||||
### Uses for money
|
||||
@ -32,7 +32,7 @@ Base specs have a base 3 cost
|
||||
Round #1
|
||||
|
||||
All costs are base costs
|
||||
# Team #1 and Team #2 (They both bought the same things)
|
||||
# Player #1 and Player #2 (They both bought the same things)
|
||||
Cryp #1 Strike (Attack + RR), (2 + 1 + 1) = (4) cost
|
||||
Cryp #1 Empower (Buff + RR), (2 + 1 + 1) = (4) cost
|
||||
Cryp #3 Attack, 2 cost
|
||||
@ -51,7 +51,7 @@ The costs of red for round #2 are now (1 + 1) = 2
|
||||
|
||||
If they were to buy the same skill setup it would be as follows:
|
||||
|
||||
# Team #1 and Team #2 (They both bought the same things)
|
||||
# Player #1 and Player #2 (They both bought the same things)
|
||||
Cryp #1 Strike (Attack + RR), (2 + 2 + 2) = (6) cost
|
||||
Cryp #1 Empower (Buff + RR), (2 + 2 + 2) = (6) cost
|
||||
Cryp #3 Attack, 2 cost
|
||||
@ -60,8 +60,8 @@ Total cost - 14
|
||||
|
||||
### Philosophy of increasing item costs
|
||||
|
||||
- Two games will never feel exactly the same
|
||||
- Costs change over rounds to diversify skill choice and gameplay
|
||||
- Two games will never feel exactly the same
|
||||
- Costs change over rounds to diversify skill choice and gameplay
|
||||
- As optimal builds emerge the paths to reach them will change every game
|
||||
- Rewarded for going (hipster) builds nobody else is trying
|
||||
- Some reward for hoarding items in your inventory while they cheaper (hodl red)
|
||||
|
||||
@ -4,16 +4,16 @@
|
||||
|
||||
skill phase:
|
||||
1.1 -> block (sp 10) -> on self
|
||||
1.2 -> attack (sp 5) -> on team 2
|
||||
1.2 -> attack (sp 5) -> on player 2
|
||||
|
||||
2.1 -> hex (sp 3) -> on team 1
|
||||
2.2 -> attack (sp 5) -> on team 1
|
||||
2.1 -> hex (sp 3) -> on player 1
|
||||
2.2 -> attack (sp 5) -> on player 1
|
||||
|
||||
target phase:
|
||||
team 2 targets 1.2 on 2.2
|
||||
player 2 targets 1.2 on 2.2
|
||||
|
||||
team 1 targets 2.1 on 1.1
|
||||
team 1 targets 2.2 on 1.1
|
||||
player 1 targets 2.1 on 1.1
|
||||
player 1 targets 2.2 on 1.1
|
||||
|
||||
resolve phase:
|
||||
1.1 <- block
|
||||
@ -116,7 +116,7 @@ Its members now scour the lands in search of magic, censoring its teaching, purg
|
||||
* Silence
|
||||
* Magic resistance
|
||||
* Information gathering
|
||||
* team composition
|
||||
* player composition
|
||||
* available skills etc
|
||||
|
||||
Universal Chaos
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
### Specs ###
|
||||
|
||||
Numbers are placeholder
|
||||
`Specs get a bonus dependent on the total of Red / Green / Blue in team skills & specs`
|
||||
`Specs get a bonus dependent on the total of Red / Green / Blue in player skills & specs`
|
||||
|
||||
# Example to meet 5 red gem bonus from skills only
|
||||
In your team Cryp #1 has `Strike`, Cryp #2 has `Slay` and `Heal`, Cryp #3 has `Snare`
|
||||
In your player Cryp #1 has `Strike`, Cryp #2 has `Slay` and `Heal`, Cryp #3 has `Snare`
|
||||
- RR skill `Strike` contributes 2 red gems to the total red gems (2 total)
|
||||
- RG skill `Slay` contributes 1 red gem to the total red gems (3 total)
|
||||
- GG skill `Heal` contirubtes 0 red gems to the total red gems (3 total)
|
||||
@ -30,7 +30,7 @@ In your team Cryp #1 has `Strike`, Cryp #2 has `Slay` and `Heal`, Cryp #3 has `S
|
||||
Cryp #2 -> Give Attack -> Attack
|
||||
Cryp #3 -> Give Stun -> Stun
|
||||
|
||||
Team Total (4 Red + 2 Basic gems)
|
||||
Player Total (4 Red + 2 Basic gems)
|
||||
|
||||
### Round 2
|
||||
|
||||
@ -87,12 +87,12 @@ In your team Cryp #1 has `Strike`, Cryp #2 has `Slay` and `Heal`, Cryp #3 has `S
|
||||
|
||||
# Basic % GreenLife
|
||||
`Base` -> 5% inc hp
|
||||
`Team Bonus` -> 3 basic gems -> +5% // 6 basic gems -> +10% // 12 basic gems -> +15%
|
||||
`Player Bonus` -> 3 basic gems -> +5% // 6 basic gems -> +10% // 12 basic gems -> +15%
|
||||
Maximum 35% inc hp
|
||||
|
||||
# Basic Speed
|
||||
`Base` -> 5% inc speed
|
||||
`Team Bonus` -> 3 basic gems -> +10% // 6 basic gems -> +15% // 12 basic gems -> +20%
|
||||
`Player Bonus` -> 3 basic gems -> +10% // 6 basic gems -> +15% // 12 basic gems -> +20%
|
||||
Maximum 50% inc speed
|
||||
|
||||
# Basic Class Spec
|
||||
@ -106,37 +106,37 @@ Generate by combining `Generic Spec (Basic Damage)` with respective RGB
|
||||
# Red Damage (Dmg + RR)
|
||||
Add 2 `red gems`
|
||||
`Base` -> 10% inc red dmg
|
||||
`Team Bonus` 5 red gems -> +10% // 10 red gems -> +15% // 20 red gems -> +25%
|
||||
`Player Bonus` 5 red gems -> +10% // 10 red gems -> +15% // 20 red gems -> +25%
|
||||
Maximum +60% red damage
|
||||
|
||||
# Blue Damage (Dmg + BB) #
|
||||
Add 2 `blue gems`
|
||||
`Base` -> 10% inc blue dmg
|
||||
`Team Bonus` 5 blue gems -> +10% // 10 blue gems -> +15% // 20 blue gems -> +25%
|
||||
`Player Bonus` 5 blue gems -> +10% // 10 blue gems -> +15% // 20 blue gems -> +25%
|
||||
Maximum +60% blue damage
|
||||
|
||||
# Healing (Dmg + GG) #
|
||||
Add 2 `green gems`
|
||||
`Base` -> 10% inc healing
|
||||
`Team Bonus` 5 green gems -> +10% // 10 green gems -> +15% // 20 green gems -> +25%
|
||||
`Player Bonus` 5 green gems -> +10% // 10 green gems -> +15% // 20 green gems -> +25%
|
||||
Maximum +60% inc healing
|
||||
|
||||
# Red damage and healing (Dmg + RG)
|
||||
Add 1 red 1 green gem
|
||||
`Base` -> 5% inc red damage and 5% inc healing
|
||||
`Team Bonus` (2R + 2G gems) -> +5% + 5% // (5R + 5G gems) -> +10% + 10% % // (10R + 10G) gems -> +15% + 15%
|
||||
`Player Bonus` (2R + 2G gems) -> +5% + 5% // (5R + 5G gems) -> +10% + 10% % // (10R + 10G) gems -> +15% + 15%
|
||||
Maximum +35% inc red damage and 35% inc healing
|
||||
|
||||
# Red and blue damage (Dmg + RB)
|
||||
Add 1 red and 1 blue gem
|
||||
`Base` -> 5% inc red damage and 5% inc healing
|
||||
`Team Bonus` (2 red + 2 green gems) -> +5% + 5% // (5 red + 5 green gems) -> +10% + 10% % // 20 green gems -> +15% + 15%
|
||||
`Player Bonus` (2 red + 2 green gems) -> +5% + 5% // (5 red + 5 green gems) -> +10% + 10% % // 20 green gems -> +15% + 15%
|
||||
Maximum +35% inc damage and 35% inc healing
|
||||
|
||||
# Blue damage and healing (Dmg + BG)
|
||||
Add 1 blue and 1 green gem
|
||||
`Base` -> 5% inc blue damage and 5% inc healing
|
||||
`Team Bonus` (2B + 2G gems) -> +5% + 5% // (5B + 5G gems) -> +10% + 10% % // (10B + 10G) gems -> +15% + 15%
|
||||
`Player Bonus` (2B + 2G gems) -> +5% + 5% // (5B + 5G gems) -> +10% + 10% % // (10B + 10G) gems -> +15% + 15%
|
||||
Maximum +35% inc blue damage and 35% inc healing
|
||||
|
||||
### Increased GreenLife Combos ###
|
||||
@ -146,37 +146,37 @@ Generate by combining `Generic Spec (Basic GreenLife)` with respective RGB
|
||||
# Increased % Red Life (Basic %HP + 2R)
|
||||
Add 2 `red gems`
|
||||
`Base` -> 10% inc red shield
|
||||
`Team Bonus` 5 red gems -> +10% // 10 red gems -> +15% // 20 red gems -> +20%
|
||||
`Player Bonus` 5 red gems -> +10% // 10 red gems -> +15% // 20 red gems -> +20%
|
||||
Maximum +55% inc red shield
|
||||
|
||||
# Increased % Red Life and GreenLife (Basic %HP + 1R1G)
|
||||
Add 1 red 1 green gem
|
||||
`Base` -> 5% inc red shield and 5% inc hp
|
||||
`Team Bonus` (2R + 2G gems) -> +5% + 5% // (5R + 5G gems) -> +10% + 10% % // (10R + 10G) gems -> +15% + 15%
|
||||
`Player Bonus` (2R + 2G gems) -> +5% + 5% // (5R + 5G gems) -> +10% + 10% % // (10R + 10G) gems -> +15% + 15%
|
||||
Maximum +35% inc red shield and 35% inc hp
|
||||
|
||||
# Increased % Blue Life (Basic %HP + 2B)
|
||||
Add 2 `blue gems`
|
||||
`Base` -> 10% inc red shield
|
||||
`Team Bonus` 5 blue gems -> +10% // 10 blue gems -> +15% // 20 blue gems -> +20%
|
||||
`Player Bonus` 5 blue gems -> +10% // 10 blue gems -> +15% // 20 blue gems -> +20%
|
||||
Maximum +55% inc blue shield
|
||||
|
||||
# Increased % Blue Life and GreenLife (Basic %HP + 1B1G)
|
||||
Add `1 blue and 1 green gems`
|
||||
`Base` -> 5% inc red shield and 5% inc hp
|
||||
`Team Bonus` (2B + 2G gems) -> +5% + 5% // (5B + 5G gems) -> +10% + 10% % // (10B + 10G) gems -> +15% + 15%
|
||||
`Player Bonus` (2B + 2G gems) -> +5% + 5% // (5B + 5G gems) -> +10% + 10% % // (10B + 10G) gems -> +15% + 15%
|
||||
Maximum +35% inc blue shield and 35% inc hp
|
||||
|
||||
# Increased % GreenLife (Basic %HP + 2G)
|
||||
Add `2 green gems`
|
||||
`Base` -> 10% inc hp
|
||||
`Team Bonus` 5 green gems -> +10% // 10 green gems -> +15% // 20 green gems -> +20%
|
||||
`Player Bonus` 5 green gems -> +10% // 10 green gems -> +15% // 20 green gems -> +20%
|
||||
Maximum +55% inc hp
|
||||
|
||||
# Increased % Blue and Red Life (Basic %HP + 1B1R)
|
||||
Add `1 blue and 1 red gem`
|
||||
`Base` -> 5% inc red shield and 5% inc hp
|
||||
`Team Bonus` (2B + 2R gems) -> +5% + 5% // (5B + 5R gems) -> +10% + 10% % // (10B + 10R) gems -> +15% + 15%
|
||||
`Player Bonus` (2B + 2R gems) -> +5% + 5% // (5B + 5R gems) -> +10% + 10% % // (10B + 10R) gems -> +15% + 15%
|
||||
Maximum +35% inc blue shield and 35% inc red shield
|
||||
|
||||
## Upgraded Attack Spec Combos
|
||||
@ -185,31 +185,31 @@ Maximum +35% inc blue shield and 35% inc red shield
|
||||
Cryp Requires `8 red gems`
|
||||
Adds `6 red gems`
|
||||
`Base` -> 15% increased strike damage
|
||||
`Team Bonus` 15 red gems -> +15% // 20 red gems -> +20% // 30 red gems -> +30%
|
||||
`Player Bonus` 15 red gems -> +15% // 20 red gems -> +20% // 30 red gems -> +30%
|
||||
Maximum 80% increased strike damage
|
||||
|
||||
# Improved Heal (Combine Heal + Healing Spec x 2)
|
||||
Cryp Requires `8 green gems`
|
||||
`Base` -> 15% increased heal healing
|
||||
`Team Bonus` 15 green gems -> +15% // 20 green gems -> +20% // 30 green gems -> +30%
|
||||
`Player Bonus` 15 green gems -> +15% // 20 green gems -> +20% // 30 green gems -> +30%
|
||||
Maximum 80% increased heal healing
|
||||
|
||||
# Increased Blast Damage (Combine Blast + Blue Spec x 2)
|
||||
Cryp Requires `8 blue gems`
|
||||
`Base` -> 15% increased blast damage
|
||||
`Team Bonus` 15 blue gems -> +15% // 20 blue gems -> +20% // 30 blue gems -> +30%
|
||||
`Player Bonus` 15 blue gems -> +15% // 20 blue gems -> +20% // 30 blue gems -> +30%
|
||||
Maximum 80% increased blast damage
|
||||
|
||||
# Increased Slay Damage (Combine Slay + Red Damage Spec + Healing Spec)
|
||||
Cryp Requires `4 red 4 green gems`
|
||||
`Base` -> 15% increased slay damage
|
||||
`Team Bonus` (8R + 8G) gems -> +15% // (10R + 10G) gems -> +20% // (15R + 15G) gems -> +30%
|
||||
`Player Bonus` (8R + 8G) gems -> +15% // (10R + 10G) gems -> +20% // (15R + 15G) gems -> +30%
|
||||
Maximum 80% increased slay damage
|
||||
|
||||
# Increased Banish Damage (Combine Slay + Red Damage Spec + Blue Damage Spec)
|
||||
Cryp Requires `4 red 4 blue gems`
|
||||
`Base` -> 15% increased slay damage
|
||||
`Team Bonus` (8R + 8B) gems -> +15% // (10R + 10B) gems -> +20% // (15R + 15B) gems -> +30%
|
||||
`Player Bonus` (8R + 8B) gems -> +15% // (10R + 10B) gems -> +20% // (15R + 15B) gems -> +30%
|
||||
Maximum 80% increased banish damage
|
||||
|
||||
## Other Combos
|
||||
@ -217,7 +217,7 @@ Maximum 80% increased banish damage
|
||||
# Increased % Red Speed (Basic Speed + 2R)
|
||||
Add 2 red gems
|
||||
`Base` -> 15% inc red speed
|
||||
`Team Bonus` 5 red gems -> +15% // 10 red gems -> +20% // 20 red gems -> +25%
|
||||
`Player Bonus` 5 red gems -> +15% // 10 red gems -> +20% // 20 red gems -> +25%
|
||||
Maximum 80% inc red speed
|
||||
|
||||
# Nature Affinity (Basic Class spec + 2R)
|
||||
|
||||
@ -16,14 +16,22 @@
|
||||
# WORK WORK
|
||||
## NOW
|
||||
|
||||
*INSTANCES*
|
||||
*WARDEN*
|
||||
|
||||
* games
|
||||
check updated timestamps
|
||||
once a second?
|
||||
add a timestamp to each player
|
||||
after 30s issue warning (client)
|
||||
after 1m automove
|
||||
increment warnings
|
||||
after 3 warnings forfeit
|
||||
|
||||
* instances
|
||||
add timestamp to each player
|
||||
after 60s force ready
|
||||
|
||||
lobby opens
|
||||
add player
|
||||
add player
|
||||
|
||||
players ready
|
||||
on start -> vbox
|
||||
|
||||
*CLIENT*
|
||||
* general
|
||||
@ -76,6 +84,13 @@ make strike *really* hit first / resolve at same time?
|
||||
|
||||
## LATER
|
||||
* redis for game events
|
||||
|
||||
* store instances / games in redis?
|
||||
* not sure hwo to get sets of player games
|
||||
* set joined_games_$account [game_id]
|
||||
|
||||
* move player -> player
|
||||
|
||||
* chat
|
||||
* notifications
|
||||
* elo + leaderboards
|
||||
@ -106,7 +121,7 @@ $$$
|
||||
* empower on ko
|
||||
|
||||
# Mechanic Ideas
|
||||
teams
|
||||
players
|
||||
1v1 2v2 3v3
|
||||
|
||||
gem td style attr combinations
|
||||
|
||||
@ -122,7 +122,7 @@ impl CrypStat {
|
||||
// self.recalculate(specs)
|
||||
// }
|
||||
|
||||
pub fn recalculate(&mut self, specs: &Vec<Spec>, team_colours: &Colours) -> &mut CrypStat {
|
||||
pub fn recalculate(&mut self, specs: &Vec<Spec>, player_colours: &Colours) -> &mut CrypStat {
|
||||
let specs = specs
|
||||
.iter()
|
||||
.filter(|s| s.affects().contains(&self.stat))
|
||||
@ -131,7 +131,7 @@ impl CrypStat {
|
||||
|
||||
// applied with fold because it can be zeroed or multiplied
|
||||
// but still needs access to the base amount
|
||||
let value = specs.iter().fold(self.base, |acc, s| s.apply(acc, self.base, team_colours));
|
||||
let value = specs.iter().fold(self.base, |acc, s| s.apply(acc, self.base, player_colours));
|
||||
self.value = value;
|
||||
self.max = value;
|
||||
|
||||
@ -259,17 +259,17 @@ impl Cryp {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn apply_modifiers(&mut self, team_colours: &Colours) -> &mut Cryp {
|
||||
pub fn apply_modifiers(&mut self, player_colours: &Colours) -> &mut Cryp {
|
||||
self.specs.sort_unstable();
|
||||
|
||||
self.red_damage.recalculate(&self.specs, team_colours);
|
||||
self.red_life.recalculate(&self.specs, team_colours);
|
||||
self.blue_damage.recalculate(&self.specs, team_colours);
|
||||
self.blue_life.recalculate(&self.specs, team_colours);
|
||||
self.evasion.recalculate(&self.specs, team_colours);
|
||||
self.speed.recalculate(&self.specs, team_colours);
|
||||
self.green_damage.recalculate(&self.specs, team_colours);
|
||||
self.green_life.recalculate(&self.specs, team_colours);
|
||||
self.red_damage.recalculate(&self.specs, player_colours);
|
||||
self.red_life.recalculate(&self.specs, player_colours);
|
||||
self.blue_damage.recalculate(&self.specs, player_colours);
|
||||
self.blue_life.recalculate(&self.specs, player_colours);
|
||||
self.evasion.recalculate(&self.specs, player_colours);
|
||||
self.speed.recalculate(&self.specs, player_colours);
|
||||
self.green_damage.recalculate(&self.specs, player_colours);
|
||||
self.green_life.recalculate(&self.specs, player_colours);
|
||||
|
||||
self
|
||||
}
|
||||
@ -278,6 +278,11 @@ impl Cryp {
|
||||
self.green_life.value == 0
|
||||
}
|
||||
|
||||
pub fn force_ko(&mut self) -> &mut Cryp {
|
||||
self.green_life.value = 0;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn immune(&self, skill: Skill) -> Option<Immunity> {
|
||||
// also checked in resolve stage so shouldn't happen really
|
||||
if self.is_ko() {
|
||||
@ -836,21 +841,21 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cryp_team_modifiers_test() {
|
||||
fn cryp_player_modifiers_test() {
|
||||
let mut cryp = Cryp::new()
|
||||
.named(&"team player".to_string());
|
||||
.named(&"player player".to_string());
|
||||
|
||||
cryp.spec_add(Spec::RedDamageI).unwrap();
|
||||
cryp.spec_add(Spec::GreenDamageI).unwrap();
|
||||
cryp.spec_add(Spec::BlueDamageI).unwrap();
|
||||
|
||||
let team_colours = Colours {
|
||||
let player_colours = Colours {
|
||||
red: 5,
|
||||
green: 15,
|
||||
blue: 25,
|
||||
};
|
||||
|
||||
cryp.apply_modifiers(&team_colours);
|
||||
cryp.apply_modifiers(&player_colours);
|
||||
|
||||
assert!(cryp.red_damage.value == cryp.red_damage.base + cryp.red_damage.base.pct(20));
|
||||
assert!(cryp.green_damage.value == cryp.green_damage.base + cryp.green_damage.base.pct(40));
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -9,12 +9,16 @@ use failure::err_msg;
|
||||
|
||||
use std::iter;
|
||||
|
||||
// timekeeping
|
||||
use chrono::prelude::*;
|
||||
use chrono::Duration;
|
||||
|
||||
use rpc::{InstanceLobbyParams, InstanceJoinParams, InstanceReadyParams, InstanceStateParams};
|
||||
use account::Account;
|
||||
use player::{Player, Score, player_create, player_get, player_update};
|
||||
use player::{Player, player_create, player_get, player_global_update};
|
||||
use cryp::{Cryp, cryp_get};
|
||||
use mob::{instance_mobs};
|
||||
use game::{Game, Phase, Team, game_get, game_write, game_instance_new, game_instance_join, game_global_get, game_global_set};
|
||||
use game::{Game, Phase, game_get, game_write, game_instance_new};
|
||||
use vbox::{Var};
|
||||
use rpc::{RpcResult};
|
||||
use names::{name};
|
||||
@ -29,7 +33,7 @@ enum InstancePhase {
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
struct Round {
|
||||
player_ids: Vec<Uuid>,
|
||||
game_id: Uuid,
|
||||
game_id: Option<Uuid>,
|
||||
finished: bool,
|
||||
}
|
||||
|
||||
@ -41,8 +45,10 @@ pub struct Instance {
|
||||
rounds: Vec<Vec<Round>>,
|
||||
open: bool,
|
||||
max_players: usize,
|
||||
max_rounds: usize,
|
||||
password: Option<String>,
|
||||
pub name: String,
|
||||
phase_start: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl Instance {
|
||||
@ -54,8 +60,10 @@ impl Instance {
|
||||
phase: InstancePhase::Lobby,
|
||||
open: true,
|
||||
max_players: 2,
|
||||
max_rounds: 16,
|
||||
name: String::new(),
|
||||
password: None,
|
||||
phase_start: Utc::now(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,11 +75,44 @@ impl Instance {
|
||||
phase: InstancePhase::InProgress,
|
||||
open: false,
|
||||
max_players: 0,
|
||||
max_rounds: 1,
|
||||
name: "Global Matchmaking".to_string(),
|
||||
password: None,
|
||||
phase_start: Utc::now(),
|
||||
}
|
||||
}
|
||||
|
||||
fn phase_timed_out(&self) -> bool {
|
||||
Utc::now().signed_duration_since(self.phase_start).num_seconds() > 60
|
||||
}
|
||||
|
||||
fn timed_out_players(&self) -> Vec<Uuid> {
|
||||
self.players
|
||||
.iter()
|
||||
.filter(|p| !p.ready)
|
||||
.filter(|p| self.current_game_id(p.id).is_none())
|
||||
.map(|p| p.id)
|
||||
.collect::<Vec<Uuid>>()
|
||||
}
|
||||
|
||||
pub fn upkeep(mut self) -> (Instance, Vec<Game>) {
|
||||
if self.phase != InstancePhase::InProgress {
|
||||
return (self, vec![]);
|
||||
}
|
||||
|
||||
if !self.phase_timed_out() {
|
||||
return (self, vec![]);
|
||||
}
|
||||
|
||||
let new_games = self
|
||||
.timed_out_players()
|
||||
.iter()
|
||||
.filter_map(|p| self.player_ready(*p).unwrap())
|
||||
.collect::<Vec<Game>>();
|
||||
|
||||
(self, new_games)
|
||||
}
|
||||
|
||||
fn set_max_players(mut self, max: usize) -> Result<Instance, Error> {
|
||||
if max > 16 || max % 2 != 0 {
|
||||
return Err(err_msg("max players must be divisible by 2 and less than 16"));
|
||||
@ -90,12 +131,21 @@ impl Instance {
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn set_max_rounds(mut self, rounds: usize) -> Result<Instance, Error> {
|
||||
if rounds == 0 {
|
||||
return Err(err_msg("max rounds must be nonzero"));
|
||||
}
|
||||
|
||||
self.max_rounds = rounds;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn add_bots(mut self) -> Instance {
|
||||
self.open = false;
|
||||
self.players = iter::repeat_with(|| {
|
||||
let bot_id = Uuid::new_v4();
|
||||
let cryps = instance_mobs(bot_id);
|
||||
let mut p = Player::new(bot_id, self.id, &name(), cryps).set_bot(true);
|
||||
let mut p = Player::new(bot_id, &name(), cryps).set_bot(true);
|
||||
p.set_ready(true);
|
||||
p
|
||||
})
|
||||
@ -114,87 +164,98 @@ impl Instance {
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn player_update(mut self, player: Player, ignore_phase: bool) -> Result<Instance, Error> {
|
||||
if !ignore_phase && self.phase != InstancePhase::InProgress {
|
||||
return Err(format_err!("instance not in vbox phase ({:?})", self.phase));
|
||||
}
|
||||
|
||||
let i = self.players
|
||||
.iter()
|
||||
.position(|p| p.id == player.id)
|
||||
.ok_or(err_msg("player_id not found"))?;
|
||||
|
||||
self.players[i] = player;
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn player_ready(&mut self, player_id: Uuid) -> Result<&mut Instance, Error> {
|
||||
fn player_ready(&mut self, player_id: Uuid) -> Result<Option<Game>, Error> {
|
||||
if ![InstancePhase::InProgress, InstancePhase::Lobby].contains(&self.phase) {
|
||||
return Err(err_msg("instance not in start or vbox phase"));
|
||||
}
|
||||
|
||||
// LOBBY CHECKS
|
||||
if self.phase == InstancePhase::Lobby {
|
||||
let i = self.players
|
||||
.iter_mut()
|
||||
.position(|p| p.id == player_id)
|
||||
.ok_or(err_msg("player_id not found"))?;
|
||||
|
||||
let v = !self.players[i].ready;
|
||||
self.players[i].set_ready(v);
|
||||
|
||||
match self.can_start() {
|
||||
true => {
|
||||
self.start();
|
||||
return Ok(None);
|
||||
}
|
||||
false => return Ok(None),
|
||||
};
|
||||
}
|
||||
|
||||
// GAME PHASE READY
|
||||
let i = self.players
|
||||
.iter_mut()
|
||||
.position(|p| p.id == player_id)
|
||||
.ok_or(err_msg("player_id not found"))?;
|
||||
|
||||
if self.phase != InstancePhase::Lobby && self.players[i].cryps.iter().all(|c| c.skills.len() == 0) {
|
||||
return Err(err_msg("your cryps have no skills"));
|
||||
}
|
||||
|
||||
let v = !self.players[i].ready;
|
||||
self.players[i].set_ready(v);
|
||||
|
||||
if self.phase == InstancePhase::Lobby && self.can_start() {
|
||||
self.start();
|
||||
// start the game even if afk noobs have no skills
|
||||
if !self.phase_timed_out() && self.players[i].cryps.iter().all(|c| c.skills.len() == 0) {
|
||||
return Err(err_msg("your cryps have no skills"));
|
||||
}
|
||||
|
||||
Ok(self)
|
||||
// create a game object if both players are ready
|
||||
// this should only happen once
|
||||
|
||||
let all_ready = self.round_ready_check(player_id);
|
||||
|
||||
if !all_ready {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let game = self.create_round_game(player_id);
|
||||
|
||||
{
|
||||
let round_num = self.rounds.len() - 1;
|
||||
let current_round = self.rounds[round_num]
|
||||
.iter_mut()
|
||||
.find(|g| g.player_ids.contains(&player_id))
|
||||
.unwrap();
|
||||
|
||||
current_round.game_id = Some(game.id);
|
||||
}
|
||||
|
||||
return Ok(Some(game));
|
||||
|
||||
}
|
||||
|
||||
fn player_has_pve_game(&self, player_id: Uuid) -> bool {
|
||||
let opponent_id = self.current_round(player_id).player_ids
|
||||
.iter()
|
||||
.find(|p| **p != player_id)
|
||||
.expect("unable to find opponent");
|
||||
|
||||
return self.players
|
||||
.iter()
|
||||
.find(|p| p.id == *opponent_id)
|
||||
.expect("unable to find opponent")
|
||||
.bot;
|
||||
}
|
||||
|
||||
fn bot_vs_player_game(&self, player_id: Uuid) -> Result<Game, Error> {
|
||||
fn round_ready_check(&mut self, player_id: Uuid) -> bool {
|
||||
let current_round = self.current_round(player_id);
|
||||
let bot_id = current_round.player_ids.iter().find(|id| **id != player_id).unwrap();
|
||||
|
||||
let plr = self.players.clone().into_iter().find(|p| p.id == player_id).unwrap();
|
||||
let bot = self.players.clone().into_iter().find(|p| p.id == *bot_id).unwrap();
|
||||
self.players
|
||||
.iter()
|
||||
.filter(|p| current_round.player_ids.contains(&p.id))
|
||||
.all(|p| p.ready)
|
||||
}
|
||||
|
||||
// maybe just embed the games in the instance
|
||||
// but seems hella inefficient
|
||||
fn create_round_game(&self, player_id: Uuid) -> Game {
|
||||
let current_round = self.current_round(player_id);
|
||||
let mut game = Game::new();
|
||||
game.id = current_round.game_id;
|
||||
|
||||
game
|
||||
.set_team_num(2)
|
||||
.set_team_size(3)
|
||||
.set_player_num(2)
|
||||
.set_player_cryps(3)
|
||||
.set_instance(self.id);
|
||||
|
||||
// add the players
|
||||
let mut plr_team = Team::new(plr.id);
|
||||
plr_team.set_cryps(plr.cryps);
|
||||
// create the initiators player
|
||||
for player in self.players
|
||||
.clone()
|
||||
.into_iter()
|
||||
.filter(|p| current_round.player_ids.contains(&p.id)) {
|
||||
game.player_add(player).unwrap();
|
||||
}
|
||||
|
||||
let mut bot_team = Team::new(bot.id);
|
||||
bot_team.set_cryps(bot.cryps);
|
||||
bot_team.set_bot();
|
||||
|
||||
game
|
||||
.team_add(plr_team)?
|
||||
.team_add(bot_team)?;
|
||||
|
||||
game = game.start();
|
||||
|
||||
Ok(game)
|
||||
assert!(game.can_start());
|
||||
return game.start();
|
||||
}
|
||||
|
||||
fn can_start(&self) -> bool {
|
||||
@ -209,121 +270,47 @@ impl Instance {
|
||||
|
||||
fn next_round(&mut self) -> &mut Instance {
|
||||
self.phase = InstancePhase::InProgress;
|
||||
self.phase_start = Utc::now();
|
||||
|
||||
if self.rounds.len() >= self.max_rounds {
|
||||
return self.finish();
|
||||
}
|
||||
|
||||
self.players.iter_mut().for_each(|p| {
|
||||
p.ready = false;
|
||||
p.set_ready(false);
|
||||
p.vbox.fill();
|
||||
});
|
||||
|
||||
self.generate_rounds();
|
||||
self.bot_vbox_phase();
|
||||
self.bot_games_phase();
|
||||
self.bot_round_actions();
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
fn all_ready(&self) -> bool {
|
||||
self.players.iter().all(|p| p.ready)
|
||||
fn finish(&mut self) -> &mut Instance {
|
||||
self.phase = InstancePhase::Finished;
|
||||
self
|
||||
}
|
||||
|
||||
fn game_finished(&mut self, game: &Game) -> Result<&mut Instance, Error> {
|
||||
let round_num = self.rounds.len() - 1;
|
||||
self.rounds[round_num]
|
||||
.iter_mut()
|
||||
.find(|r| r.game_id == game.id)
|
||||
.ok_or(err_msg("could not find matchup in current round"))?
|
||||
.finished = true;
|
||||
|
||||
let winner = game.winner().ok_or(err_msg("game not finished"))?;
|
||||
|
||||
for team in game.teams.iter() {
|
||||
let mut player = self.account_player(team.id)?;
|
||||
match team.id == winner.id {
|
||||
true => player.add_win(),
|
||||
false => player.add_loss(),
|
||||
};
|
||||
}
|
||||
|
||||
if self.all_games_finished() {
|
||||
self.next_round();
|
||||
}
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn all_games_finished(&self) -> bool {
|
||||
match self.rounds.last() {
|
||||
Some(r) => r.iter().all(|g| g.finished),
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
||||
fn bot_vbox_phase(&mut self) -> &mut Instance {
|
||||
fn bot_round_actions(&mut self) -> &mut Instance {
|
||||
for bot in self.players.iter_mut().filter(|p| p.bot) {
|
||||
bot.vbox.fill();
|
||||
bot.autobuy();
|
||||
bot.set_ready(true);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
let games = self.players
|
||||
.clone()
|
||||
.iter()
|
||||
.filter(|b| b.bot)
|
||||
.filter_map(|b| self.player_ready(b.id).unwrap())
|
||||
.collect::<Vec<Game>>();
|
||||
|
||||
fn bot_games_phase(&mut self) -> &mut Instance {
|
||||
if self.phase != InstancePhase::InProgress {
|
||||
panic!("instance not in progress phase");
|
||||
}
|
||||
|
||||
let r = self.rounds.len() - 1;
|
||||
// println!("round num {:?}", r);
|
||||
// println!("{:?}", self.rounds[r]);
|
||||
for mut round in self.rounds[r].iter_mut() {
|
||||
if self.players
|
||||
.iter()
|
||||
.filter(|p| round.player_ids.contains(&p.id) && p.bot && p.ready)
|
||||
.count() == 2 {
|
||||
// println!("should play a game between {:?}", round.player_ids);
|
||||
let a = self.players.clone().into_iter().find(|p| p.id == round.player_ids[0]).unwrap();
|
||||
let b = self.players.clone().into_iter().find(|p| p.id == round.player_ids[1]).unwrap();
|
||||
|
||||
// println!("{:?} vs {:?}", a.name, b.name);
|
||||
|
||||
let mut game = Game::new();
|
||||
game
|
||||
.set_team_num(2)
|
||||
.set_team_size(3);
|
||||
|
||||
// add the players
|
||||
let mut a_team = Team::new(a.id);
|
||||
a_team.set_cryps(a.cryps);
|
||||
a_team.set_bot();
|
||||
|
||||
let mut b_team = Team::new(b.id);
|
||||
b_team.set_cryps(b.cryps);
|
||||
b_team.set_bot();
|
||||
|
||||
game
|
||||
.team_add(a_team).unwrap()
|
||||
.team_add(b_team).unwrap();
|
||||
|
||||
game = game.start();
|
||||
|
||||
assert!(game.finished());
|
||||
let winner = match game.winner() {
|
||||
Some(w) => w,
|
||||
None => panic!("game has no winner {:?}", game),
|
||||
};
|
||||
|
||||
round.finished = true;
|
||||
|
||||
for team in game.teams.iter() {
|
||||
let mut player = self.players.iter_mut().find(|p| p.id == team.id).unwrap();
|
||||
match team.id == winner.id {
|
||||
true => player.add_win(),
|
||||
false => player.add_loss(),
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
for game in games {
|
||||
if game.finished() {
|
||||
self.game_finished(&game).unwrap();
|
||||
} else {
|
||||
println!("{:?} unfishededes", game);
|
||||
}
|
||||
}
|
||||
|
||||
self
|
||||
@ -350,7 +337,7 @@ impl Instance {
|
||||
.enumerate()
|
||||
.map(|(i, id)| Round {
|
||||
player_ids: vec![*id, matched_players[np - (i + 1)]],
|
||||
game_id: Uuid::new_v4(),
|
||||
game_id: None,
|
||||
finished: false,
|
||||
})
|
||||
.collect::<Vec<Round>>();
|
||||
@ -371,32 +358,60 @@ impl Instance {
|
||||
current_round
|
||||
}
|
||||
|
||||
fn current_game(&mut self, player_id: Uuid) -> Option<Uuid> {
|
||||
fn current_game_id(&self, player_id: Uuid) -> Option<Uuid> {
|
||||
if self.phase == InstancePhase::Lobby {
|
||||
return None;
|
||||
}
|
||||
|
||||
let current_round = self.current_round(player_id);
|
||||
|
||||
let can_start = self.players
|
||||
.iter()
|
||||
.filter(|p| current_round.player_ids.contains(&p.id))
|
||||
.all(|p| p.ready);
|
||||
|
||||
match can_start {
|
||||
true => Some(current_round.game_id),
|
||||
false => None,
|
||||
if current_round.finished || current_round.game_id.is_none() {
|
||||
return None;
|
||||
}
|
||||
|
||||
return current_round.game_id;
|
||||
}
|
||||
|
||||
fn scores(&self) -> Vec<(String, Score)> {
|
||||
let mut scores = self.players.iter()
|
||||
.map(|p| (p.name.clone(), p.score))
|
||||
.collect::<Vec<(String, Score)>>();
|
||||
scores.sort_unstable_by_key(|s| s.1.wins);
|
||||
scores.reverse();
|
||||
fn game_finished(&mut self, game: &Game) -> Result<&mut Instance, Error> {
|
||||
let round_num = self.rounds.len() - 1;
|
||||
self.rounds[round_num]
|
||||
.iter_mut()
|
||||
.filter(|r| r.game_id.is_some())
|
||||
.find(|r| r.game_id.unwrap() == game.id)
|
||||
.ok_or(err_msg("could not find matchup in current round"))?
|
||||
.finished = true;
|
||||
|
||||
scores
|
||||
// if you don't win, you lose
|
||||
// ties can happen if both players forfeit
|
||||
let winner_id = match game.winner() {
|
||||
Some(w) => w.id,
|
||||
None => Uuid::nil(),
|
||||
};
|
||||
|
||||
for player in game.players.iter() {
|
||||
let mut player = self.account_player(player.id)?;
|
||||
match player.id == winner_id {
|
||||
true => player.add_win(),
|
||||
false => player.add_loss(),
|
||||
};
|
||||
}
|
||||
|
||||
if self.all_games_finished() {
|
||||
self.next_round();
|
||||
}
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn all_ready(&self) -> bool {
|
||||
self.players.iter().all(|p| p.ready)
|
||||
}
|
||||
|
||||
fn all_games_finished(&self) -> bool {
|
||||
match self.rounds.last() {
|
||||
Some(r) => r.iter().all(|g| g.finished),
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
||||
// PLAYER ACTIONS
|
||||
@ -407,37 +422,54 @@ impl Instance {
|
||||
.ok_or(err_msg("account not in instance"))
|
||||
}
|
||||
|
||||
pub fn vbox_action_allowed(&self, account: Uuid) -> Result<(), Error> {
|
||||
if self.phase == InstancePhase::Lobby {
|
||||
return Err(err_msg("game not yet started"));
|
||||
}
|
||||
if self.current_game_id(account).is_some() {
|
||||
return Err(err_msg("you cannot perform vbox actions while in a game"));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn vbox_discard(mut self, account: Uuid) -> Result<Instance, Error> {
|
||||
self.vbox_action_allowed(account)?;
|
||||
self.account_player(account)?
|
||||
.vbox_discard()?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn vbox_accept(mut self, account: Uuid, group: usize, index: usize) -> Result<Instance, Error> {
|
||||
self.vbox_action_allowed(account)?;
|
||||
self.account_player(account)?
|
||||
.vbox_accept(group, index)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn vbox_combine(mut self, account: Uuid, indices: Vec<usize>) -> Result<Instance, Error> {
|
||||
self.vbox_action_allowed(account)?;
|
||||
self.account_player(account)?
|
||||
.vbox_combine(indices)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn vbox_reclaim(mut self, account: Uuid, index: usize) -> Result<Instance, Error> {
|
||||
self.vbox_action_allowed(account)?;
|
||||
self.account_player(account)?
|
||||
.vbox_reclaim(index)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn vbox_apply(mut self, account: Uuid, index: usize, cryp_id: Uuid) -> Result<Instance, Error> {
|
||||
self.vbox_action_allowed(account)?;
|
||||
self.account_player(account)?
|
||||
.vbox_apply(index, cryp_id)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn vbox_unequip(mut self, account: Uuid, target: Var, cryp_id: Uuid) -> Result<Instance, Error> {
|
||||
self.vbox_action_allowed(account)?;
|
||||
self.account_player(account)?
|
||||
.vbox_unequip(target, cryp_id)?;
|
||||
Ok(self)
|
||||
@ -485,7 +517,8 @@ pub fn instance_get(tx: &mut Transaction, instance_id: Uuid) -> Result<Instance,
|
||||
let query = "
|
||||
SELECT *
|
||||
FROM instances
|
||||
WHERE id = $1;
|
||||
WHERE id = $1
|
||||
FOR UPDATE;
|
||||
";
|
||||
|
||||
let result = tx
|
||||
@ -542,6 +575,33 @@ pub fn instance_get_open(tx: &mut Transaction) -> Result<Instance, Error> {
|
||||
return Ok(instance);
|
||||
}
|
||||
|
||||
pub fn instances_need_upkeep(tx: &mut Transaction) -> Result<Vec<Instance>, Error> {
|
||||
let query = "
|
||||
SELECT data, id
|
||||
FROM instances
|
||||
WHERE id != '00000000-0000-0000-0000-000000000000';
|
||||
";
|
||||
|
||||
let result = tx
|
||||
.query(query, &[])?;
|
||||
|
||||
let mut list = vec![];
|
||||
|
||||
for row in result.into_iter() {
|
||||
let bytes: Vec<u8> = row.get(0);
|
||||
let id = row.get(1);
|
||||
|
||||
match from_slice::<Instance>(&bytes) {
|
||||
Ok(i) => list.push(i),
|
||||
Err(_e) => {
|
||||
instance_delete(tx, id)?;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return Ok(list);
|
||||
}
|
||||
|
||||
pub fn instance_new(params: InstanceLobbyParams, tx: &mut Transaction, account: &Account) -> Result<Instance, Error> {
|
||||
let mut instance = match params.players {
|
||||
1 => Instance::new()
|
||||
@ -568,84 +628,56 @@ pub fn instance_join(params: InstanceJoinParams, tx: &mut Transaction, account:
|
||||
.collect::<Result<Vec<Cryp>, Error>>()?;
|
||||
|
||||
if cryps.len() != 3 {
|
||||
return Err(format_err!("incorrect team size. ({:})", 3));
|
||||
return Err(format_err!("incorrect player size. ({:})", 3));
|
||||
}
|
||||
|
||||
let player = player_create(tx, Player::new(account.id, instance.id, &account.name, cryps), account)?;
|
||||
let player = player_create(tx, Player::new(account.id, &account.name, cryps), instance.id, account)?;
|
||||
|
||||
instance.add_player(player)?;
|
||||
|
||||
instance_update(tx, instance)
|
||||
}
|
||||
|
||||
pub fn instance_ready_global(tx: &mut Transaction, _account: &Account, player: Player) -> Result<Game, Error> {
|
||||
// get the game
|
||||
let game = match game_global_get(tx) {
|
||||
Ok(g) => {
|
||||
println!("received global game {:?}", g.id);
|
||||
// if there is one try to join
|
||||
match game_instance_join(tx, player.clone(), g.id) {
|
||||
Ok(g) => g,
|
||||
// if fails make a new one
|
||||
Err(_e) => game_instance_new(tx, vec![player], Uuid::new_v4(), Uuid::nil())?,
|
||||
}
|
||||
},
|
||||
// if not found make a new one
|
||||
Err(_) => game_instance_new(tx, vec![player], Uuid::new_v4(), Uuid::nil())?,
|
||||
};
|
||||
// pub fn instance_ready_global(tx: &mut Transaction, _account: &Account, player: Player) -> Result<Game, Error> {
|
||||
// // get the game
|
||||
// let game = match game_global_get(tx) {
|
||||
// Ok(g) => {
|
||||
// println!("received global game {:?}", g.id);
|
||||
// // if there is one try to join
|
||||
// match game_instance_join(tx, player.clone(), g.id) {
|
||||
// Ok(g) => g,
|
||||
// // if fails make a new one
|
||||
// Err(_e) => game_instance_new(tx, vec![player], Uuid::new_v4(), Uuid::nil())?,
|
||||
// }
|
||||
// },
|
||||
// // if not found make a new one
|
||||
// Err(_) => game_instance_new(tx, vec![player], Uuid::new_v4(), Uuid::nil())?,
|
||||
// };
|
||||
|
||||
// set the current game
|
||||
game_global_set(tx, &game)?;
|
||||
Ok(game)
|
||||
}
|
||||
|
||||
pub fn instance_scores(params: InstanceReadyParams, tx: &mut Transaction, _account: &Account) -> Result<Vec<(String, Score)>, Error> {
|
||||
let scores = instance_get(tx, params.instance_id)?.scores();
|
||||
Ok(scores)
|
||||
}
|
||||
// // set the current game
|
||||
// game_global_set(tx, &game)?;
|
||||
// Ok(game)
|
||||
// }
|
||||
|
||||
pub fn instance_ready(params: InstanceReadyParams, tx: &mut Transaction, account: &Account) -> Result<Instance, Error> {
|
||||
let mut instance = instance_get(tx, params.instance_id)?;
|
||||
let player_id = instance.account_player(account.id)?.id;
|
||||
instance.player_ready(player_id)?;
|
||||
|
||||
if let Some(game_id) = instance.current_game(player_id) {
|
||||
match instance.player_has_pve_game(player_id) {
|
||||
true => match game_get(tx, game_id) {
|
||||
Ok(g) => g,
|
||||
Err(_) => {
|
||||
let game = instance.bot_vs_player_game(player_id)?;
|
||||
game_write(&game, tx)?;
|
||||
game
|
||||
},
|
||||
},
|
||||
false => {
|
||||
let opponent_id = *instance
|
||||
.current_round(account.id)
|
||||
.player_ids
|
||||
.iter()
|
||||
.find(|p| **p != account.id)
|
||||
.expect("could not find opponent");
|
||||
|
||||
let a = instance.account_player(account.id)?.clone();
|
||||
let b = instance.account_player(opponent_id)?.clone();
|
||||
let teams = vec![a, b];
|
||||
game_instance_new(tx, teams, game_id, instance.id)?
|
||||
}
|
||||
};
|
||||
if let Some(game) = instance.player_ready(player_id)? {
|
||||
game_write(tx, &game)?;
|
||||
}
|
||||
|
||||
instance_update(tx, instance)
|
||||
}
|
||||
|
||||
pub fn instance_state(params: InstanceStateParams, tx: &mut Transaction, account: &Account) -> Result<RpcResult, Error> {
|
||||
let mut instance = instance_get(tx, params.instance_id)?;
|
||||
let instance = instance_get(tx, params.instance_id)?;
|
||||
|
||||
if let Some(game_id) = instance.current_game(account.id) {
|
||||
if let Some(game_id) = instance.current_game_id(account.id) {
|
||||
let game = game_get(tx, game_id)?;
|
||||
|
||||
// return the game until it's finished
|
||||
if game.phase != Phase::Finish {
|
||||
|
||||
return Ok(RpcResult::GameState(game))
|
||||
}
|
||||
}
|
||||
@ -656,14 +688,14 @@ pub fn instance_state(params: InstanceStateParams, tx: &mut Transaction, account
|
||||
pub fn global_game_finished(tx: &mut Transaction, game: &Game) -> Result<(), Error> {
|
||||
let winner = game.winner().ok_or(err_msg("game not finished"))?;
|
||||
|
||||
for team in game.teams.iter() {
|
||||
let mut player = player_get(tx, team.id, Uuid::nil())?;
|
||||
match team.id == winner.id {
|
||||
for player in game.players.iter() {
|
||||
let mut player = player_get(tx, player.id, Uuid::nil())?;
|
||||
match player.id == winner.id {
|
||||
true => player.add_win(),
|
||||
false => player.add_loss(),
|
||||
};
|
||||
player.vbox.fill();
|
||||
player_update(tx, player, true)?;
|
||||
player_global_update(tx, player, true)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -687,11 +719,12 @@ mod tests {
|
||||
fn instance_pve_test() {
|
||||
let mut instance = Instance::new()
|
||||
.set_max_players(16).expect("unable to set max players")
|
||||
.set_max_rounds(2).expect("max rounds failure")
|
||||
.add_bots();
|
||||
|
||||
let player_account = Uuid::new_v4();
|
||||
let cryps = instance_mobs(player_account);
|
||||
let player = Player::new(player_account, instance.id, &"test".to_string(), cryps).set_bot(true);
|
||||
let player = Player::new(player_account, &"test".to_string(), cryps).set_bot(true);
|
||||
let player_id = player.id;
|
||||
|
||||
instance.add_player(player).expect("could not add player");
|
||||
@ -699,21 +732,9 @@ mod tests {
|
||||
assert_eq!(instance.phase, InstancePhase::Lobby);
|
||||
instance.player_ready(player_id).unwrap();
|
||||
|
||||
assert_eq!(instance.phase, InstancePhase::InProgress);
|
||||
assert_eq!(instance.phase, InstancePhase::Finished);
|
||||
assert_eq!(instance.rounds[0].len(), 8);
|
||||
|
||||
instance.player_ready(player_id).unwrap();
|
||||
|
||||
assert!(instance.all_games_finished());
|
||||
instance.next_round();
|
||||
|
||||
instance.player_ready(player_id).unwrap();
|
||||
|
||||
instance.next_round();
|
||||
|
||||
instance.player_ready(player_id).unwrap();
|
||||
|
||||
assert_eq!(instance.rounds.len(), 3);
|
||||
assert_eq!(instance.rounds.len(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -721,7 +742,7 @@ mod tests {
|
||||
let instance = Instance::new();
|
||||
let player_account = Uuid::new_v4();
|
||||
let cryps = instance_mobs(player_account);
|
||||
let _player = Player::new(player_account, instance.id, &"test".to_string(), cryps).set_bot(true);
|
||||
let _player = Player::new(player_account, &"test".to_string(), cryps).set_bot(true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -734,7 +755,7 @@ mod tests {
|
||||
|
||||
let player_account = Uuid::new_v4();
|
||||
let cryps = instance_mobs(player_account);
|
||||
let player = Player::new(player_account, instance.id, &"a".to_string(), cryps);
|
||||
let player = Player::new(player_account, &"a".to_string(), cryps);
|
||||
let a_id = player.id;
|
||||
|
||||
instance.add_player(player).expect("could not add player");
|
||||
@ -742,7 +763,7 @@ mod tests {
|
||||
|
||||
let player_account = Uuid::new_v4();
|
||||
let cryps = instance_mobs(player_account);
|
||||
let player = Player::new(player_account, instance.id, &"b".to_string(), cryps);
|
||||
let player = Player::new(player_account, &"b".to_string(), cryps);
|
||||
let b_id = player.id;
|
||||
|
||||
instance.add_player(player).expect("could not add player");
|
||||
@ -755,5 +776,55 @@ mod tests {
|
||||
assert_eq!(instance.phase, InstancePhase::InProgress);
|
||||
|
||||
assert!(!instance.can_start());
|
||||
|
||||
instance.players[0].autobuy();
|
||||
instance.players[1].autobuy();
|
||||
|
||||
instance.player_ready(a_id).expect("a ready");
|
||||
let game = instance.player_ready(b_id).expect("b ready");
|
||||
|
||||
assert!(game.is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn instance_upkeep_test() {
|
||||
let mut instance = Instance::new()
|
||||
.set_max_players(2)
|
||||
.expect("could not create instance");
|
||||
|
||||
let player_account = Uuid::new_v4();
|
||||
let cryps = instance_mobs(player_account);
|
||||
let player = Player::new(player_account, &"a".to_string(), cryps);
|
||||
let a_id = player.id;
|
||||
|
||||
instance.add_player(player).expect("could not add player");
|
||||
assert!(!instance.can_start());
|
||||
|
||||
let player_account = Uuid::new_v4();
|
||||
let cryps = instance_mobs(player_account);
|
||||
let player = Player::new(player_account, &"b".to_string(), cryps);
|
||||
let b_id = player.id;
|
||||
instance.add_player(player).expect("could not add player");
|
||||
|
||||
instance.players[0].autobuy();
|
||||
|
||||
instance.player_ready(a_id).expect("a ready");
|
||||
instance.player_ready(b_id).expect("b ready");
|
||||
|
||||
instance.phase_start = Utc::now().checked_sub_signed(Duration::seconds(61)).unwrap();
|
||||
|
||||
let (mut instance, new_games) = instance.upkeep();
|
||||
|
||||
assert_eq!(new_games.len(), 1);
|
||||
|
||||
let game = &new_games[0];
|
||||
assert!(game.finished());
|
||||
|
||||
instance.game_finished(game).unwrap();
|
||||
|
||||
assert_eq!(instance.rounds.len(), 2);
|
||||
assert!(instance.players.iter().all(|p| !p.ready));
|
||||
|
||||
println!("{:#?}", instance);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,36 +3,32 @@ extern crate uuid;
|
||||
extern crate tungstenite;
|
||||
extern crate env_logger;
|
||||
extern crate bcrypt;
|
||||
extern crate chrono;
|
||||
|
||||
extern crate dotenv;
|
||||
// extern crate petgraph;
|
||||
extern crate postgres;
|
||||
extern crate r2d2;
|
||||
extern crate r2d2_postgres;
|
||||
|
||||
extern crate serde;
|
||||
extern crate serde_cbor;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[macro_use] extern crate serde_derive;
|
||||
#[macro_use] extern crate failure;
|
||||
// #[macro_use] extern crate failure_derive;
|
||||
|
||||
mod cryp;
|
||||
mod game;
|
||||
mod net;
|
||||
mod skill;
|
||||
mod spec;
|
||||
// mod passives;
|
||||
mod names;
|
||||
mod rpc;
|
||||
mod account;
|
||||
mod instance;
|
||||
mod player;
|
||||
// mod zone;
|
||||
mod mob;
|
||||
mod util;
|
||||
mod vbox;
|
||||
mod warden;
|
||||
|
||||
use dotenv::dotenv;
|
||||
use net::{start};
|
||||
|
||||
@ -21,19 +21,19 @@ pub fn generate_mob() -> Cryp {
|
||||
return mob;
|
||||
}
|
||||
|
||||
// fn quick_game(team_size: usize) -> Vec<Cryp> {
|
||||
// fn quick_game(player_size: usize) -> Vec<Cryp> {
|
||||
// iter::repeat_with(||
|
||||
// generate_mob()
|
||||
// .set_account(Uuid::nil())
|
||||
// .learn(Skill::Attack))
|
||||
// .take(team_size)
|
||||
// .take(player_size)
|
||||
// .collect::<Vec<Cryp>>()
|
||||
// }
|
||||
|
||||
pub fn instance_mobs(team_id: Uuid) -> Vec<Cryp> {
|
||||
pub fn instance_mobs(player_id: Uuid) -> Vec<Cryp> {
|
||||
iter::repeat_with(||
|
||||
generate_mob()
|
||||
.set_account(team_id))
|
||||
.set_account(player_id))
|
||||
// .learn(Skill::Attack))
|
||||
.take(3)
|
||||
.collect::<Vec<Cryp>>()
|
||||
@ -104,14 +104,14 @@ pub fn instance_mobs(team_id: Uuid) -> Vec<Cryp> {
|
||||
// }
|
||||
|
||||
|
||||
// pub fn generate_mob_team(mode: GameMode, cryps: &Vec<Cryp>) -> Team {
|
||||
// let mut mob_team = Team::new(Uuid::nil());
|
||||
// pub fn generate_mob_player(mode: GameMode, cryps: &Vec<Cryp>) -> Player {
|
||||
// let mut mob_player = Player::new(Uuid::nil());
|
||||
|
||||
// let cryp_lvl = cryps.iter().max_by_key(|c| c.lvl).unwrap().lvl;
|
||||
// let team_size = cryps.len();
|
||||
// let player_size = cryps.len();
|
||||
|
||||
// let mobs = match mode {
|
||||
// GameMode::Normal => quick_game(cryp_lvl, team_size),
|
||||
// GameMode::Normal => quick_game(cryp_lvl, player_size),
|
||||
// GameMode::Zone3v2Attack => zone_3v2_attack(cryp_lvl),
|
||||
// GameMode::Zone2v2Caster => zone_2v2_caster(cryp_lvl),
|
||||
// GameMode::Zone3v3MeleeMiniboss => zone_3v3_melee_miniboss(cryp_lvl),
|
||||
@ -119,8 +119,8 @@ pub fn instance_mobs(team_id: Uuid) -> Vec<Cryp> {
|
||||
// _ => panic!("{:?} not handled for pve mobs", mode),
|
||||
// };
|
||||
|
||||
// mob_team.set_cryps(mobs);
|
||||
// mob_player.set_cryps(mobs);
|
||||
|
||||
// return mob_team;
|
||||
// return mob_player;
|
||||
|
||||
// }
|
||||
|
||||
@ -7,7 +7,8 @@ use std::net::{TcpListener, TcpStream};
|
||||
use serde_cbor::{to_vec};
|
||||
|
||||
use std::env;
|
||||
use std::thread::spawn;
|
||||
use std::thread::{spawn, sleep};
|
||||
use std::time::Duration;
|
||||
|
||||
use r2d2::{Pool};
|
||||
use r2d2::{PooledConnection};
|
||||
@ -19,6 +20,7 @@ pub type Db = PooledConnection<PostgresConnectionManager>;
|
||||
|
||||
use rpc::{Rpc};
|
||||
use util::{startup};
|
||||
use warden::{warden};
|
||||
|
||||
// struct Server {
|
||||
// client: WebSocket<TcpStream>,
|
||||
@ -69,9 +71,22 @@ pub fn start() {
|
||||
}
|
||||
|
||||
let server = TcpListener::bind("0.0.0.0:40000").unwrap();
|
||||
|
||||
let warden_pool = pool.clone();
|
||||
spawn(move || {
|
||||
loop {
|
||||
let db_connection = warden_pool.get().expect("unable to get db connection");
|
||||
if let Err(e) = warden(db_connection) {
|
||||
println!("{:?}", e);
|
||||
}
|
||||
sleep(Duration::new(5, 0));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
for stream in server.incoming() {
|
||||
let db = pool.clone();
|
||||
spawn (move || {
|
||||
spawn(move || {
|
||||
let mut websocket = accept(stream.unwrap()).unwrap();
|
||||
let rpc = Rpc {};
|
||||
|
||||
|
||||
@ -13,6 +13,7 @@ use cryp::{Cryp, Colours, cryp_get};
|
||||
use vbox::{Vbox, Var, VarEffect};
|
||||
use rpc::{PlayerCrypsSetParams};
|
||||
use instance::{Instance, instance_get, instance_update};
|
||||
use skill::{Effect};
|
||||
|
||||
const DISCARD_COST: u16 = 5;
|
||||
|
||||
@ -25,26 +26,26 @@ pub struct Score {
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
pub struct Player {
|
||||
pub id: Uuid,
|
||||
pub instance: Uuid,
|
||||
pub name: String,
|
||||
pub vbox: Vbox,
|
||||
pub score: Score,
|
||||
pub cryps: Vec<Cryp>,
|
||||
pub bot: bool,
|
||||
pub ready: bool,
|
||||
pub warnings: u8,
|
||||
}
|
||||
|
||||
impl Player {
|
||||
pub fn new(account: Uuid, instance: Uuid, name: &String, cryps: Vec<Cryp>) -> Player {
|
||||
pub fn new(account: Uuid, name: &String, cryps: Vec<Cryp>) -> Player {
|
||||
Player {
|
||||
id: account,
|
||||
instance,
|
||||
name: name.clone(),
|
||||
vbox: Vbox::new(account, instance),
|
||||
vbox: Vbox::new(),
|
||||
score: Score { wins: 0, losses: 0 },
|
||||
cryps,
|
||||
bot: false,
|
||||
ready: false,
|
||||
warnings: 0,
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,16 +59,26 @@ impl Player {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_warning(&mut self) -> &mut Player {
|
||||
self.warnings += 1;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn forfeit(&mut self) -> &mut Player {
|
||||
for cryp in self.cryps.iter_mut() {
|
||||
cryp.force_ko();
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_win(&mut self) -> &mut Player {
|
||||
self.score.wins += 1;
|
||||
self.set_ready(false);
|
||||
self.vbox.balance_add(12);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_loss(&mut self) -> &mut Player {
|
||||
self.score.losses += 1;
|
||||
self.set_ready(false);
|
||||
self.vbox.balance_add(9);
|
||||
self
|
||||
}
|
||||
@ -205,8 +216,8 @@ impl Player {
|
||||
}
|
||||
|
||||
// now the var has been applied
|
||||
// recalculate the stats of the whole team
|
||||
let team_colours = self.cryps.iter().fold(Colours::new(), |tc, c| {
|
||||
// recalculate the stats of the whole player
|
||||
let player_colours = self.cryps.iter().fold(Colours::new(), |tc, c| {
|
||||
Colours {
|
||||
red: tc.red + c.colours.red,
|
||||
green: tc.green + c.colours.green,
|
||||
@ -215,7 +226,7 @@ impl Player {
|
||||
});
|
||||
|
||||
for cryp in self.cryps.iter_mut() {
|
||||
cryp.apply_modifiers(&team_colours);
|
||||
cryp.apply_modifiers(&player_colours);
|
||||
}
|
||||
|
||||
Ok(self)
|
||||
@ -241,8 +252,8 @@ impl Player {
|
||||
}
|
||||
|
||||
// now the var has been applied
|
||||
// recalculate the stats of the whole team
|
||||
let team_colours = self.cryps.iter().fold(Colours::new(), |tc, c| {
|
||||
// recalculate the stats of the whole player
|
||||
let player_colours = self.cryps.iter().fold(Colours::new(), |tc, c| {
|
||||
Colours {
|
||||
red: tc.red + c.colours.red,
|
||||
green: tc.green + c.colours.green,
|
||||
@ -251,7 +262,7 @@ impl Player {
|
||||
});
|
||||
|
||||
for cryp in self.cryps.iter_mut() {
|
||||
cryp.apply_modifiers(&team_colours);
|
||||
cryp.apply_modifiers(&player_colours);
|
||||
}
|
||||
|
||||
self.vbox.bound.push(target);
|
||||
@ -259,6 +270,32 @@ impl Player {
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
// GAME METHODS
|
||||
pub fn skills_required(&self) -> usize {
|
||||
let required = self.cryps.iter()
|
||||
.filter(|c| !c.is_ko())
|
||||
.filter(|c| c.available_skills().len() > 0)
|
||||
.collect::<Vec<&Cryp>>().len();
|
||||
// println!("{:} requires {:} skills this turn", self.id, required);
|
||||
return required;
|
||||
}
|
||||
|
||||
pub fn taunting(&self) -> Option<&Cryp> {
|
||||
self.cryps.iter()
|
||||
.find(|c| c.affected(Effect::Taunt))
|
||||
}
|
||||
|
||||
pub fn set_cryps(&mut self, mut cryps: Vec<Cryp>) -> &mut Player {
|
||||
cryps.sort_unstable_by_key(|c| c.id);
|
||||
self.cryps = cryps;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn cryp_by_id(&mut self, id: Uuid) -> Option<&mut Cryp> {
|
||||
self.cryps.iter_mut().find(|c| c.id == id)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn player_get(tx: &mut Transaction, account_id: Uuid, instance_id: Uuid) -> Result<Player, Error> {
|
||||
@ -266,7 +303,8 @@ pub fn player_get(tx: &mut Transaction, account_id: Uuid, instance_id: Uuid) ->
|
||||
SELECT *
|
||||
FROM players
|
||||
WHERE account = $1
|
||||
AND instance = $2;
|
||||
AND instance = $2
|
||||
FOR UPDATE;
|
||||
";
|
||||
|
||||
let result = tx
|
||||
@ -284,7 +322,7 @@ pub fn player_get(tx: &mut Transaction, account_id: Uuid, instance_id: Uuid) ->
|
||||
return Ok(data);
|
||||
}
|
||||
|
||||
pub fn player_create(tx: &mut Transaction, player: Player, account: &Account) -> Result<Player, Error> {
|
||||
pub fn player_create(tx: &mut Transaction, player: Player, instance: Uuid, account: &Account) -> Result<Player, Error> {
|
||||
let player_bytes = to_vec(&player)?;
|
||||
|
||||
let query = "
|
||||
@ -294,27 +332,19 @@ pub fn player_create(tx: &mut Transaction, player: Player, account: &Account) ->
|
||||
";
|
||||
|
||||
let result = tx
|
||||
.query(query, &[&Uuid::new_v4(), &player.instance, &account.id, &player_bytes])?;
|
||||
.query(query, &[&Uuid::new_v4(), &instance, &account.id, &player_bytes])?;
|
||||
|
||||
let _returned = result.iter().next().expect("no row written");
|
||||
|
||||
println!("wrote player {:} joined instance: {:}", account.name, player.instance);
|
||||
println!("wrote player {:} joined instance: {:}", account.name, instance);
|
||||
|
||||
return Ok(player);
|
||||
}
|
||||
|
||||
pub fn player_update(tx: &mut Transaction, mut player: Player, ignore_phase: bool) -> Result<Player, Error> {
|
||||
pub fn player_global_update(tx: &mut Transaction, mut player: Player, ignore_phase: bool) -> Result<Player, Error> {
|
||||
// sort vbox for niceness
|
||||
player.vbox.bound.sort_unstable();
|
||||
|
||||
// update the instance this player is associated with
|
||||
// if not a global player
|
||||
if player.instance != Uuid::nil() {
|
||||
let instance = instance_get(tx, player.instance)?
|
||||
.player_update(player.clone(), ignore_phase)?;
|
||||
instance_update(tx, instance)?;
|
||||
}
|
||||
|
||||
let bytes = to_vec(&player)?;
|
||||
|
||||
let query = "
|
||||
@ -353,7 +383,7 @@ pub fn player_delete(tx: &mut Transaction, id: Uuid) -> Result<(), Error> {
|
||||
|
||||
pub fn player_mm_cryps_set(params: PlayerCrypsSetParams, tx: &mut Transaction, account: &Account) -> Result<Instance, Error> {
|
||||
if params.cryp_ids.len() != 3 {
|
||||
return Err(err_msg("team size is 3"));
|
||||
return Err(err_msg("player size is 3"));
|
||||
}
|
||||
|
||||
let cryps = params.cryp_ids
|
||||
@ -364,11 +394,11 @@ pub fn player_mm_cryps_set(params: PlayerCrypsSetParams, tx: &mut Transaction, a
|
||||
let player = match player_get(tx, account.id, Uuid::nil()) {
|
||||
Ok(mut p) => {
|
||||
p.cryps = cryps;
|
||||
p.vbox = Vbox::new(account.id, Uuid::nil());
|
||||
player_update(tx, p, false)?
|
||||
p.vbox = Vbox::new();
|
||||
player_global_update(tx, p, false)?
|
||||
},
|
||||
Err(_) => {
|
||||
player_create(tx, Player::new(account.id, Uuid::nil(), &account.name, cryps), &account)?
|
||||
player_create(tx, Player::new(account.id, &account.name, cryps), Uuid::nil(), &account)?
|
||||
}
|
||||
};
|
||||
|
||||
@ -385,7 +415,7 @@ mod tests {
|
||||
fn player_bot_vbox_test() {
|
||||
let player_account = Uuid::new_v4();
|
||||
let cryps = instance_mobs(player_account);
|
||||
let mut player = Player::new(player_account, Uuid::new_v4(), &"test".to_string(), cryps).set_bot(true);
|
||||
let mut player = Player::new(player_account, &"test".to_string(), cryps).set_bot(true);
|
||||
player.vbox.fill();
|
||||
|
||||
player.autobuy();
|
||||
|
||||
@ -16,13 +16,13 @@ use failure::err_msg;
|
||||
|
||||
use net::Db;
|
||||
use cryp::{Cryp, cryp_spawn};
|
||||
use game::{Game, game_state, game_skill};
|
||||
use game::{Game, game_state, game_skill, game_ready};
|
||||
use account::{Account, account_create, account_login, account_from_token, account_cryps, account_instances};
|
||||
use skill::{Skill};
|
||||
// use zone::{Zone, zone_create, zone_join, zone_close};
|
||||
use spec::{Spec};
|
||||
use player::{Score, player_mm_cryps_set, Player};
|
||||
use instance::{Instance, instance_state, instance_new, instance_ready, instance_join, instance_scores};
|
||||
use instance::{Instance, instance_state, instance_new, instance_ready, instance_join};
|
||||
use vbox::{Var, vbox_accept, vbox_apply, vbox_discard, vbox_combine, vbox_reclaim, vbox_unequip};
|
||||
|
||||
pub struct Rpc;
|
||||
@ -71,11 +71,11 @@ impl Rpc {
|
||||
|
||||
"game_state" => Rpc::game_state(data, &mut tx, account.unwrap(), client),
|
||||
"game_skill" => Rpc::game_skill(data, &mut tx, account.unwrap(), client),
|
||||
"game_ready" => Rpc::game_ready(data, &mut tx, account.unwrap(), client),
|
||||
|
||||
"instance_join" => Rpc::instance_join(data, &mut tx, account.unwrap(), client),
|
||||
"instance_ready" => Rpc::instance_ready(data, &mut tx, account.unwrap(), client),
|
||||
"instance_new" => Rpc::instance_new(data, &mut tx, account.unwrap(), client),
|
||||
"instance_scores" => Rpc::instance_scores(data, &mut tx, account.unwrap(), client),
|
||||
"instance_state" => Rpc::instance_state(data, &mut tx, account.unwrap(), client),
|
||||
|
||||
"player_mm_cryps_set" => Rpc::player_mm_cryps_set(data, &mut tx, account.unwrap(), client),
|
||||
@ -141,6 +141,18 @@ impl Rpc {
|
||||
return Ok(game_response);
|
||||
}
|
||||
|
||||
fn game_ready(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
let msg = from_slice::<GameStateMsg>(&data).or(Err(err_msg("invalid params")))?;
|
||||
|
||||
let game_response = RpcResponse {
|
||||
method: "game_state".to_string(),
|
||||
params: RpcResult::GameState(game_ready(msg.params, tx, &account)?)
|
||||
};
|
||||
|
||||
return Ok(game_response);
|
||||
}
|
||||
|
||||
|
||||
fn cryp_spawn(data: Vec<u8>, tx: &mut Transaction, account: Account, client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
let msg = from_slice::<CrypSpawnMsg>(&data).or(Err(err_msg("invalid params")))?;
|
||||
|
||||
@ -261,17 +273,6 @@ impl Rpc {
|
||||
// return Ok(response);
|
||||
// }
|
||||
|
||||
fn instance_scores(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
let msg = from_slice::<InstanceReadyMsg>(&data).or(Err(err_msg("invalid params")))?;
|
||||
|
||||
let response = RpcResponse {
|
||||
method: "instance_scores".to_string(),
|
||||
params: RpcResult::InstanceScores(instance_scores(msg.params, tx, &account)?)
|
||||
};
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
|
||||
fn instance_state(data: Vec<u8>, tx: &mut Transaction, account: Account, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
|
||||
let msg = from_slice::<InstanceStateMsg>(&data).or(Err(err_msg("invalid params")))?;
|
||||
match instance_state(msg.params, tx, &account)? {
|
||||
|
||||
@ -125,7 +125,7 @@ pub fn resolve(skill: Skill, source: &mut Cryp, target: &mut Cryp, mut resolutio
|
||||
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
|
||||
pub struct Cast {
|
||||
pub id: Uuid,
|
||||
pub source_team_id: Uuid,
|
||||
pub source_player_id: Uuid,
|
||||
pub source_cryp_id: Uuid,
|
||||
pub target_cryp_id: Uuid,
|
||||
pub skill: Skill,
|
||||
@ -134,11 +134,11 @@ pub struct Cast {
|
||||
}
|
||||
|
||||
impl Cast {
|
||||
pub fn new(source_cryp_id: Uuid, source_team_id: Uuid, target_cryp_id: Uuid, skill: Skill) -> Cast {
|
||||
pub fn new(source_cryp_id: Uuid, source_player_id: Uuid, target_cryp_id: Uuid, skill: Skill) -> Cast {
|
||||
return Cast {
|
||||
id: Uuid::new_v4(),
|
||||
source_cryp_id,
|
||||
source_team_id,
|
||||
source_player_id,
|
||||
target_cryp_id,
|
||||
skill,
|
||||
speed: 0,
|
||||
|
||||
@ -68,94 +68,94 @@ impl Spec {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn apply(&self, modified: u64, base: u64, team_colours: &Colours) -> u64 {
|
||||
pub fn apply(&self, modified: u64, base: u64, player_colours: &Colours) -> u64 {
|
||||
match *self {
|
||||
// Upgrades to Damage Spec
|
||||
Spec::Damage => modified + base.pct(5),
|
||||
Spec::RedDamageI => modified + {
|
||||
let mut pct = 10;
|
||||
if team_colours.red >= 5 { pct += 10 };
|
||||
if team_colours.red >= 10 { pct += 20 };
|
||||
if team_colours.red >= 20 { pct += 40 };
|
||||
if player_colours.red >= 5 { pct += 10 };
|
||||
if player_colours.red >= 10 { pct += 20 };
|
||||
if player_colours.red >= 20 { pct += 40 };
|
||||
base.pct(pct)
|
||||
},
|
||||
Spec::GreenDamageI => modified + {
|
||||
let mut pct = 10;
|
||||
if team_colours.green >= 5 { pct += 10 };
|
||||
if team_colours.green >= 10 { pct += 20 };
|
||||
if team_colours.green >= 20 { pct += 40 };
|
||||
if player_colours.green >= 5 { pct += 10 };
|
||||
if player_colours.green >= 10 { pct += 20 };
|
||||
if player_colours.green >= 20 { pct += 40 };
|
||||
base.pct(pct)
|
||||
},
|
||||
Spec::BlueDamageI => modified + {
|
||||
let mut pct = 10;
|
||||
if team_colours.blue >= 5 { pct += 10 };
|
||||
if team_colours.blue >= 10 { pct += 20 };
|
||||
if team_colours.blue >= 20 { pct += 40 };
|
||||
if player_colours.blue >= 5 { pct += 10 };
|
||||
if player_colours.blue >= 10 { pct += 20 };
|
||||
if player_colours.blue >= 20 { pct += 40 };
|
||||
base.pct(pct)
|
||||
},
|
||||
Spec::GRDI => modified + {
|
||||
let mut pct = 5;
|
||||
if team_colours.green >= 2 && team_colours.red >= 2 { pct += 10 };
|
||||
if team_colours.green >= 5 && team_colours.red >= 5 { pct += 15 };
|
||||
if team_colours.green >= 10 && team_colours.red >= 10 { pct += 30 };
|
||||
if player_colours.green >= 2 && player_colours.red >= 2 { pct += 10 };
|
||||
if player_colours.green >= 5 && player_colours.red >= 5 { pct += 15 };
|
||||
if player_colours.green >= 10 && player_colours.red >= 10 { pct += 30 };
|
||||
base.pct(pct)
|
||||
},
|
||||
Spec::GBDI => modified + {
|
||||
let mut pct = 5;
|
||||
if team_colours.green >= 2 && team_colours.blue >= 2 { pct += 10 };
|
||||
if team_colours.green >= 5 && team_colours.blue >= 5 { pct += 15 };
|
||||
if team_colours.green >= 10 && team_colours.blue >= 10 { pct += 30 };
|
||||
if player_colours.green >= 2 && player_colours.blue >= 2 { pct += 10 };
|
||||
if player_colours.green >= 5 && player_colours.blue >= 5 { pct += 15 };
|
||||
if player_colours.green >= 10 && player_colours.blue >= 10 { pct += 30 };
|
||||
base.pct(pct)
|
||||
},
|
||||
Spec::RBDI => modified + {
|
||||
let mut pct = 5;
|
||||
if team_colours.blue >= 2 && team_colours.red >= 2 { pct += 10 };
|
||||
if team_colours.blue >= 5 && team_colours.red >= 5 { pct += 15 };
|
||||
if team_colours.blue >= 10 && team_colours.red >= 10 { pct += 30 };
|
||||
if player_colours.blue >= 2 && player_colours.red >= 2 { pct += 10 };
|
||||
if player_colours.blue >= 5 && player_colours.red >= 5 { pct += 15 };
|
||||
if player_colours.blue >= 10 && player_colours.red >= 10 { pct += 30 };
|
||||
base.pct(pct)
|
||||
},
|
||||
// Upgrades to speed Spec
|
||||
Spec::Speed => modified + base.pct(5),
|
||||
Spec::RedSpeedI => modified + {
|
||||
let mut pct = 5;
|
||||
if team_colours.red >= 5 { pct += 5 };
|
||||
if team_colours.red >= 10 { pct += 10 };
|
||||
if team_colours.red >= 20 { pct += 20 };
|
||||
if player_colours.red >= 5 { pct += 5 };
|
||||
if player_colours.red >= 10 { pct += 10 };
|
||||
if player_colours.red >= 20 { pct += 20 };
|
||||
base.pct(pct)
|
||||
},
|
||||
Spec::GreenSpeedI => modified + {
|
||||
let mut pct = 5;
|
||||
if team_colours.green >= 5 { pct += 5 };
|
||||
if team_colours.green >= 10 { pct += 10 };
|
||||
if team_colours.green >= 20 { pct += 20 };
|
||||
if player_colours.green >= 5 { pct += 5 };
|
||||
if player_colours.green >= 10 { pct += 10 };
|
||||
if player_colours.green >= 20 { pct += 20 };
|
||||
base.pct(pct)
|
||||
},
|
||||
Spec::BlueSpeedI => modified + {
|
||||
let mut pct = 5;
|
||||
if team_colours.blue >= 5 { pct += 5 };
|
||||
if team_colours.blue >= 10 { pct += 10 };
|
||||
if team_colours.blue >= 20 { pct += 20 };
|
||||
if player_colours.blue >= 5 { pct += 5 };
|
||||
if player_colours.blue >= 10 { pct += 10 };
|
||||
if player_colours.blue >= 20 { pct += 20 };
|
||||
base.pct(pct)
|
||||
},
|
||||
Spec::GRSpeedI => modified + {
|
||||
let mut pct = 5;
|
||||
if team_colours.green >= 2 && team_colours.red >= 2 { pct += 5 };
|
||||
if team_colours.green >= 5 && team_colours.red >= 5 { pct += 10 };
|
||||
if team_colours.green >= 10 && team_colours.red >= 10 { pct += 20 };
|
||||
if player_colours.green >= 2 && player_colours.red >= 2 { pct += 5 };
|
||||
if player_colours.green >= 5 && player_colours.red >= 5 { pct += 10 };
|
||||
if player_colours.green >= 10 && player_colours.red >= 10 { pct += 20 };
|
||||
base.pct(pct)
|
||||
},
|
||||
Spec::GBSpeedI => modified + {
|
||||
let mut pct = 5;
|
||||
if team_colours.green >= 2 && team_colours.blue >= 2 { pct += 5 };
|
||||
if team_colours.green >= 5 && team_colours.blue >= 5 { pct += 10 };
|
||||
if team_colours.green >= 10 && team_colours.blue >= 10 { pct += 20 };
|
||||
if player_colours.green >= 2 && player_colours.blue >= 2 { pct += 5 };
|
||||
if player_colours.green >= 5 && player_colours.blue >= 5 { pct += 10 };
|
||||
if player_colours.green >= 10 && player_colours.blue >= 10 { pct += 20 };
|
||||
base.pct(pct)
|
||||
},
|
||||
Spec::RBSpeedI => modified + {
|
||||
let mut pct = 5;
|
||||
if team_colours.blue >= 2 && team_colours.red >= 2 { pct += 5 };
|
||||
if team_colours.blue >= 5 && team_colours.red >= 5 { pct += 10 };
|
||||
if team_colours.blue >= 10 && team_colours.red >= 10 { pct += 20 };
|
||||
if player_colours.blue >= 2 && player_colours.red >= 2 { pct += 5 };
|
||||
if player_colours.blue >= 5 && player_colours.red >= 5 { pct += 10 };
|
||||
if player_colours.blue >= 10 && player_colours.red >= 10 { pct += 20 };
|
||||
base.pct(pct)
|
||||
},
|
||||
|
||||
@ -163,45 +163,45 @@ impl Spec {
|
||||
Spec::Life => modified + base.pct(5),
|
||||
Spec::GreenLifeI => modified + {
|
||||
let mut mult: u64 = 15;
|
||||
if team_colours.green >= 5 { mult += 25 };
|
||||
if team_colours.green >= 10 { mult += 50 };
|
||||
if team_colours.green >= 20 { mult += 75 };
|
||||
mult * team_colours.green as u64
|
||||
if player_colours.green >= 5 { mult += 25 };
|
||||
if player_colours.green >= 10 { mult += 50 };
|
||||
if player_colours.green >= 20 { mult += 75 };
|
||||
mult * player_colours.green as u64
|
||||
},
|
||||
Spec::RedLifeI => modified + {
|
||||
let mut mult: u64 = 15;
|
||||
if team_colours.red >= 5 { mult += 25 };
|
||||
if team_colours.red >= 10 { mult += 50 };
|
||||
if team_colours.red >= 20 { mult += 75 };
|
||||
mult * team_colours.red as u64
|
||||
if player_colours.red >= 5 { mult += 25 };
|
||||
if player_colours.red >= 10 { mult += 50 };
|
||||
if player_colours.red >= 20 { mult += 75 };
|
||||
mult * player_colours.red as u64
|
||||
},
|
||||
Spec::BlueLifeI => modified + {
|
||||
let mut mult: u64 = 15;
|
||||
if team_colours.blue >= 5 { mult += 25 };
|
||||
if team_colours.blue >= 10 { mult += 50 };
|
||||
if team_colours.blue >= 20 { mult += 75 };
|
||||
mult * team_colours.blue as u64
|
||||
if player_colours.blue >= 5 { mult += 25 };
|
||||
if player_colours.blue >= 10 { mult += 50 };
|
||||
if player_colours.blue >= 20 { mult += 75 };
|
||||
mult * player_colours.blue as u64
|
||||
},
|
||||
Spec::GRLI => modified + {
|
||||
let mut mult: u64 = 10;
|
||||
if team_colours.green >= 2 && team_colours.red >= 2 { mult += 10 };
|
||||
if team_colours.green >= 5 && team_colours.red >= 5 { mult += 25 };
|
||||
if team_colours.green >= 10 && team_colours.red >= 10 { mult += 50 };
|
||||
mult * (team_colours.green + team_colours.red) as u64
|
||||
if player_colours.green >= 2 && player_colours.red >= 2 { mult += 10 };
|
||||
if player_colours.green >= 5 && player_colours.red >= 5 { mult += 25 };
|
||||
if player_colours.green >= 10 && player_colours.red >= 10 { mult += 50 };
|
||||
mult * (player_colours.green + player_colours.red) as u64
|
||||
},
|
||||
Spec::GBLI => modified + {
|
||||
let mut mult: u64 = 10;
|
||||
if team_colours.green >= 2 && team_colours.red >= 2 { mult += 10 };
|
||||
if team_colours.green >= 5 && team_colours.red >= 5 { mult += 25 };
|
||||
if team_colours.green >= 10 && team_colours.red >= 10 { mult += 50 };
|
||||
mult * (team_colours.green + team_colours.red) as u64
|
||||
if player_colours.green >= 2 && player_colours.red >= 2 { mult += 10 };
|
||||
if player_colours.green >= 5 && player_colours.red >= 5 { mult += 25 };
|
||||
if player_colours.green >= 10 && player_colours.red >= 10 { mult += 50 };
|
||||
mult * (player_colours.green + player_colours.red) as u64
|
||||
},
|
||||
Spec::RBLI => modified + {
|
||||
let mut mult: u64 = 10;
|
||||
if team_colours.blue >= 2 && team_colours.red >= 2 { mult += 10 };
|
||||
if team_colours.blue >= 5 && team_colours.red >= 5 { mult += 25 };
|
||||
if team_colours.blue >= 10 && team_colours.red >= 10 { mult += 50 };
|
||||
mult * (team_colours.blue + team_colours.red) as u64
|
||||
if player_colours.blue >= 2 && player_colours.red >= 2 { mult += 10 };
|
||||
if player_colours.blue >= 5 && player_colours.red >= 5 { mult += 25 };
|
||||
if player_colours.blue >= 10 && player_colours.red >= 10 { mult += 50 };
|
||||
mult * (player_colours.blue + player_colours.red) as u64
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,14 +2,14 @@ use net::Db;
|
||||
// Db Commons
|
||||
use failure::Error;
|
||||
|
||||
use game::{game_global_startup};
|
||||
// use game::{game_global_startup};
|
||||
|
||||
pub fn startup(db: Db) -> Result<(), Error> {
|
||||
let mut tx = db.transaction()?;
|
||||
|
||||
println!("running startup fns");
|
||||
|
||||
game_global_startup(&mut tx)?;
|
||||
// game_global_startup(&mut tx)?;
|
||||
|
||||
match tx.commit() {
|
||||
Ok(_) => {
|
||||
|
||||
@ -15,7 +15,6 @@ use account::Account;
|
||||
use rpc::{VboxAcceptParams, VboxDiscardParams, VboxCombineParams, VboxApplyParams, VboxReclaimParams, VboxUnequipParams};
|
||||
use skill::{Skill};
|
||||
use spec::{Spec};
|
||||
use player::{Player};
|
||||
use instance::{Instance, instance_get, instance_update};
|
||||
use cryp::{Colours};
|
||||
|
||||
@ -397,16 +396,13 @@ fn get_combos() -> Vec<Combo> {
|
||||
|
||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||
pub struct Vbox {
|
||||
pub id: Uuid,
|
||||
pub bits: u16,
|
||||
pub free: Vec<Vec<Var>>,
|
||||
pub bound: Vec<Var>,
|
||||
pub instance: Uuid,
|
||||
pub account: Uuid,
|
||||
}
|
||||
|
||||
impl Vbox {
|
||||
pub fn new(account_id: Uuid, instance_id: Uuid) -> Vbox {
|
||||
pub fn new() -> Vbox {
|
||||
let starting_items = vec![
|
||||
Var::Attack,
|
||||
Var::Attack,
|
||||
@ -414,9 +410,6 @@ impl Vbox {
|
||||
];
|
||||
|
||||
Vbox {
|
||||
id: Uuid::new_v4(),
|
||||
account: account_id,
|
||||
instance: instance_id,
|
||||
free: vec![vec![], vec![], vec![]],
|
||||
bound: starting_items,
|
||||
bits: 18,
|
||||
@ -558,19 +551,19 @@ pub fn vbox_combine(params: VboxCombineParams, tx: &mut Transaction, account: &A
|
||||
}
|
||||
|
||||
pub fn vbox_reclaim(params: VboxReclaimParams, tx: &mut Transaction, account: &Account) -> Result<Instance, Error> {
|
||||
let mut instance = instance_get(tx, params.instance_id)?
|
||||
let instance = instance_get(tx, params.instance_id)?
|
||||
.vbox_reclaim(account.id, params.index)?;
|
||||
return instance_update(tx, instance);
|
||||
}
|
||||
|
||||
pub fn vbox_apply(params: VboxApplyParams, tx: &mut Transaction, account: &Account) -> Result<Instance, Error> {
|
||||
let mut instance = instance_get(tx, params.instance_id)?
|
||||
let instance = instance_get(tx, params.instance_id)?
|
||||
.vbox_apply(account.id, params.index, params.cryp_id)?;
|
||||
return instance_update(tx, instance);
|
||||
}
|
||||
|
||||
pub fn vbox_unequip(params: VboxUnequipParams, tx: &mut Transaction, account: &Account) -> Result<Instance, Error> {
|
||||
let mut instance = instance_get(tx, params.instance_id)?
|
||||
let instance = instance_get(tx, params.instance_id)?
|
||||
.vbox_unequip(account.id, params.target, params.cryp_id)?;
|
||||
return instance_update(tx, instance);
|
||||
}
|
||||
@ -581,7 +574,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn combine_test() {
|
||||
let mut vbox = Vbox::new(Uuid::new_v4(), Uuid::new_v4());
|
||||
let mut vbox = Vbox::new();
|
||||
vbox.bound = vec![Var::Attack, Var::Green, Var::Green];
|
||||
vbox.combine(vec![1,2,0]).unwrap();
|
||||
assert_eq!(vbox.bound[0], Var::Heal);
|
||||
@ -601,7 +594,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn reclaim_test() {
|
||||
let mut vbox = Vbox::new(Uuid::new_v4(), Uuid::new_v4());
|
||||
let mut vbox = Vbox::new();
|
||||
vbox.bound = vec![Var::Strike];
|
||||
vbox.reclaim(0).unwrap();
|
||||
assert_eq!(vbox.bits, 22);
|
||||
|
||||
53
server/src/warden.rs
Normal file
53
server/src/warden.rs
Normal file
@ -0,0 +1,53 @@
|
||||
|
||||
// Db Commons
|
||||
use postgres::transaction::Transaction;
|
||||
use failure::Error;
|
||||
|
||||
use game::{games_need_upkeep, game_update, game_write, game_delete};
|
||||
use instance::{instances_need_upkeep, instance_update};
|
||||
use net::{Db};
|
||||
|
||||
fn fetch_games(mut tx: Transaction) -> Result<Transaction, Error> {
|
||||
let games = games_need_upkeep(&mut tx)?;
|
||||
|
||||
for mut game in games {
|
||||
let game = game.upkeep();
|
||||
match game_update(&mut tx, &game) {
|
||||
Ok(_) => (),
|
||||
Err(e) => {
|
||||
println!("{:?}", e);
|
||||
game_delete(&mut tx, game.id)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(tx)
|
||||
}
|
||||
|
||||
fn fetch_instances(mut tx: Transaction) -> Result<Transaction, Error> {
|
||||
let instances = instances_need_upkeep(&mut tx)?;
|
||||
|
||||
for mut instance in instances {
|
||||
let (instance, new_games) = instance.upkeep();
|
||||
println!("{:?} new games", new_games.len());
|
||||
for game in new_games {
|
||||
game_write(&mut tx, &game)?;
|
||||
}
|
||||
instance_update(&mut tx, instance)?;
|
||||
}
|
||||
|
||||
Ok(tx)
|
||||
}
|
||||
|
||||
pub fn warden(db: Db) -> Result<(), Error> {
|
||||
println!("upkeep beginning");
|
||||
fetch_games(db.transaction()?)?
|
||||
.commit()?;
|
||||
|
||||
fetch_instances(db.transaction()?)?
|
||||
.commit()?;
|
||||
|
||||
println!("upkeep done");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -187,7 +187,7 @@ pub fn zone_join(params: ZoneJoinParams, tx: &mut Transaction, account: &Account
|
||||
}
|
||||
|
||||
// persist
|
||||
game_write(&game, tx)?;
|
||||
game_write(tx, &game)?;
|
||||
zone_update(&zone, tx)?;
|
||||
|
||||
return Ok(game);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user