@@ -21,6 +32,7 @@ function GamePanel({ game, sendGameAbility, account }) {
return (
+
{game.phase}
them
{JSON.stringify(otherTeams)}
@@ -28,6 +40,7 @@ function GamePanel({ game, sendGameAbility, account }) {
us
{playerCryps}
+ {targetBtn}
)
diff --git a/client/src/socket.jsx b/client/src/socket.jsx
index 357fd547..b6e6d03e 100755
--- a/client/src/socket.jsx
+++ b/client/src/socket.jsx
@@ -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,
diff --git a/server/WORKLOG.md b/server/WORKLOG.md
index 3e3effc5..361bb12e 100755
--- a/server/WORKLOG.md
+++ b/server/WORKLOG.md
@@ -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
diff --git a/server/src/game.rs b/server/src/game.rs
index f14c54f0..97f9f659 100755
--- a/server/src/game.rs
+++ b/server/src/game.rs
@@ -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
{
@@ -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 {
+ let query = "
+ SELECT *
+ FROM games
+ WHERE id = $1
+ ";
+
+ let result = tx
+ .query(query, &[¶ms.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 = returned.get("data");
+ let mut game = from_slice::(&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);
diff --git a/server/src/rpc.rs b/server/src/rpc.rs
index 65fa4dbe..4b1be3fe 100755
--- a/server/src/rpc.rs
+++ b/server/src/rpc.rs
@@ -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, tx: &mut Transaction, account: Option, _client: &mut WebSocket) -> Result {
+ let a = match account {
+ Some(a) => a,
+ None => return Err(err_msg("auth required")),
+ };
+
+ let msg = from_slice::(&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, tx: &mut Transaction, account: Option, _client: &mut WebSocket) -> Result {
match from_slice::(&data) {
Ok(v) => {
@@ -194,7 +217,7 @@ pub enum RpcResult {
SpawnCryp(Cryp),
Account(Account),
CrypList(Vec),
- Pve(Game),
+ GameState(Game),
ItemList(Vec- ),
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,