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
+99 -17
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);
+40 -4
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,