diff --git a/server/WORKLOG.md b/server/WORKLOG.md index a82abd4b..ea0ecff3 100755 --- a/server/WORKLOG.md +++ b/server/WORKLOG.md @@ -4,30 +4,19 @@ * Prove something # WORK WORK -* QOL - * auto login - * cryp list on spawn - * ws reconnect ✔ -* Levelling ✔ +* move rpc functions out + * unwrap account for all functions except list * Global rolls -* Logins ✔️ - * Cryp Ownership ✔ - -* Matchmaking - * Lobbies - * Create - * Join - * Resolve - * Stats * Scrabble grid * skills * offensive -> choose target ✔ * private fields for opponents + * cooldowns reduce each turn * teach cyps skills * can you attack yourself? * fetch existing battles @@ -50,6 +39,17 @@ * Cryp Generation * +* ws reconnect ✔ +* Levelling ✔ +* Logins ✔️ + * Cryp Ownership ✔ +* Matchmaking ✔ + * Lobbies ✔ + * Create ✔ + * Join ✔ + * Resolve ✔ + + # Db maintenance * delete games when a cryp is deleted * does this need to happen? can have historical games diff --git a/server/src/cryp.rs b/server/src/cryp.rs index dd018cea..5e27aa23 100755 --- a/server/src/cryp.rs +++ b/server/src/cryp.rs @@ -26,7 +26,9 @@ impl CrypSkill { Skill::Block => Some(1), Skill::Dodge => Some(1), Skill::Heal => Some(2), - Skill::Stun => None, + Skill::Stun => Some(2), + Skill::TestTouch => None, + Skill::TestStun => None, }; CrypSkill { @@ -190,12 +192,12 @@ impl Cryp { self.skills.iter().any(|s| s.skill == skill) } - pub fn skill_on_cd(&self, skill: Skill) -> bool { - self.skills.iter().any(|s| s.skill == skill && s.cd.is_some()) + pub fn skill_on_cd(&self, skill: Skill) -> Option<&CrypSkill> { + self.skills.iter().find(|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)) + self.skills.iter().any(|s| s.skill == skill && s.can_cast(self)) } pub fn rez(&mut self) -> &mut Cryp { @@ -213,6 +215,10 @@ impl Cryp { Skill::Stun => self.str, Skill::Dodge => self.agi, Skill::Heal => self.int, + + // test skills + Skill::TestTouch => self.int, + Skill::TestStun => self.str, }; let mut roll = Roll { base, result: base }; diff --git a/server/src/game.rs b/server/src/game.rs index 413484ec..94dcf67e 100755 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -18,6 +18,7 @@ pub struct Team { cryps: Vec, skills: Vec, incoming: Vec, + resolved: Vec, } impl Team { @@ -27,6 +28,7 @@ impl Team { cryps: vec![], skills: vec![], incoming: vec![], + resolved: vec![] }; } @@ -41,6 +43,13 @@ impl Team { self } + fn update_cryp(&mut self, updated: Cryp) -> &mut Team { + let index = self.cryps.iter().position(|c| c.id == updated.id).unwrap(); + self.cryps.remove(index); + self.cryps.push(updated); + self + } + pub fn cryp_by_id(&mut self, id: Uuid) -> Option<&mut Cryp> { self.cryps.iter_mut().find(|c| c.id == id) } @@ -129,26 +138,15 @@ impl Game { panic!("cryp not in game"); } - // fn update_team(&mut self, updated: Team) -> &mut Game { - // match self.teams.iter().position(|t| t.id == updated.id) { - // Some(index) => { - // self.teams.remove(index); - // self.teams.push(updated); - // self - // } - // None => panic!("team not in game"), - // } - // } - - fn update_cryp(&mut self, updated: Cryp) -> &mut Game { - for team in self.teams.iter_mut() { - if let Some(index) = team.cryps.iter().position(|c| c.id == updated.id) { - team.cryps.remove(index); - team.cryps.push(updated); - break; + fn update_team(&mut self, updated: &mut Team) -> &mut Game { + match self.teams.iter().position(|t| t.id == updated.id) { + Some(index) => { + self.teams.remove(index); + self.teams.push(updated.clone()); + self } + None => panic!("team not in game"), } - self } fn can_start(&self) -> bool { @@ -214,15 +212,16 @@ impl Game { return Err(err_msg("cryp does not have that skill")); } - if cryp.skill_on_cd(skill) { + if cryp.skill_on_cd(skill).is_some() { return Err(err_msg("abiltity on cooldown")); } - if cryp.skill_can_cast(skill) { + if !cryp.skill_can_cast(skill) { return Err(err_msg("cryp cannot cast spell")); } } + // replace cryp skill if let Some(s) = team.skills.iter_mut().position(|s| s.cryp_id == cryp_id) { team.skills.remove(s); @@ -333,11 +332,13 @@ impl Game { // they better fuckin be there let mut cryp = self.cryp_by_id(incoming.cryp_id).clone(); let mut target_cryp = self.cryp_by_id(incoming.target_cryp_id.unwrap()).clone(); - println!("{:?} is attacking {:?}", cryp.name, target_cryp.name); - incoming.resolve(&mut cryp, &mut target_cryp); - self.update_cryp(target_cryp); + let resolution = incoming.resolve(&mut cryp, &mut target_cryp); + team.resolved.push(*resolution); + team.update_cryp(target_cryp); + self.update_team(team); } } + self } @@ -638,6 +639,55 @@ mod tests { use game::*; use cryp::*; + fn create_test_game() -> Game { + let x = Cryp::new() + .named(&"pronounced \"creeep\"".to_string()) + .level(8) + .learn(Skill::TestStun) + .learn(Skill::TestTouch) + .learn(Skill::Block) + .create(); + + let _x_id = x.id; + + let y = Cryp::new() + .named(&"lemongrass tea".to_string()) + .level(8) + .learn(Skill::TestStun) + .learn(Skill::TestTouch) + .learn(Skill::Block) + .create(); + + let _y_id = y.id; + + let mut game = Game::new(); + + game + .set_team_num(2) + .set_team_size(1) + .set_pve(false); + + let x_team_id = Uuid::new_v4(); + let mut x_team = Team::new(x_team_id); + x_team + .set_cryps(vec![x]); + + let y_team_id = Uuid::new_v4(); + let mut y_team = Team::new(y_team_id); + y_team + .set_cryps(vec![y]); + + game + .add_team(x_team).unwrap() + .add_team(y_team).unwrap(); + + assert!(game.can_start()); + + game.start(); + + return game; + } + #[test] fn game_test() { let x = Cryp::new() @@ -701,4 +751,39 @@ mod tests { return; } + + #[test] + fn cooldown_test() { + let mut game = create_test_game(); + + let x_team = game.teams[0].clone(); + let y_team = game.teams[1].clone(); + + let x_cryp = x_team.cryps[0].clone(); + let y_cryp = y_team.cryps[0].clone(); + + let x_stun_id = game.add_skill(x_team.id, x_cryp.id, y_team.id, Skill::TestStun).unwrap(); + let y_attack_id = game.add_skill(y_team.id, y_cryp.id, x_team.id, Skill::TestTouch).unwrap(); + + assert!(game.skill_phase_finished()); + game.target_phase_start(); + + game.add_target(x_team.id, x_cryp.id, y_attack_id).unwrap(); + game.add_target(y_team.id, y_cryp.id, x_stun_id).unwrap(); + + assert!(game.target_phase_finished()); + game.damage_phase_start(); + + // should auto progress back to skill phase + assert!(game.phase == Phase::Skill); + assert!(game.team_by_id(y_team.id).cryps[0].is_stunned()); + assert!(game.team_by_id(y_team.id).skills_required() == 0); + + // should be on cooldown now + assert!(game.add_skill(x_team.id, x_cryp.id, y_team.id, Skill::Stun).is_err()); + + println!("{:#?}", game); + // after 1 turn block should be off cooldown + assert!(game.team_by_id(y_team.id).cryps[0].skill_on_cd(Skill::Block).is_none()); + } } diff --git a/server/src/skill.rs b/server/src/skill.rs index ab9b5953..cb65ee6e 100755 --- a/server/src/skill.rs +++ b/server/src/skill.rs @@ -16,6 +16,9 @@ pub enum Skill { Heal, Stun, Dodge, + // used by tests to do no dmg + TestTouch, + TestStun, } @@ -26,6 +29,7 @@ pub struct Cast { pub cryp_id: Uuid, pub target_cryp_id: Option, pub target_team_id: Uuid, + pub roll: Option, } impl Cast { @@ -36,18 +40,31 @@ impl Cast { target_cryp_id: None, target_team_id, skill, + roll: None, }; } pub fn resolve(&mut self, cryp: &mut Cryp, target: &mut Cryp) -> &mut Cast { let roll = cryp.roll(self.skill); + println!("{:?} -> {:?} -> {:?}", cryp.name, self.skill, target.name); + match self.skill { + // the real deal Skill::Stun => target.stun(roll), - _ => target.attack(roll), + Skill::Attack => target.attack(roll), + Skill::Block => target, + Skill::Heal => target, + Skill::Dodge => target, + + // Test Skills + Skill::TestStun => target.stun(roll), + Skill::TestTouch => target, }; println!("{:?} gettin clapped for {:?}", target.name, roll.result); + + self.roll = Some(roll); self }