From 89445a0b65767719cd4468e60b729c92f7fde75e Mon Sep 17 00:00:00 2001 From: ntr Date: Thu, 25 Oct 2018 17:53:35 +1100 Subject: [PATCH] stuns and statuses --- client/src/components/game.jsx | 14 ++++++ client/src/socket.jsx | 2 +- server/src/cryp.rs | 78 +++++++++++++++++++++++++--------- server/src/game.rs | 36 ++++++++++------ server/src/rpc.rs | 2 +- server/src/skill.rs | 47 +++++--------------- 6 files changed, 107 insertions(+), 72 deletions(-) diff --git a/client/src/components/game.jsx b/client/src/components/game.jsx index a113c27c..74a25404 100755 --- a/client/src/components/game.jsx +++ b/client/src/components/game.jsx @@ -55,6 +55,12 @@ function GamePanel(props) { ); }); + const statuses = cryp.statuses.map((status, i) => { + return ( +
{status} for {status.turns}T
+ ) + }) + if (activeIncoming) console.log('should be a pointer'); return (
{cryp.xp} / {Math.pow(2,cryp.lvl+1)} XP
+ {statuses} {skills} ); @@ -97,6 +104,12 @@ function GamePanel(props) { } function OpponentCrypCard(cryp) { + const statuses = cryp.statuses.map((status, i) => { + return ( +
{status.status} for {status.turns}T
+ ) + }); + return (
@@ -119,6 +132,7 @@ function GamePanel(props) {
+ {statuses}
); } diff --git a/client/src/socket.jsx b/client/src/socket.jsx index d01dba3c..e73e49f3 100755 --- a/client/src/socket.jsx +++ b/client/src/socket.jsx @@ -140,7 +140,7 @@ function createSocket(store) { } function sendGameTarget(gameId, crypId, skillId) { - send({ method: 'game_target', params: { game_id: gameId, cryp_id: crypId, skill_id: skillId } }); + send({ method: 'game_target', params: { game_id: gameId, cryp_id: crypId, cast_id: skillId } }); store.dispatch(actions.setActiveIncoming(null)); } diff --git a/server/src/cryp.rs b/server/src/cryp.rs index 6f72fc27..dd018cea 100755 --- a/server/src/cryp.rs +++ b/server/src/cryp.rs @@ -9,7 +9,7 @@ use failure::err_msg; use account::Account; use rpc::{CrypSpawnParams}; -use skill::{Skill}; +use skill::{Skill, Roll}; type Cooldown = Option; @@ -26,7 +26,7 @@ impl CrypSkill { Skill::Block => Some(1), Skill::Dodge => Some(1), Skill::Heal => Some(2), - Skill::Stun => Some(2), + Skill::Stun => None, }; CrypSkill { @@ -35,7 +35,10 @@ impl CrypSkill { } } - fn is_usable(&self, cryp: &Cryp) -> bool { + fn can_cast(&self, cryp: &Cryp) -> bool { + if cryp.is_stunned() { + return false; + } true } } @@ -52,7 +55,6 @@ pub struct CrypStatus { turns: u8, } - #[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] pub enum Stat { Str, @@ -62,13 +64,6 @@ pub enum Stat { Stam, } -#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] -pub struct Roll { - pub base: u64, - pub result: u64, - pub kind: Stat, -} - #[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] pub struct CrypStat { pub value: u64, @@ -87,12 +82,6 @@ impl CrypStat { } } -pub struct Turn { - pub str: Roll, - pub agi: Roll, - pub log: Vec, -} - #[derive(Debug,Clone,Serialize,Deserialize)] pub struct Cryp { pub id: Uuid, @@ -189,22 +178,70 @@ impl Cryp { self.hp.value == 0 } + pub fn is_stunned(&self) -> bool { + self.statuses.iter().any(|s| s.status == Status::Stunned) + } + pub fn available_skills(&self) -> Vec<&CrypSkill> { - self.skills.iter().filter(|s| s.is_usable(self)).collect() + self.skills.iter().filter(|s| s.can_cast(self)).collect() } pub fn knows(&self, skill: Skill) -> bool { self.skills.iter().any(|s| s.skill == skill) } - pub fn has_cooldown(&self, skill: Skill) -> bool { + pub fn skill_on_cd(&self, skill: Skill) -> bool { self.skills.iter().any(|s| s.skill == skill && s.cd.is_some()) } + pub fn skill_can_cast(&self, skill: Skill) -> bool { + self.skills.iter().any(|s| s.skill == skill && !s.can_cast(self)) + } + pub fn rez(&mut self) -> &mut Cryp { self.hp.set(self.stam.value); self } + + pub fn roll(&self, skill: Skill) -> Roll { + let mut rng = thread_rng(); + let base: u64 = rng.gen(); + + let stat = match skill { + Skill::Attack => self.str, + Skill::Block => self.str, + Skill::Stun => self.str, + Skill::Dodge => self.agi, + Skill::Heal => self.int, + }; + + let mut roll = Roll { base, result: base }; + + // // apply skills + // roll = c.skills.iter().fold(roll, |roll, s| s.apply(roll)); + + // finally combine with stat + println!("{:?}'s stats", self.name); + println!("{:064b} <- finalised", roll.result); + roll.result = roll.result & stat.value; + + println!("{:064b} & <- attribute roll", stat.value); + println!("{:064b} = {:?}", roll.result, roll.result); + println!(""); + + return roll; + } + + pub fn stun(&mut self, roll: Roll) -> &mut Cryp { + self.statuses.push(CrypStatus { status: Status::Stunned, turns: 1 }); + self + } + + pub fn attack(&mut self, roll: Roll) -> &mut Cryp { + self.hp.reduce(roll.result); + self + } + } pub fn cryp_get(tx: &mut Transaction, id: Uuid, account_id: Uuid) -> Result { @@ -229,8 +266,7 @@ pub fn cryp_spawn(params: CrypSpawnParams, tx: &mut Transaction, account: &Accou let cryp = Cryp::new() .named(¶ms.name) .level(10) - .learn(Skill::Block) - .learn(Skill::Heal) + .learn(Skill::Stun) .set_account(account.id) .create(); diff --git a/server/src/game.rs b/server/src/game.rs index 198c6326..413484ec 100755 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -10,14 +10,14 @@ use failure::err_msg; use account::Account; use rpc::{GameStateParams, GameSkillParams, GamePveParams, GamePvpParams, GameTargetParams, GameJoinParams}; use cryp::{Cryp, cryp_get}; -use skill::{Skill, Turn}; +use skill::{Skill, Cast}; #[derive(Debug,Clone,Serialize,Deserialize)] pub struct Team { id: Uuid, cryps: Vec, - skills: Vec, - incoming: Vec, + skills: Vec, + incoming: Vec, } impl Team { @@ -31,7 +31,9 @@ impl Team { } fn skills_required(&self) -> usize { - self.cryps.iter().filter(|c| c.available_skills().len() > 0).collect::>().len() + let required = self.cryps.iter().filter(|c| c.available_skills().len() > 0).collect::>().len(); + println!("{:?} requires {:?} skills this turn", self.id, required); + return required; } pub fn set_cryps(&mut self, cryps: Vec) -> &mut Team { @@ -43,7 +45,7 @@ impl Team { self.cryps.iter_mut().find(|c| c.id == id) } - pub fn turn_by_id(&mut self, id: Uuid) -> &mut Turn { + pub fn cast_by_id(&mut self, id: Uuid) -> &mut Cast { match self.incoming.iter_mut().find(|a| a.id == id) { Some(a) => a, None => panic!("abiltity not in game"), @@ -184,7 +186,8 @@ impl Game { // 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_skill(mob_team_id, mob.id, player_team.id, Skill::Attack).unwrap(); + // doesn't matter if the cryp can't cast + self.add_skill(mob_team_id, mob.id, player_team.id, Skill::Attack).ok(); } } @@ -211,9 +214,13 @@ impl Game { return Err(err_msg("cryp does not have that skill")); } - if cryp.has_cooldown(skill) { + if cryp.skill_on_cd(skill) { return Err(err_msg("abiltity on cooldown")); } + + if cryp.skill_can_cast(skill) { + return Err(err_msg("cryp cannot cast spell")); + } } // replace cryp skill @@ -221,7 +228,7 @@ impl Game { team.skills.remove(s); } - let skill = Turn::new(cryp_id, target_team_id, skill); + let skill = Cast::new(cryp_id, target_team_id, skill); team.skills.push(skill); return Ok(skill.id); @@ -253,6 +260,11 @@ impl Game { self.pve_add_targets(); } + // all cryps are stunned or otherwise inactive + if self.target_phase_finished() { + self.damage_phase_start(); + } + self } @@ -271,7 +283,7 @@ impl Game { // targets can only be added by the owner of the team - fn add_target(&mut self, team_id: Uuid, cryp_id: Uuid, skill_id: Uuid) -> Result<&mut Turn, Error> { + fn add_target(&mut self, team_id: Uuid, cryp_id: Uuid, cast_id: Uuid) -> Result<&mut Cast, Error> { // whose team is this? let team = self.team_by_id(team_id); @@ -282,8 +294,8 @@ impl Game { }; // set the target - let turn = team.turn_by_id(skill_id); - Ok(turn.set_target(cryp_id)) + let cast = team.cast_by_id(cast_id); + Ok(cast.set_target(cryp_id)) } fn target_phase_finished(&self) -> bool { @@ -394,7 +406,7 @@ pub fn game_target(params: GameTargetParams, tx: &mut Transaction, account: &Acc let game_bytes: Vec = returned.get("data"); let mut game = from_slice::(&game_bytes)?; - game.add_target(account.id, params.cryp_id, params.skill_id)?; + game.add_target(account.id, params.cryp_id, params.cast_id)?; if game.target_phase_finished() { game.damage_phase_start(); diff --git a/server/src/rpc.rs b/server/src/rpc.rs index 736560b2..a7b3b08a 100755 --- a/server/src/rpc.rs +++ b/server/src/rpc.rs @@ -355,7 +355,7 @@ struct GameTargetMsg { pub struct GameTargetParams { pub game_id: Uuid, pub cryp_id: Uuid, - pub skill_id: Uuid, + pub cast_id: Uuid, } #[derive(Debug,Clone,Serialize,Deserialize)] diff --git a/server/src/skill.rs b/server/src/skill.rs index 8188790c..ab9b5953 100755 --- a/server/src/skill.rs +++ b/server/src/skill.rs @@ -20,65 +20,38 @@ pub enum Skill { #[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] -pub struct Turn { +pub struct Cast { pub id: Uuid, pub skill: Skill, pub cryp_id: Uuid, - pub roll: Option, pub target_cryp_id: Option, pub target_team_id: Uuid, } -impl Turn { - pub fn new(cryp_id: Uuid, target_team_id: Uuid, skill: Skill) -> Turn { - return Turn { +impl Cast { + pub fn new(cryp_id: Uuid, target_team_id: Uuid, skill: Skill) -> Cast { + return Cast { id: Uuid::new_v4(), cryp_id, target_cryp_id: None, target_team_id, - roll: None, skill, }; } - fn roll(&self, c: &Cryp) -> Roll { - let mut rng = thread_rng(); - let base: u64 = rng.gen(); + pub fn resolve(&mut self, cryp: &mut Cryp, target: &mut Cryp) -> &mut Cast { + let roll = cryp.roll(self.skill); - let stat = match self.skill { - Skill::Attack => &c.str, - Skill::Block => &c.str, - Skill::Stun => &c.str, - Skill::Dodge => &c.agi, - Skill::Heal => &c.int, + match self.skill { + Skill::Stun => target.stun(roll), + _ => target.attack(roll), }; - let mut roll = Roll { base, result: base }; - - // // apply skills - // roll = c.skills.iter().fold(roll, |roll, s| s.apply(roll)); - - // finally combine with stat - println!("{:?}'s stats", c.name); - println!("{:064b} <- finalised", roll.result); - roll.result = roll.result & stat.value; - - println!("{:064b} & <- attribute roll", stat.value); - println!("{:064b} = {:?}", roll.result, roll.result); - println!(""); - - return roll; - } - - pub fn resolve(&mut self, cryp: &mut Cryp, target: &mut Cryp) -> &mut Turn { - let roll = self.roll(&cryp); - println!("{:?} gettin clapped for {:?}", target.name, roll.result); - target.hp.reduce(roll.result); self } - pub fn set_target(&mut self, cryp_id: Uuid) -> &mut Turn { + pub fn set_target(&mut self, cryp_id: Uuid) -> &mut Cast { self.target_cryp_id = Some(cryp_id); self }