diff --git a/server/src/game.rs b/server/src/game.rs index 6a0c8500..69f2d0ff 100755 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -16,9 +16,6 @@ use skill::{Skill, Cast}; pub struct Team { id: Uuid, cryps: Vec, - skills: Vec, - incoming: Vec, - resolved: Vec, } impl Team { @@ -26,9 +23,6 @@ impl Team { return Team { id: account, cryps: vec![], - skills: vec![], - incoming: vec![], - resolved: vec![] }; } @@ -53,35 +47,6 @@ impl Team { pub fn cryp_by_id(&mut self, id: Uuid) -> Option<&mut Cryp> { self.cryps.iter_mut().find(|c| c.id == id) } - - 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"), - } - } - - pub fn progress_cooldowns(&mut self) -> &mut Team { - // get a copy of the used skills - for skill in self.skills.clone().iter() { - // copy the creep cause we will replace it - let mut cryp = self.cryp_by_id(skill.cryp_id).unwrap().clone(); - - if skill.used_cooldown() { - cryp.skill_set_cd(skill.skill); - self.update_cryp(cryp); - continue; - } - - cryp.decrease_cooldowns(); - - println!("{:?}", cryp); - - self.update_cryp(cryp); - } - - self - } } #[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] @@ -101,6 +66,8 @@ pub struct Game { pub teams: Vec, pub is_pve: bool, pub phase: Phase, + pub skills: Vec, + pub resolutions: Vec, pub log: Vec, } @@ -113,6 +80,8 @@ impl Game { teams: vec![], is_pve: true, phase: Phase::Start, + skills: vec![], + resolutions: vec![], log: vec![], }; } @@ -171,6 +140,19 @@ impl Game { } } + fn update_cryp(&mut self, cryp: &mut Cryp) -> &mut Game { + match self.teams.iter_mut().find(|t| t.cryps.iter().any(|c| c.id == cryp.id)) { + Some(team) => { + let index = team.cryps.iter().position(|t| t.id == cryp.id).unwrap(); + team.cryps.remove(index); + team.cryps.push(cryp.clone()); + }, + None => panic!("cryp not in game"), + }; + + self + } + fn can_start(&self) -> bool { self.teams.len() == self.team_num } @@ -186,10 +168,8 @@ impl Game { } self.phase = Phase::Skill; - for team in self.teams.iter_mut() { - team.skills.clear(); - team.incoming.clear(); - } + + self.skills.clear(); if self.is_pve { self.pve_add_skills(); @@ -201,13 +181,13 @@ impl Game { fn pve_add_skills(&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(); + let player_team_id = self.teams.iter().find(|t| t.id != mob_team_id).unwrap().id; for mob in &mobs.cryps { // doesn't matter if the cryp can't cast - self.add_skill(mob_team_id, mob.id, player_team.id, Skill::Attack).ok(); + self.add_skill(mob_team_id, mob.id, player_team_id, Skill::Attack).ok(); } } @@ -216,15 +196,14 @@ impl Game { // skills can target any team, but we have to check if the caller is the owner of the cryp // and that the cryp has the skill they are trying to add - fn add_skill(&mut self, team_id: Uuid, cryp_id: Uuid, target_team_id: Uuid, skill: Skill) -> Result { + fn add_skill(&mut self, team_id: Uuid, source_cryp_id: Uuid, target_team_id: Uuid, skill: Skill) -> Result { if self.phase != Phase::Skill { return Err(err_msg("game not in skill phase")); } - let team = self.team_by_id(team_id); - { - let cryp = match team.cryp_by_id(cryp_id) { + let team = self.team_by_id(team_id); + let cryp = match team.cryp_by_id(source_cryp_id) { Some(c) => c, None => return Err(err_msg("cryp not in team")), }; @@ -245,18 +224,26 @@ impl Game { // replace cryp skill - if let Some(s) = team.skills.iter_mut().position(|s| s.cryp_id == cryp_id) { - team.skills.remove(s); + if let Some(s) = self.skills.iter_mut().position(|s| s.source_cryp_id == source_cryp_id) { + self.skills.remove(s); } - let skill = Cast::new(cryp_id, target_team_id, skill); - team.skills.push(skill); + let skill = Cast::new(source_cryp_id, team_id, target_team_id, skill); + self.skills.push(skill); return Ok(skill.id); } fn skill_phase_finished(&self) -> bool { - self.teams.iter().all(|t| t.skills.len() == t.skills_required()) + self.teams.iter() + // for every team + .all(|t| self.skills.iter() + // the number of skills they have cast + .filter(|s| s.target_team_id == t.id) + .collect::>() + // should equal the number required this turn + .len() == t.skills_required() + ) } // move all skills into their target team's targets list @@ -267,16 +254,6 @@ impl Game { self.phase = Phase::Target; - // have to clone the teams because we change them while iterating - let teams = self.teams.clone(); - - for mut team in teams { - for skill in team.skills.iter_mut() { - let target_team = self.team_by_id(skill.target_team_id); - target_team.incoming.push(*skill); - } - } - if self.is_pve { self.pve_add_targets(); } @@ -294,33 +271,38 @@ impl 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).unwrap(); + for incoming_skill_id in self.skills.clone().iter().filter(|s| s.target_team_id == mob_team_id).map(|s| s.id) { + self.add_target(mob_team_id, mobs.cryps[0].id, incoming_skill_id).unwrap(); } } self } - // targets can only be added by the owner of the team 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); + { + // whose team is this? + let team = self.team_by_id(team_id); - // is the target in the team? - match team.cryp_by_id(cryp_id) { - Some(c) => c, - None => return Err(err_msg("cryp not in team")), - }; + // is the target in the team? + match team.cryp_by_id(cryp_id) { + Some(c) => c, + None => return Err(err_msg("cryp not in team")), + }; + } // set the target - let cast = team.cast_by_id(cast_id); + let cast = match self.skills.iter_mut().find(|s| s.id == cast_id) { + Some(c) => c, + None => return Err(err_msg("cast_id not found")), + }; + Ok(cast.set_target(cryp_id)) } fn target_phase_finished(&self) -> bool { - self.teams.iter().all(|t| t.incoming.iter().all(|i| i.target_cryp_id.is_some())) + self.skills.iter().all(|s| s.target_cryp_id.is_some()) } // requires no input @@ -348,30 +330,44 @@ impl Game { panic!("game not in damage phase"); } - // sometimes... you just gotta - for team in self.teams.clone().iter_mut() { - for incoming in team.incoming.clone().iter_mut() { - // 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(); - let resolution = incoming.resolve(&mut cryp, &mut target_cryp); + for skill in self.skills.clone().iter_mut() { + let mut source = self.cryp_by_id(skill.source_cryp_id).clone(); + let mut target = self.cryp_by_id(skill.target_cryp_id.unwrap()).clone(); + let resolution = skill.resolve(&mut source, &mut target); - // push the resolved spell on - team.resolved.push(*resolution); - team.update_cryp(target_cryp); - self.update_team(team); - } + self.update_cryp(&mut source); + self.update_cryp(&mut target); } // now damage has all been assigned // handle cooldowns - for team in self.teams.iter_mut() { - team.progress_cooldowns(); + self.progress_cooldowns(); + + self + } + + fn progress_cooldowns(&mut self) -> &mut Game { + for skill in self.skills.clone().iter() { + // copy the creep cause we will replace it + let mut cryp = self.cryp_by_id(skill.source_cryp_id).clone(); + + if skill.used_cooldown() { + cryp.skill_set_cd(skill.skill); + self.update_cryp(&mut cryp); + continue; + } + + cryp.decrease_cooldowns(); + + println!("{:?}", cryp); + + self.update_cryp(&mut cryp); } self } + fn is_finished(&self) -> bool { self.teams.iter().any(|t| t.cryps.iter().all(|c| c.is_ko())) } @@ -379,10 +375,7 @@ impl Game { fn finish(&mut self) -> &mut Game { self.phase = Phase::Finish; - for team in self.teams.iter_mut() { - team.skills.clear(); - team.incoming.clear(); - } + self.skills.clear(); self } @@ -714,62 +707,64 @@ mod tests { return game; } - // #[test] - // fn phase_test() { - // let mut game = create_test_game(); + #[test] + fn phase_test() { + let mut game = create_test_game(); - // let x_team = game.teams[0].clone(); - // let y_team = game.teams[1].clone(); + 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_cryp = x_team.cryps[0].clone(); + let y_cryp = y_team.cryps[0].clone(); - // let x_attack_id = game.add_skill(x_team.id, x_cryp.id, y_team.id, Skill::Attack).unwrap(); - // let y_attack_id = game.add_skill(y_team.id, y_cryp.id, x_team.id, Skill::Attack).unwrap(); + let x_attack_id = game.add_skill(x_team.id, x_cryp.id, y_team.id, Skill::Attack).unwrap(); + let y_attack_id = game.add_skill(y_team.id, y_cryp.id, x_team.id, Skill::Attack).unwrap(); - // assert!(game.skill_phase_finished()); + assert!(game.skill_phase_finished()); - // game.target_phase_start(); + 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_attack_id).unwrap(); + game.add_target(x_team.id, x_cryp.id, y_attack_id).unwrap(); + game.add_target(y_team.id, y_cryp.id, x_attack_id).unwrap(); - // assert!(game.target_phase_finished()); + assert!(game.target_phase_finished()); - // game.damage_phase_start(); + game.damage_phase_start(); - // assert!([Phase::Skill, Phase::Finish].contains(&game.phase)); + assert!([Phase::Skill, Phase::Finish].contains(&game.phase)); - // return; - // } + return; + } - // #[test] - // fn stun_test() { - // let mut game = create_test_game(); + #[test] + fn stun_test() { + let mut game = create_test_game(); - // let x_team = game.teams[0].clone(); - // let y_team = game.teams[1].clone(); + 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_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(); + 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(); + 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(); + 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(); + 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 auto progress back to skill phase + assert!(game.phase == Phase::Skill); + + println!("{:#?}", game); + assert!(game.team_by_id(y_team.id).cryps[0].is_stunned()); + assert!(game.team_by_id(y_team.id).skills_required() == 0); + } #[test] fn cooldown_test() { diff --git a/server/src/skill.rs b/server/src/skill.rs index 0e2d2fc3..d01114c4 100755 --- a/server/src/skill.rs +++ b/server/src/skill.rs @@ -26,17 +26,19 @@ pub enum Skill { pub struct Cast { pub id: Uuid, pub skill: Skill, - pub cryp_id: Uuid, + pub source_team_id: Uuid, + pub source_cryp_id: Uuid, pub target_cryp_id: Option, pub target_team_id: Uuid, pub roll: Option, } impl Cast { - pub fn new(cryp_id: Uuid, target_team_id: Uuid, skill: Skill) -> Cast { + pub fn new(source_cryp_id: Uuid, source_team_id: Uuid, target_team_id: Uuid, skill: Skill) -> Cast { return Cast { id: Uuid::new_v4(), - cryp_id, + source_cryp_id, + source_team_id, target_cryp_id: None, target_team_id, skill, @@ -62,7 +64,7 @@ impl Cast { Skill::TestTouch => target, }; - println!("{:?} gettin clapped for {:?}", target.name, roll.result); + // println!("{:?} gettin clapped for {:?}", target.name, roll.result); self.roll = Some(roll); self