takin hits

This commit is contained in:
ntr 2018-10-20 19:13:15 +11:00
parent 50cb9a574f
commit 3a4c9e4971
6 changed files with 163 additions and 23 deletions

View File

@ -9,7 +9,11 @@ const addState = connect(
return ws.sendGameAbility(game.id, crypId, targetTeamId, ability);
}
return { game, account, sendGameAbility };
function sendGameTarget(crypId, abilityId) {
return ws.sendGameTarget(game.id, crypId, abilityId);
}
return { game, account, sendGameAbility, sendGameTarget };
}
);

View File

@ -1,11 +1,22 @@
const preact = require('preact');
function GamePanel({ game, sendGameAbility, account }) {
function GamePanel({ game, sendGameAbility, sendGameTarget, account }) {
if (!game) return <div>...</div>;
const otherTeams = game.teams.filter(t => t.id !== account.id);
const playerTeam = game.teams.find(t => t.id === account.id);
const targetBtn = playerTeam.incoming.map(i => (
<button
key={i.id}
className="button is-dark is-fullwidth"
type="submit"
onClick={() => sendGameTarget(playerTeam.cryps[0].id, i.id)}>
take the hit
</button>
));
const playerCryps = playerTeam.cryps.map(c => (
<div key={c.id} >
<div>{c.name}</div>
@ -21,6 +32,7 @@ function GamePanel({ game, sendGameAbility, account }) {
return (
<div>
<h1>{game.phase}</h1>
<div>
<h1>them</h1>
<div>{JSON.stringify(otherTeams)}</div>
@ -28,6 +40,7 @@ function GamePanel({ game, sendGameAbility, account }) {
<div>
<h1>us</h1>
{playerCryps}
{targetBtn}
</div>
</div>
)

View File

@ -117,6 +117,9 @@ function createSocket(store) {
send({ method: 'game_ability', params: { game_id: gameId, cryp_id: crypId, target_team_id: targetTeamId, ability } });
}
function sendGameTarget(gameId, crypId, abilityId) {
send({ method: 'game_target', params: { game_id: gameId, cryp_id: crypId, ability_id: abilityId } });
}
function sendItemUse(item, target) {
console.log(item, target);
@ -160,6 +163,7 @@ function createSocket(store) {
sendAccountRegister,
sendGamePve,
sendGameAbility,
sendGameTarget,
sendCrypSpawn,
sendItemUse,
connect,

View File

@ -26,6 +26,7 @@
* skills
* offensive -> choose target ✔
* check for cryp ability already used
* check for cryp ability ownership
* check for game participation
* write players row for every team+cryp added

View File

@ -8,7 +8,7 @@ use failure::Error;
use failure::err_msg;
use account::Account;
use rpc::{GameAbilityParams, GamePveParams};
use rpc::{GameAbilityParams, GamePveParams, GameTargetParams};
use cryp::{Cryp, CrypStat, Stat};
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
@ -86,15 +86,6 @@ impl GameAbility {
}
}
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
pub enum Phase {
Start,
GameAbility,
Target,
Damage,
Finish,
}
#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct Team {
id: Uuid,
@ -130,6 +121,15 @@ impl Team {
}
}
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
pub enum Phase {
Start,
Ability,
Target,
Damage,
Finish,
}
#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct Game {
pub id: Uuid,
@ -216,11 +216,31 @@ impl Game {
panic!("game not in damage or start phase");
}
self.phase = Phase::GameAbility;
self.phase = Phase::Ability;
for team in self.teams.iter_mut() {
team.abilities.clear();
team.incoming.clear();
}
if self.is_pve {
self.pve_add_abilities();
}
self
}
fn pve_add_abilities(&mut self) -> &mut Game {
{
let mob_team_id = Uuid::nil();
let teams = self.teams.clone();
let mobs = self.team_by_id(mob_team_id).clone();
// TODO attack multiple players based on some criteria
let player_team = teams.iter().find(|t| t.id != mob_team_id).unwrap();
for mob in &mobs.cryps {
self.add_ability(mob_team_id, mob.id, player_team.id, Ability::Attack);
}
}
self
}
@ -233,6 +253,8 @@ impl Game {
None => panic!("cryp not in team"),
};
// TODO check cryp ownership
// TODO check cryp ability already used
// TODO check cryp has ability
let ability = GameAbility::new(cryp_id, target_team_id, ability);
team.abilities.push(ability);
@ -245,8 +267,8 @@ impl Game {
}
// move all abilities into their target team's targets list
pub fn targets_phase_start(&mut self) -> &mut Game {
if self.phase != Phase::GameAbility {
pub fn target_phase_start(&mut self) -> &mut Game {
if self.phase != Phase::Ability {
panic!("game not in ability phase");
}
@ -262,9 +284,27 @@ impl Game {
}
}
if self.is_pve {
self.pve_add_targets();
}
self
}
fn pve_add_targets(&mut self) -> &mut Game {
{
let mob_team_id = Uuid::nil();
let mobs = self.team_by_id(mob_team_id).clone();
// TODO attack multiple players based on some criteria
for incoming in &mobs.incoming {
self.add_target(mob_team_id, mobs.cryps[0].id, incoming.id);
}
}
self
}
// targets can only be added by the owner of the team
pub fn add_target(&mut self, team_id: Uuid, cryp_id: Uuid, ability_id: Uuid) -> &mut GameAbility {
// whose team is this?
@ -297,8 +337,7 @@ impl Game {
self.resolve_abilities();
if self.is_finished() {
self.phase = Phase::Finish;
return self;
return self.finish()
}
self.ability_phase_start();
@ -327,6 +366,17 @@ impl Game {
pub fn is_finished(&self) -> bool {
self.teams.iter().any(|t| t.cryps.iter().all(|c| c.is_ko()))
}
fn finish(&mut self) -> &mut Game {
self.phase = Phase::Finish;
for team in self.teams.iter_mut() {
team.abilities.clear();
team.incoming.clear();
}
self
}
}
pub fn game_ability(params: GameAbilityParams, tx: &mut Transaction, account: &Account) -> Result<Game, Error> {
@ -350,6 +400,38 @@ pub fn game_ability(params: GameAbilityParams, tx: &mut Transaction, account: &A
game.add_ability(account.id, params.cryp_id, params.target_team_id, params.ability);
if game.ability_phase_finished() {
game.target_phase_start();
}
return game_write(game, tx);
}
pub fn game_target(params: GameTargetParams, tx: &mut Transaction, account: &Account) -> Result<Game, Error> {
let query = "
SELECT *
FROM games
WHERE id = $1
";
let result = tx
.query(query, &[&params.game_id])?;
let returned = match result.iter().next() {
Some(row) => row,
None => return Err(err_msg("game not found")),
};
// tells from_slice to cast into a cryp
let game_bytes: Vec<u8> = returned.get("data");
let mut game = from_slice::<Game>(&game_bytes)?;
game.add_target(account.id, params.cryp_id, params.ability_id);
if game.target_phase_finished() {
game.damage_phase_start();
}
return game_write(game, tx);
}
@ -540,7 +622,7 @@ mod tests {
assert!(game.ability_phase_finished());
game.targets_phase_start();
game.target_phase_start();
println!("{:?}", game);
@ -551,7 +633,7 @@ mod tests {
game.damage_phase_start();
assert!([Phase::GameAbility, Phase::Finish].contains(&game.phase));
assert!([Phase::Ability, Phase::Finish].contains(&game.phase));
println!("{:?}", game);

View File

@ -11,7 +11,7 @@ use failure::err_msg;
use net::Db;
use cryp::{Cryp, cryp_spawn};
use game::{Game, Ability, game_pve, game_ability};
use game::{Game, Ability, game_pve, game_ability, game_target};
use account::{Account, account_create, account_login, account_from_token, account_cryps};
use item::{Item, items_list, item_use};
@ -40,6 +40,7 @@ impl Rpc {
"cryp_spawn" => Rpc::cryp_spawn(data, &mut tx, account, client),
"game_pve" => Rpc::game_pve(data, &mut tx, account, client),
"game_ability" => Rpc::game_ability(data, &mut tx, account, client),
"game_target" => Rpc::game_target(data, &mut tx, account, client),
"account_create" => Rpc::account_create(data, &mut tx, account, client),
"account_login" => Rpc::account_login(data, &mut tx, account, client),
"account_cryps" => Rpc::account_cryps(data, &mut tx, account, client),
@ -75,7 +76,7 @@ impl Rpc {
let game_response = RpcResponse {
method: "game_state".to_string(),
params: RpcResult::Pve(game_pve(msg.params, tx, &a)?)
params: RpcResult::GameState(game_pve(msg.params, tx, &a)?)
};
Rpc::send_msg(client, RpcResponse {
@ -96,7 +97,7 @@ impl Rpc {
let game_response = RpcResponse {
method: "game_state".to_string(),
params: RpcResult::Pve(game_ability(msg.params, tx, &a)?)
params: RpcResult::GameState(game_ability(msg.params, tx, &a)?)
};
// Rpc::send_msg(client, RpcResponse {
@ -107,6 +108,28 @@ impl Rpc {
return Ok(game_response);
}
fn game_target(data: Vec<u8>, tx: &mut Transaction, account: Option<Account>, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
let a = match account {
Some(a) => a,
None => return Err(err_msg("auth required")),
};
let msg = from_slice::<GameTargetMsg>(&data).or(Err(err_msg("invalid params")))?;
let game_response = RpcResponse {
method: "game_state".to_string(),
params: RpcResult::GameState(game_target(msg.params, tx, &a)?)
};
// Rpc::send_msg(client, RpcResponse {
// method: "account_cryps".to_string(),
// params: RpcResult::CrypList(account_cryps(tx, &a)?)
// })?;
return Ok(game_response);
}
fn cryp_spawn(data: Vec<u8>, tx: &mut Transaction, account: Option<Account>, _client: &mut WebSocket<TcpStream>) -> Result<RpcResponse, Error> {
match from_slice::<CrypSpawnMsg>(&data) {
Ok(v) => {
@ -194,7 +217,7 @@ pub enum RpcResult {
SpawnCryp(Cryp),
Account(Account),
CrypList(Vec<Cryp>),
Pve(Game),
GameState(Game),
ItemList(Vec<Item>),
ItemUse(()),
}
@ -227,6 +250,19 @@ pub struct GamePveParams {
pub id: Uuid,
}
#[derive(Debug,Clone,Serialize,Deserialize)]
struct GameTargetMsg {
method: String,
params: GameTargetParams,
}
#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct GameTargetParams {
pub game_id: Uuid,
pub cryp_id: Uuid,
pub ability_id: Uuid,
}
#[derive(Debug,Clone,Serialize,Deserialize)]
struct GameAbilityMsg {
method: String,