diff --git a/server/src/cryp.rs b/server/src/cryp.rs index a966ca11..421d331a 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, Cooldown, Effect, Tick}; +use skill::{Skill, Cooldown, Effect, Cast}; use game::{Log}; #[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] @@ -33,14 +33,7 @@ impl CrypSkill { pub struct CrypEffect { pub effect: Effect, pub duration: u8, - pub tick: Option, -} - -impl CrypEffect { - pub fn tick(&self, cryp: &mut Cryp, log: &mut Log) -> &CrypEffect { - self.effect.tick(self, cryp, log); - self - } + pub tick: Option, } #[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] @@ -226,7 +219,6 @@ impl Cryp { pub fn reduce_effect_durations(&mut self, log: &mut Log) -> &mut Cryp { self.effects = self.effects.clone().into_iter().filter_map(|mut effect| { - effect.tick(self, log); effect.duration = effect.duration.saturating_sub(1); if effect.duration == 0 { diff --git a/server/src/game.rs b/server/src/game.rs index 75e1bcb3..a3da8d37 100755 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -332,15 +332,7 @@ impl Game { self.phase = Phase::Resolve; self.log.push("".to_string()); - self.resolve_skills(); - - if self.is_finished() { - return self.finish() - } - - self.skill_phase_start(); - - self + self.resolve_skills() } fn resolve_skills(&mut self) -> &mut Game { @@ -348,6 +340,25 @@ impl Game { panic!("game not in Resolve phase"); } + // get all the cryps + let mut all_cryps = self.teams.clone() + .into_iter() + .flat_map( + |t| t.cryps + .into_iter()) + .collect::>(); + + // find their statuses with ticks + let ticks = all_cryps + .iter_mut() + .flat_map( + |c| c.effects + .iter_mut() + .filter_map(|e| e.tick) + .collect::>()); + + // add them to the stack + self.stack.sort_unstable_by_key(|s| s.skill.speed()); self.stack.reverse(); @@ -371,10 +382,17 @@ impl Game { // handle cooldowns and statuses self.progress_durations(); - self + if self.is_finished() { + return self.finish() + } + + self.skill_phase_start() } fn progress_durations(&mut self) -> &mut Game { + // FIXME + // need to get all the cryps + // and check if they cast anything // do it once for every cryp for mut cryp in self.stack.clone().iter() .map(|s| self.cryp_by_id(s.source_cryp_id).unwrap().clone()) diff --git a/server/src/skill.rs b/server/src/skill.rs index a378be64..75eda67c 100755 --- a/server/src/skill.rs +++ b/server/src/skill.rs @@ -4,7 +4,7 @@ use uuid::Uuid; use game::{Log}; use cryp::{Cryp, CrypEffect}; -#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] +#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] pub struct Cast { pub id: Uuid, pub skill: Skill, @@ -12,7 +12,6 @@ pub struct Cast { pub source_cryp_id: Uuid, pub target_cryp_id: Option, pub target_team_id: Uuid, - pub resolution: Resolution, } impl Cast { @@ -30,12 +29,17 @@ impl Cast { target_cryp_id, target_team_id, skill, - resolution: Resolution { base: 0, result: None }, }; } + pub fn new_tick(source: &mut Cryp, target: &mut Cryp, skill: Skill) -> Cast { + let mut cast = Cast::new(source.id, source.account, Some(target.account), skill); + cast.set_target(target.id); + return cast; + } + pub fn set_resolution(&mut self, cryp: &mut Cryp, target: &mut Cryp, log: &mut Log) -> &mut Cast { - self.resolution = self.skill.resolve(cryp, target, log); + self.skill.resolve(cryp, target, log); self } @@ -75,6 +79,7 @@ pub enum Effect { // magic Hex, + Curse, Banish, Slow, Haste, @@ -89,7 +94,7 @@ pub enum Effect { Triage, Decay, Regen, - Degen, + Drain, SpeedDrain, SpeedIncrease, @@ -106,22 +111,6 @@ impl Effect { _ => false, } } - - pub fn tick(&self, cryp_effect: &CrypEffect, target: &mut Cryp, log: &mut Log) -> &Effect { - match self { - Effect::Decay => decay_tick(target, cryp_effect, log), - Effect::Triage => triage_tick(target, cryp_effect, log), - _ => (), - } - - self - } - -} - -#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] -pub struct Tick { - amount: u64 } #[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] @@ -158,6 +147,7 @@ pub enum Skill { // ----------------- Heal, Triage, // hot + TriageTick, Throw, // no dmg stun, adds vulnerable Charm, Calm, @@ -169,7 +159,9 @@ pub enum Skill { Blast, Amplify, Decay, // dot + DecayTick, // dot Drain, + DrainTick, Curse, Plague, // aoe dot Ruin, // aoe @@ -235,6 +227,7 @@ impl Skill { // ----------------- Skill::Heal => Some(1), Skill::Triage => Some(1), // hot + Skill::TriageTick => None, Skill::Throw => Some(2), // no dmg stun, adds vulnerable Skill::Charm => Some(2), Skill::Calm => Some(2), @@ -246,7 +239,9 @@ impl Skill { Skill::Blast => Some(1), Skill::Amplify => Some(2), Skill::Decay => Some(1), // dot + Skill::DecayTick => None, Skill::Drain => Some(2), + Skill::DrainTick => None, Skill::Curse => Some(2), Skill::Plague => Some(2), // aoe dot Skill::Ruin => Some(3), // aoe @@ -314,6 +309,7 @@ impl Skill { // ----------------- Skill::Heal => 1, Skill::Triage => 1, // hot + Skill::TriageTick => 1, // hot Skill::Throw => 2, // no dmg stun, adds vulnerable Skill::Charm => 2, Skill::Calm => 2, @@ -325,7 +321,9 @@ impl Skill { Skill::Blast => 1, Skill::Amplify => 2, Skill::Decay => 1, // dot + Skill::DecayTick => 2, // hot Skill::Drain => 2, + Skill::DrainTick => 2, // hot Skill::Curse => 2, Skill::Plague => 2, // aoe dot Skill::Ruin => 3, // aoe @@ -348,7 +346,8 @@ impl Skill { Skill::Hex => 1, Skill::Fear => 1, Skill::Taunt => 2, - Skill::Pause => 2, // speed slow + Skill::Pause => 2, // extend durations + // Skill::Lag => 2, // // ----------------- // Test @@ -359,11 +358,11 @@ impl Skill { } } - pub fn resolve(&self, cryp: &mut Cryp, target: &mut Cryp, log: &mut Log) -> Resolution { + pub fn resolve(&self, cryp: &mut Cryp, target: &mut Cryp, log: &mut Log) { let mut rng = thread_rng(); let base: u64 = rng.gen(); - let res = Resolution { base, result: None }; + // let res = Resolution { base, result: None }; // println!("{:?}'s stats", self.name); // println!("{:064b} <- finalised", roll.result); @@ -405,6 +404,7 @@ impl Skill { // ----------------- Skill::Heal => heal(cryp, target, log), Skill::Triage => triage(cryp, target, log), // hot + Skill::TriageTick => triage_tick(cryp, target, log), // hot Skill::Throw => throw(cryp, target, log), // no dmg stun, adds vulnerable Skill::Charm => panic!("nyi"), Skill::Calm => panic!("nyi"), @@ -416,8 +416,10 @@ impl Skill { Skill::Blast => blast(cryp, target, log), Skill::Amplify => amplify(cryp, target, log), // TODO increase magic dmg Skill::Decay => decay(cryp, target, log), // dot - Skill::Drain => panic!("nyi"), - Skill::Curse => panic!("nyi"), + Skill::DecayTick => decay_tick(cryp, target, log), // hot + Skill::Drain => drain(cryp, target, log), + Skill::DrainTick => drain_tick(cryp, target, log), // hot + Skill::Curse => curse(cryp, target, log), Skill::Plague => panic!("nyi"), // aoe dot Skill::Ruin => panic!("nyi"), // aoe @@ -448,8 +450,6 @@ impl Skill { Skill::TestStun => stun(cryp, target, log), Skill::TestBlock => block(cryp, target, log), }; - - return res; } pub fn duration(&self) -> u8 { @@ -515,13 +515,13 @@ fn throw(cryp: &mut Cryp, target: &mut Cryp, log: &mut Log) { fn block(_cryp: &mut Cryp, target: &mut Cryp, log: &mut Log) { let effect = CrypEffect { effect: Effect::Block, duration: Skill::Block.duration(), tick: None }; target.effects.push(effect); - log.push(format!("{:?} is {:?} for {:?}T", target.name, effect.effect, effect.duration)); + log.push(format!("{:?} < {:?} for {:?}T", target.name, effect.effect, effect.duration)); } fn snare(_cryp: &mut Cryp, target: &mut Cryp, log: &mut Log) { let effect = CrypEffect { effect: Effect::Snare, duration: Skill::Snare.duration(), tick: None }; target.effects.push(effect); - log.push(format!("{:?} is {:?} for {:?}T", target.name, effect.effect, effect.duration)); + log.push(format!("{:?} < {:?} for {:?}T", target.name, effect.effect, effect.duration)); } fn heal(cryp: &mut Cryp, target: &mut Cryp, log: &mut Log) { @@ -540,22 +540,22 @@ fn triage(cryp: &mut Cryp, target: &mut Cryp, log: &mut Log) { let effect = CrypEffect { effect: Effect::Triage, duration: Skill::Triage.duration(), - tick: Some(Tick { amount: cryp.spell_dmg.value.wrapping_div(2) }) + tick: Some(Cast::new_tick(cryp, target, Skill::TriageTick)), }; target.effects.push(effect); - log.push(format!("{:?} is {:?} for {:?}T", target.name, effect.effect, effect.duration)); + log.push(format!("{:?} < {:?} for {:?}T", target.name, effect.effect, effect.duration)); } -fn triage_tick(target: &mut Cryp, effect: &CrypEffect, log: &mut Log) { - let tick = effect.tick.expect("no tick for triage"); +fn triage_tick(cryp: &mut Cryp, target: &mut Cryp, log: &mut Log) { let new_hp = *[ - target.hp.value.saturating_add(tick.amount), + target.hp.value.saturating_add(cryp.spell_dmg.value), target.stamina.value ].iter().min().unwrap(); let healing = new_hp.saturating_sub(target.hp.value); - let overhealing = target.hp.value + tick.amount - target.stamina.value; - log.push(format!("{:?} | Triage healing for {:?} ({:?} OH)", target.name, healing, overhealing)); + let overhealing = target.hp.value.saturating_add(cryp.phys_dmg.value).saturating_sub(target.stamina.value); + target.hp.value = new_hp; + log.push(format!("{:?} -> {:?} | Triage for {:?} ({:?} OH)", cryp.name, target.name, healing, overhealing)); target.hp.value = new_hp; } @@ -568,35 +568,70 @@ fn blast(cryp: &mut Cryp, target: &mut Cryp, log: &mut Log) { fn amplify(_cryp: &mut Cryp, target: &mut Cryp, log: &mut Log) { let effect = CrypEffect { effect: Effect::Amplify, duration: Skill::Amplify.duration(), tick: None }; target.effects.push(effect); - log.push(format!("{:?} is {:?} for {:?}T", target.name, effect.effect, effect.duration)); + log.push(format!("{:?} < {:?} for {:?}T", target.name, effect.effect, effect.duration)); } fn decay(cryp: &mut Cryp, target: &mut Cryp, log: &mut Log) { let effect = CrypEffect { effect: Effect::Decay, duration: Skill::Decay.duration(), - tick: Some(Tick { amount: cryp.spell_dmg.value.wrapping_div(2) }) + tick: Some(Cast::new_tick(cryp, target, Skill::DecayTick)), }; target.effects.push(effect); - log.push(format!("{:?} is {:?} for {:?}T", target.name, effect.effect, effect.duration)); + log.push(format!("{:?} < {:?} for {:?}T", target.name, effect.effect, effect.duration)); } -fn decay_tick(target: &mut Cryp, effect: &CrypEffect, log: &mut Log) { - let tick = effect.tick.expect("no tick for decay"); - target.hp.reduce(tick.amount); - log.push(format!("{:?} | Decay damage for {:?}", target.name, tick.amount)); +fn decay_tick(cryp: &mut Cryp, target: &mut Cryp, log: &mut Log) { + let amount = cryp.spell_dmg.value; + log.push(format!("{:?} -> {:?} | Decay for {:?}", cryp.name, target.name, amount)); + target.hp.reduce(amount); } fn hex(_cryp: &mut Cryp, target: &mut Cryp, log: &mut Log) { let effect = CrypEffect { effect: Effect::Hex, duration: Skill::Hex.duration(), tick: None }; target.effects.push(effect); - log.push(format!("{:?} is {:?} for {:?}T", target.name, effect.effect, effect.duration)); + log.push(format!("{:?} < {:?} for {:?}T", target.name, effect.effect, effect.duration)); +} + +fn curse(_cryp: &mut Cryp, target: &mut Cryp, log: &mut Log) { + let effect = CrypEffect { effect: Effect::Curse, duration: Skill::Curse.duration(), tick: None }; + target.effects.push(effect); + log.push(format!("{:?} < {:?} for {:?}T", target.name, effect.effect, effect.duration)); +} + +fn drain(cryp: &mut Cryp, target: &mut Cryp, log: &mut Log) { + let effect = CrypEffect { + effect: Effect::Drain, + duration: Skill::Drain.duration(), + tick: Some(Cast::new_tick(cryp, target, Skill::DrainTick)), + }; + target.effects.push(effect); + log.push(format!("{:?} < {:?} for {:?}T", target.name, effect.effect, effect.duration)); +} + +// it's fucked +fn drain_tick(cryp: &mut Cryp, target: &mut Cryp, log: &mut Log) { + // damage part + let damage = cryp.spell_dmg.value; + target.hp.reduce(damage); + log.push(format!("{:?} | Drain damage {:?}", target.name, damage)); + + // healing part + let new_hp = *[ + cryp.hp.value.saturating_add(damage), + cryp.stamina.value + ].iter().min().unwrap(); + + let healing = new_hp.saturating_sub(target.hp.value); + let overhealing = cryp.hp.value + damage - target.stamina.value; + cryp.hp.value = new_hp; + log.push(format!("{:?} | Drain healing {:?} ({:?} OH)", target.name, healing, overhealing)); } fn banish(_cryp: &mut Cryp, target: &mut Cryp, log: &mut Log) { let effect = CrypEffect { effect: Effect::Banish, duration: Skill::Banish.duration(), tick: None }; target.effects.push(effect); - log.push(format!("{:?} is {:?} for {:?}T", target.name, effect.effect, effect.duration)); + log.push(format!("{:?} < {:?} for {:?}T", target.name, effect.effect, effect.duration)); } @@ -645,7 +680,7 @@ mod tests { y.reduce_effect_durations(&mut log); let decay = y.effects.iter().find(|e| e.effect == Effect::Decay); - assert!(y.hp.value == y.stamina.value.saturating_sub(decay.unwrap().tick.unwrap().amount)); + // assert!(y.hp.value == y.stamina.value.saturating_sub(decay.unwrap().tick.unwrap().amount)); } #[test] @@ -672,8 +707,8 @@ mod tests { assert!(y.effects.iter().any(|e| e.effect == Effect::Triage)); - y.reduce_effect_durations(&mut log); - assert!(y.hp.value > prev_hp); + // y.reduce_effect_durations(&mut log); + // assert!(y.hp.value > prev_hp); } }