From 168bf81f3e11256c6dde9028e37878a1fd761ebe Mon Sep 17 00:00:00 2001 From: ntr Date: Sat, 7 Dec 2019 14:50:51 +1000 Subject: [PATCH] compiles --- core/src/construct.rs | 52 ++--- core/src/game.rs | 482 +++++++++++++++++++++--------------------- core/src/skill.rs | 26 +-- 3 files changed, 278 insertions(+), 282 deletions(-) diff --git a/core/src/construct.rs b/core/src/construct.rs index 2f494922..26fab7ce 100644 --- a/core/src/construct.rs +++ b/core/src/construct.rs @@ -5,7 +5,7 @@ use failure::Error; use failure::err_msg; use skill::{Skill, Cast}; -use game::{Colour, Disable, EventVariant, EventConstruct}; +use game::{Colour, Disable, Event, EventConstruct}; use effect::{Cooldown, Effect}; use spec::{Spec}; use item::{Item}; @@ -415,7 +415,7 @@ impl Construct { self } - pub fn increase_cooldowns(&mut self, turns: usize) -> Vec { + pub fn increase_cooldowns(&mut self, turns: usize) -> Vec { let mut events = vec![]; for skill in self.skills.iter_mut() { @@ -423,11 +423,11 @@ impl Construct { match skill.cd { Some(cd) => { skill.cd = Some(cd.saturating_add(turns)); - events.push(EventVariant::CooldownIncrease { construct: self.id, turns }) + events.push(Event::CooldownIncrease { construct: self.id, turns }) }, None => { skill.cd = Some(turns); - events.push(EventVariant::CooldownIncrease { construct: self.id, turns }) + events.push(Event::CooldownIncrease { construct: self.id, turns }) }, } } @@ -546,7 +546,7 @@ impl Construct { } } - pub fn recharge(&mut self, red_amount: usize, blue_amount: usize) -> Vec { + pub fn recharge(&mut self, red_amount: usize, blue_amount: usize) -> Vec { let mut events = vec![]; if self.is_ko() { return events; } @@ -564,7 +564,7 @@ impl Construct { let blue = new_blue_life - current_blue_life; if red != 0 || blue != 0 { - events.push(EventVariant::Recharge { construct: self.id, red, blue }); + events.push(Event::Recharge { construct: self.id, red, blue }); } }, true => { @@ -590,7 +590,7 @@ impl Construct { self.reduce_green_life(red_remainder); let red_damage_amount = red_current_green_life - self.green_life(); - events.push(EventVariant::Damage { + events.push(Event::Damage { construct: self.id, amount: red_damage_amount, mitigation: red_mitigation, @@ -620,7 +620,7 @@ impl Construct { self.reduce_green_life(blue_remainder); let blue_damage_amount = blue_current_green_life - self.green_life(); - events.push(EventVariant::Damage { + events.push(Event::Damage { construct: self.id, amount: blue_damage_amount, mitigation: blue_mitigation, @@ -633,7 +633,7 @@ impl Construct { return events; } - pub fn deal_green_damage(&mut self, amount: usize) -> Vec { + pub fn deal_green_damage(&mut self, amount: usize) -> Vec { let mut events = vec![]; if self.is_ko() { return events; } let construct = self.id; @@ -655,21 +655,21 @@ impl Construct { let healing = new_green_life - current_green_life; let overhealing = modified_power - healing; - events.push(EventVariant::Healing { + events.push(Event::Healing { construct, amount: healing, overhealing, }); }, true => { - // events.push(Event::new(EventVariant::Inversion { skill })); + // events.push(Event::new(Event::Inversion { skill })); // there is no green shield (yet) let current_green_life = self.green_life(); self.reduce_green_life(modified_power); let delta = current_green_life - self.green_life(); - events.push(EventVariant::Damage { + events.push(Event::Damage { construct, amount: delta, mitigation: 0, @@ -682,7 +682,7 @@ impl Construct { return events; } - pub fn deal_red_damage(&mut self, amount: usize) -> Vec { + pub fn deal_red_damage(&mut self, amount: usize) -> Vec { let mut events = vec![]; if self.is_ko() { return events; } @@ -714,7 +714,7 @@ impl Construct { let delta = current_green_life - self.green_life(); events.push( - EventVariant::Damage { + Event::Damage { construct, amount: delta, mitigation, @@ -723,11 +723,11 @@ impl Construct { } ); if self.is_ko() { - events.push(EventVariant::Ko { construct }); + events.push(Event::Ko { construct }); } }, true => { - // events.push(Event::new(EventVariant::Inversion { skill })); + // events.push(Event::new(Event::Inversion { skill })); let current_green_life = self.green_life(); self.green_life.increase(modified_power); @@ -741,7 +741,7 @@ impl Construct { if healing > 0 { events.push( - EventVariant::Healing { + Event::Healing { construct, amount: healing, overhealing: overhealing - recharge, @@ -750,7 +750,7 @@ impl Construct { } if recharge > 0 { - events.push(EventVariant::Recharge { construct, red: recharge, blue: 0 }); + events.push(Event::Recharge { construct, red: recharge, blue: 0 }); } } }; @@ -758,7 +758,7 @@ impl Construct { return events; } - pub fn deal_blue_damage(&mut self, amount: usize) -> Vec { + pub fn deal_blue_damage(&mut self, amount: usize) -> Vec { let mut events = vec![]; if self.is_ko() { return events; } @@ -785,7 +785,7 @@ impl Construct { self.reduce_green_life(remainder); let delta = current_green_life - self.green_life(); - events.push(EventVariant::Damage { + events.push(Event::Damage { construct, amount: delta, mitigation, @@ -794,7 +794,7 @@ impl Construct { }); }, true => { - // events.push(Event::new(EventVariant::Inversion { skill })); + // events.push(Event::new(Event::Inversion { skill })); let current_green_life = self.green_life(); self.green_life.increase(modified_power); @@ -807,11 +807,11 @@ impl Construct { let recharge = self.blue_life.value - current_life; if healing > 0 { - events.push(EventVariant::Healing { construct, amount: healing, overhealing }); + events.push(Event::Healing { construct, amount: healing, overhealing }); } if recharge > 0 { - events.push(EventVariant::Recharge { construct, red: 0, blue: recharge }); + events.push(Event::Recharge { construct, red: 0, blue: recharge }); } } }; @@ -819,7 +819,7 @@ impl Construct { return events; } - pub fn add_effect(&mut self, effect: ConstructEffect) -> Vec { + pub fn add_effect(&mut self, effect: ConstructEffect) -> Vec { if self.is_ko() { return vec![] } if self.affected(Effect::Banish) { panic!("banish immunity not fixt yet") } @@ -836,7 +836,7 @@ impl Construct { } // todo modified durations cause of buffs - let result = EventVariant::Effect { + let result = Event::Effect { construct: self.id, effect: effect.effect, duration: effect.duration, @@ -858,7 +858,7 @@ impl Construct { // info!("{:} < {:?}", roll, evasion_rating); // match roll < evasion_rating { - // true => Some(EventVariant::Evasion { + // true => Some(Event::Evasion { // skill, // evasion_rating: evasion_rating, // }), diff --git a/core/src/game.rs b/core/src/game.rs index 4745fc88..84bb86f8 100644 --- a/core/src/game.rs +++ b/core/src/game.rs @@ -16,167 +16,6 @@ use effect::{Effect}; use player::{Player}; use instance::{TimeControl}; -#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] -pub enum Phase { - Start, - Skill, - Resolve, - Finished, -} - -#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] -pub enum Colour { - Red, - Blue, - Green, -} - -#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] -pub enum Value { - Stat { construct: Uuid, stat: Stat, mult: usize }, - Fixed { value: usize }, - Cooldowns { construct: Uuid, mult: usize }, - ColourSkills { construct: Uuid, colour: Colour, mult: usize }, - DamageTaken { construct: Uuid, colour: Colour, mult: usize }, - // Skills { construct: Uuid, colour: Colour }, -} - -#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] -pub enum Action { - Hit { construct: Uuid }, - Cast { construct: Uuid }, - Healing { construct: Uuid, values: Vec, colour: Colour }, - Damage { construct: Uuid, values: Vec, colour: Colour }, - Effect { construct: Uuid, effect: ConstructEffect }, - IncreaseCooldowns { construct: Uuid, turns: usize }, - // Recharge { skill: Skill, red: usize, blue: usize }, -} - -#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] -pub struct Event { - pub cast: Cast, - pub focus: Vec, - pub variant: EventVariant, - pub delay: i64, -} - -impl Event { - pub fn new(cast: Cast, variant: EventVariant) -> Event { - let focus = match variant { - EventVariant::HitAoe { construct: _ } => vec![cast.source, cast.target], // fixme - _ => vec![cast.source, cast.target], - }; - - let delay = variant.delay(); - Event { - cast, - delay, - focus, - variant, - } - } -} - -pub type Disable = Vec; -pub type Direction = (i8, i8); - -#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] -pub enum EventVariant { - Cast { construct: Uuid, player: Uuid, direction: Direction }, - Hit { construct: Uuid, player: Uuid, direction: Direction }, - HitAoe { construct: Uuid }, - - Damage { construct: Uuid, amount: usize, mitigation: usize, colour: Colour, display: EventConstruct }, - Effect { construct: Uuid, effect: Effect, duration: u8, display: EventConstruct }, - Removal { construct: Uuid, effect: Option, display: EventConstruct }, - - Healing { construct: Uuid, amount: usize, overhealing: usize }, - Recharge { construct: Uuid, red: usize, blue: usize }, - Inversion { construct: Uuid }, - Reflection { construct: Uuid }, - Ko { construct: Uuid }, - - CooldownIncrease { construct: Uuid, turns: usize }, - CooldownDecrease { construct: Uuid, turns: usize }, - Forfeit (), -} - -impl EventVariant { - fn delay(&self) -> i64 { - // let source_duration = 1000; // Time for SOURCE ONLY - let target_duration = 1500; // Time for target animation - let target_delay = 500; // Add delay if theres source animation - let combat_text_delay = 1300; // Time for all post skill - let combat_text_overlap = 600; // overlap between animation and combat text - - match self { - EventVariant::Cast { construct: _, direction: _, player: _ } => target_delay, - EventVariant::Hit { construct: _, direction: _, player: _ } | - EventVariant::HitAoe { construct: _ } => target_duration - combat_text_overlap, - _ => combat_text_delay, - } - } -} - -// used to show the progress of a construct -// while the resolutions are animating -#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] -pub struct EventConstruct { - pub id: Uuid, - pub red: usize, - pub green: usize, - pub blue: usize, -} - -impl EventConstruct { - pub fn new(construct: &Construct) -> EventConstruct { - EventConstruct { - id: construct.id, - red: construct.red_life(), - green: construct.green_life(), - blue: construct.blue_life(), - } - } -} - -#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] -pub enum EventStages { - #[serde(rename = "START_SKILL END_SKILL POST_SKILL")] - AllStages, // Anim Anim Anim - #[serde(rename = "START_SKILL END_SKILL")] - StartEnd, // Anim Anim Skip - #[serde(rename = "START_SKILL POST_SKILL")] - StartPost, // Anim Skip Anim - #[serde(rename = "START_SKILL")] - StartOnly, // Anim Skip Skip - #[serde(rename = "END_SKILL POST_SKILL")] - EndPost, // Skip Anim Anim - #[serde(rename = "END_SKILL")] - EndOnly, // Skip Anim Skip - #[serde(rename = "POST_SKILL")] - PostOnly, // Skip Skip Anim -} - -impl EventStages { - fn delay(self) -> i64 { - let source_duration = 1000; // Time for SOURCE ONLY - let target_delay = 500; // Used for Source + Target - let target_duration = 1500; // Time for TARGET ONLY - let post_skill = 1000; // Time for all POST - let source_and_target_total = target_delay + target_duration; // SOURCE + TARGET time - - match self { - EventStages::AllStages => source_and_target_total + post_skill, // Anim Anim Anim - EventStages::StartEnd => source_and_target_total, // Anim Anim Skip - EventStages::StartPost => source_duration + post_skill, // Anim Skip Anim - EventStages::StartOnly => source_duration, // Anim Skip Skip - EventStages::EndPost => target_duration + post_skill, // Skip Anim Anim - EventStages::EndOnly => target_duration, // Skip Anim Skip - EventStages::PostOnly => post_skill, // Skip Skip Anim - } - } -} - #[derive(Debug,Clone,Serialize,Deserialize)] pub struct Game { pub id: Uuid, @@ -185,7 +24,7 @@ pub struct Game { pub players: Vec, pub phase: Phase, pub stack: Vec, - pub events: Vec>, + pub resolutions: Vec>, pub instance: Option, pub time_control: TimeControl, pub phase_start: DateTime, @@ -201,7 +40,7 @@ impl Game { players: vec![], phase: Phase::Start, stack: vec![], - events: vec![], + resolutions: vec![], instance: None, time_control: TimeControl::Standard, phase_end: None, @@ -320,7 +159,7 @@ impl Game { } fn skill_phase_start(mut self, resolution_animation_ms: i64) -> Game { - self.events.push(vec![]); + self.resolutions.push(vec![]); self.phase_start = Utc::now() .checked_add_signed(Duration::milliseconds(resolution_animation_ms)) @@ -635,10 +474,10 @@ impl Game { self.resolve(cast); } - // r_animation_ms = events.iter().fold(r_animation_ms, |acc, r| acc + r.clone().get_delay()); + // r_animation_ms = Resolutions.iter().fold(r_animation_ms, |acc, r| acc + r.clone().get_delay()); - // if theres no resolution events, the skill didn't trigger (disable etc) - // if events.len() > 0 && cast.used_cooldown() { + // if theres no resolution Resolutions, the skill didn't trigger (disable etc) + // if Resolutions.len() > 0 && cast.used_cooldown() { // casters.push(cast); // } @@ -659,39 +498,39 @@ impl Game { } pub fn resolve(&mut self, cast: Cast) -> &mut Game { - let mut events_group = vec![]; - let skill = cast.skill; // calculate values first? - // for result damage value need to pass &events and .find() + // for result damage value need to pass &Resolutions and .find() - for action in cast.actions() { - let mut events = match action { - Action::Cast { construct } => self.cast(cast), - Action::Hit { construct } => self.hit(construct, skill), - Action::Damage { construct, values, colour } => self.damage(construct, values, colour), - Action::Healing { construct, values, colour } => unimplemented!(), - Action::Effect { construct, effect } => self.effect(construct, effect), - Action::IncreaseCooldowns { construct, turns } => self.increase_cooldowns(construct, turns), - }; + let mut resolutions = cast.actions().into_iter() + .flat_map(|action| { + match action { + Action::Cast { construct } => self.cast(cast), + Action::Hit { construct } => self.hit(cast), + Action::Damage { construct, values, colour } => self.damage(cast, construct, values, colour), + Action::Healing { construct, values, colour } => unimplemented!(), + Action::Effect { construct, effect } => self.effect(construct, effect), + Action::IncreaseCooldowns { construct, turns } => self.increase_cooldowns(construct, turns), + } + }) + .map(|event| Resolution::new(cast, event)) + .collect::>(); - events_group.append(&mut events); - } + self.resolutions.last_mut().unwrap().append(&mut resolutions); - self.events.last_mut().unwrap().append(&mut events_group); self } fn cast(&mut self, cast: Cast) -> Vec { - vec![Event::new(cast, EventVariant::Cast { construct: cast.source, player: cast.player, direction: self.direction(cast) })] + vec![Event::Cast { construct: cast.source, player: cast.player, direction: self.direction(cast) }] } - fn hit(&mut self, construct: Uuid, skill: Skill) -> Vec { - vec![Event::new(EventVariant::Hit { skill: skill }, construct)] + fn hit(&mut self, cast: Cast) -> Vec { + vec![Event::Hit { construct: cast.target, player: cast.player, direction: self.direction(cast) }] } - fn damage(&mut self, construct: Uuid, values: Vec, colour: Colour) -> Vec { + fn damage(&mut self, cast: Cast, construct: Uuid, values: Vec, colour: Colour) -> Vec { match colour { _ => self.construct_by_id(construct).unwrap().deal_red_damage(128) // fixme unwrap } @@ -730,7 +569,7 @@ impl Game { (x, y) } - fn progress_durations(&mut self, events: &Vec) -> &mut Game { + fn progress_durations(&mut self, Resolutions: &Vec) -> &mut Game { for mut construct in self.all_constructs() { // info!("progressing durations for {:}", construct.name); @@ -738,7 +577,7 @@ impl Game { continue; } - match events.iter().find(|s| s.source == construct.id) { + match Resolutions.iter().find(|s| s.source == construct.id) { Some(skill) => { construct.skill_set_cd(skill.skill); }, None => { construct.reduce_cooldowns(); }, }; @@ -751,61 +590,61 @@ impl Game { self } - // fn log_resolution(&mut self, speed: usize, resolution: &Event) -> &mut Game { - // let Event { source, target, event, stages: _ } = resolution; - // match event { - // Event::Ko { skill: _ }=> + // fn log_resolution(&mut self, speed: usize, resolution: &Resolution) -> &mut Game { + // let Resolution { source, target, Resolution, stages: _ } = resolution; + // match Resolution { + // Resolution::Ko { skill: _ }=> // self.log.push(format!("{:} KO!", target.name)), - // Event::Disable { skill, disable } => + // Resolution::Disable { skill, disable } => // self.log.push(format!("{:} {:?} {:} disabled {:?}", // source.name, skill, target.name, disable)), - // Event::Immunity { skill, immunity } => + // Resolution::Immunity { skill, immunity } => // self.log.push(format!("[{:}] {:} {:?} {:} immune {:?}", // speed, source.name, skill, target.name, immunity)), - // Event::TargetKo { skill } => + // Resolution::TargetKo { skill } => // self.log.push(format!("[{:}] {:} {:?} {:} - target is KO", // speed, source.name, skill, target.name)), - // Event::Damage { skill, amount, mitigation, colour: _ } => + // Resolution::Damage { skill, amount, mitigation, colour: _ } => // self.log.push(format!("[{:}] {:} {:?} {:} {:} ({:} mitigated)", // speed, source.name, skill, target.name, amount, mitigation)), - // Event::Healing { skill, amount, overhealing } => + // Resolution::Healing { skill, amount, overhealing } => // self.log.push(format!("[{:}] {:} {:?} {:} {:} healing ({:}OH)", // speed, source.name, skill, target.name, amount, overhealing)), - // Event::Inversion { skill } => + // Resolution::Inversion { skill } => // self.log.push(format!("[{:}] {:} {:?} {:} INVERTED", // speed, source.name, skill, target.name)), - // Event::Reflection { skill } => + // Resolution::Reflection { skill } => // self.log.push(format!("[{:}] {:} {:?} {:} REFLECTED", // speed, source.name, skill, target.name)), - // Event::Effect { skill, effect, duration, construct_effects: _ } => + // Resolution::Effect { skill, effect, duration, construct_effects: _ } => // self.log.push(format!("[{:}] {:} {:?} {:} {:?} {:}T", // speed, source.name, skill, target.name, effect, duration)), - // Event::Skill { skill } => + // Resolution::Skill { skill } => // self.log.push(format!("[{:}] {:} {:?} {:}", // speed, source.name, skill, target.name)), - // Event::Removal { effect, construct_effects: _ } => + // Resolution::Removal { effect, construct_effects: _ } => // self.log.push(format!("[{:}] {:?} removed {:} {:?}", // speed, source.name, target.name, effect)), - // Event::Recharge { skill, red, blue } => + // Resolution::Recharge { skill, red, blue } => // self.log.push(format!("[{:}] {:} {:?} {:} {:}R {:}B", // speed, source.name, skill, target.name, red, blue)), - // Event::Evasion { skill, evasion_rating } => + // Resolution::Evasion { skill, evasion_rating } => // self.log.push(format!("[{:}] {:} {:?} {:} evaded ({:}%)", // speed, source.name, skill, target.name, evasion_rating)), - // Event::Incomplete => panic!("incomplete resolution {:?}", resolution), + // Resolution::Incomplete => panic!("incomplete resolution {:?}", resolution), // } // self @@ -864,7 +703,7 @@ impl Game { // player.forfeit(); // info!("upkeep: {:} forfeited", player.name); // //todo - // // self.events.push(forfeit) + // // self.Resolutions.push(forfeit) // // self.log.push(format!("{:} forfeited.", player.name)); // } } @@ -875,6 +714,171 @@ impl Game { } } + +#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] +pub enum Phase { + Start, + Skill, + Resolve, + Finished, +} + +#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] +pub enum Colour { + Red, + Blue, + Green, +} + +#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] +pub enum Value { + Stat { construct: Uuid, stat: Stat, mult: usize }, + Fixed { value: usize }, + Cooldowns { construct: Uuid, mult: usize }, + ColourSkills { construct: Uuid, colour: Colour, mult: usize }, + DamageTaken { construct: Uuid, colour: Colour, mult: usize }, + // Skills { construct: Uuid, colour: Colour }, +} + +#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] +pub enum Action { + Hit { construct: Uuid }, + Cast { construct: Uuid }, + Healing { construct: Uuid, values: Vec, colour: Colour }, + Damage { construct: Uuid, values: Vec, colour: Colour }, + Effect { construct: Uuid, effect: ConstructEffect }, + IncreaseCooldowns { construct: Uuid, turns: usize }, + // Recharge { skill: Skill, red: usize, blue: usize }, +} + +#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] +pub struct Resolution { + pub cast: Cast, + pub focus: Vec, + pub event: Event, + pub delay: i64, +} + +impl Resolution { + pub fn new(cast: Cast, event: Event) -> Resolution { + + // maybe map events construct_ids + let focus = match event { + Event::HitAoe { construct: _ } => vec![cast.source, cast.target], // fixme + _ => vec![cast.source, cast.target], + }; + + let delay = event.delay(); + + Resolution { + cast, + delay, + focus, + event, + } + } +} + +pub type Disable = Vec; +pub type Direction = (i8, i8); + +#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] +pub enum Event { + Cast { construct: Uuid, player: Uuid, direction: Direction }, + Hit { construct: Uuid, player: Uuid, direction: Direction }, + HitAoe { construct: Uuid }, + + Damage { construct: Uuid, amount: usize, mitigation: usize, colour: Colour, display: EventConstruct }, + Effect { construct: Uuid, effect: Effect, duration: u8, display: EventConstruct }, + Removal { construct: Uuid, effect: Option, display: EventConstruct }, + + Healing { construct: Uuid, amount: usize, overhealing: usize }, + Recharge { construct: Uuid, red: usize, blue: usize }, + Inversion { construct: Uuid }, + Reflection { construct: Uuid }, + Ko { construct: Uuid }, + + CooldownIncrease { construct: Uuid, turns: usize }, + CooldownDecrease { construct: Uuid, turns: usize }, + Forfeit (), +} + +impl Event { + fn delay(&self) -> i64 { + // let source_duration = 1000; // Time for SOURCE ONLY + let target_duration = 1500; // Time for target animation + let target_delay = 500; // Add delay if theres source animation + let combat_text_delay = 1300; // Time for all post skill + let combat_text_overlap = 600; // overlap between animation and combat text + + match self { + Event::Cast { construct: _, direction: _, player: _ } => target_delay, + Event::Hit { construct: _, direction: _, player: _ } | + Event::HitAoe { construct: _ } => target_duration - combat_text_overlap, + _ => combat_text_delay, + } + } +} + +// used to show the progress of a construct +// while the resolutions are animating +#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] +pub struct EventConstruct { + pub id: Uuid, + pub red: usize, + pub green: usize, + pub blue: usize, +} + +impl EventConstruct { + pub fn new(construct: &Construct) -> EventConstruct { + EventConstruct { + id: construct.id, + red: construct.red_life(), + green: construct.green_life(), + blue: construct.blue_life(), + } + } +} + +#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] +pub enum ResolutionStages { + #[serde(rename = "START_SKILL END_SKILL POST_SKILL")] + AllStages, // Anim Anim Anim + #[serde(rename = "START_SKILL END_SKILL")] + StartEnd, // Anim Anim Skip + #[serde(rename = "START_SKILL POST_SKILL")] + StartPost, // Anim Skip Anim + #[serde(rename = "START_SKILL")] + StartOnly, // Anim Skip Skip + #[serde(rename = "END_SKILL POST_SKILL")] + EndPost, // Skip Anim Anim + #[serde(rename = "END_SKILL")] + EndOnly, // Skip Anim Skip + #[serde(rename = "POST_SKILL")] + PostOnly, // Skip Skip Anim +} + +impl ResolutionStages { + fn delay(self) -> i64 { + let source_duration = 1000; // Time for SOURCE ONLY + let target_delay = 500; // Used for Source + Target + let target_duration = 1500; // Time for TARGET ONLY + let post_skill = 1000; // Time for all POST + let source_and_target_total = target_delay + target_duration; // SOURCE + TARGET time + + match self { + ResolutionStages::AllStages => source_and_target_total + post_skill, // Anim Anim Anim + ResolutionStages::StartEnd => source_and_target_total, // Anim Anim Skip + ResolutionStages::StartPost => source_duration + post_skill, // Anim Skip Anim + ResolutionStages::StartOnly => source_duration, // Anim Skip Skip + ResolutionStages::EndPost => target_duration + post_skill, // Skip Anim Anim + ResolutionStages::EndOnly => target_duration, // Skip Anim Skip + ResolutionStages::PostOnly => post_skill, // Skip Skip Anim + } + } +} + #[cfg(test)] mod tests { use game::*; @@ -1249,15 +1253,15 @@ mod tests { // // game = game.resolve_phase_start(); // // assert!(game.construct_by_id(x_construct.id).unwrap().affected(Effect::Link)); - // // let Event { source: _, target: _, event, stages: _ } = game.events.last.unwrap().pop().unwrap(); - // // match event { - // // Event::Effect { effect, skill: _, duration: _, construct_effects: _ } => assert_eq!(effect, Effect::Link), + // // let Resolution { source: _, target: _, Resolution, stages: _ } = game.Resolutions.last.unwrap().pop().unwrap(); + // // match Resolution { + // // Resolution::Effect { effect, skill: _, duration: _, construct_effects: _ } => assert_eq!(effect, Effect::Link), // // _ => panic!("not siphon"), // // }; - // // let Event { source: _, target: _, event, stages: _ } = game.events.last.unwrap().pop().unwrap(); - // // match event { - // // Event::Recharge { red: _, blue: _, skill: _ } => (), + // // let Resolution { source: _, target: _, Resolution, stages: _ } = game.Resolutions.last.unwrap().pop().unwrap(); + // // match Resolution { + // // Resolution::Recharge { red: _, blue: _, skill: _ } => (), // // _ => panic!("link result was not recharge"), // // } @@ -1267,10 +1271,10 @@ mod tests { // // game.player_ready(y_player.id).unwrap(); // // game = game.resolve_phase_start(); - // // let Event { source: _, target, event, stages: _ } = game.events.last.unwrap().pop().unwrap(); + // // let Resolution { source: _, target, Resolution, stages: _ } = game.Resolutions.last.unwrap().pop().unwrap(); // // assert_eq!(target.id, y_construct.id); - // // match event { - // // Event::Damage { amount, skill: _, mitigation: _, colour: _} => + // // match Resolution { + // // Resolution::Damage { amount, skill: _, mitigation: _, colour: _} => // // assert_eq!(amount, x_construct.red_power().pct(Skill::Attack.multiplier()) >> 1), // // _ => panic!("not damage link"), // // }; @@ -1337,21 +1341,21 @@ mod tests { // assert!(game.skill_phase_finished()); // game = game.resolve_phase_start(); - // let ruins = game.events + // let ruins = game.Resolutions // .last().unwrap() // .into_iter() // .filter(|r| { - // let Event { source, target: _, event, stages: _ } = r; + // let Resolution { source, target: _, Resolution, stages: _ } = r; // match source.id == x_construct.id { - // true => match event { - // Event::Effect { effect, duration, skill: _, construct_effects: _ } => { + // true => match Resolution { + // Resolution::Effect { effect, duration, skill: _, construct_effects: _ } => { // assert!(*effect == Effect::Stun); // assert!(*duration == 1); // true // }, - // Event::AoeSkill { skill: _ } => false, - // Event::Damage { amount: _, mitigation: _, colour: _, skill: _ } => false, - // _ => panic!("ruin result not effect {:?}", event), + // Resolution::AoeSkill { skill: _ } => false, + // Resolution::Damage { amount: _, mitigation: _, colour: _, skill: _ } => false, + // _ => panic!("ruin result not effect {:?}", Resolution), // } // false => false, // } @@ -1389,9 +1393,9 @@ mod tests { // game = game.resolve_phase_start(); - // assert!(game.events.len() == 4); - // while let Some(r) = game.events.last().unwrap().pop() { - // let Event { source , target, event: _, stages: _ } = r; + // assert!(game.Resolutions.len() == 4); + // while let Some(r) = game.Resolutions.last().unwrap().pop() { + // let Resolution { source , target, Resolution: _, stages: _ } = r; // if [i_construct.id, j_construct.id].contains(&source.id) { // assert!(target.id == x_construct.id); // } @@ -1480,13 +1484,13 @@ mod tests { // game = game.resolve_phase_start(); // assert!(game.construct_by_id(y_construct.id).unwrap().affected(Effect::Decay)); - // let Event { source: _, target: _, event, stages: _ } = game.events.last().unwrap().pop().unwrap(); - // match event { - // Event::Damage { amount: _, skill, mitigation: _, colour: _ } => assert_eq!(skill, Skill::DecayTick), + // let Resolution { source: _, target: _, Resolution, stages: _ } = game.Resolutions.last().unwrap().pop().unwrap(); + // match Resolution { + // Resolution::Damage { amount: _, skill, mitigation: _, colour: _ } => assert_eq!(skill, Skill::DecayTick), // _ => panic!("not decay"), // }; - // game.events.clear(); + // game.Resolutions.clear(); // // remove // game.add_skill(y_player.id, y_construct.id, y_construct.id, Skill::Purify).unwrap(); @@ -1494,10 +1498,10 @@ mod tests { // game.player_ready(y_player.id).unwrap(); // game = game.resolve_phase_start(); - // while let Some(Event { source: _, target: _, event, stages: _ }) = game.events.last().unwrap().pop() { - // match event { - // Event::Damage { amount: _, skill: _, mitigation: _, colour: _ } => - // panic!("{:?} damage event", event), + // while let Some(Resolution { source: _, target: _, Resolution, stages: _ }) = game.Resolutions.last().unwrap().pop() { + // match Resolution { + // Resolution::Damage { amount: _, skill: _, mitigation: _, colour: _ } => + // panic!("{:?} damage Resolution", Resolution), // _ => (), // } // }; @@ -1507,17 +1511,17 @@ mod tests { // game.player_ready(y_player.id).unwrap(); // game = game.resolve_phase_start(); - // game.events.clear(); + // game.Resolutions.clear(); // game.add_skill(y_player.id, y_construct.id, y_construct.id, Skill::Purify).unwrap(); // game.player_ready(x_player.id).unwrap(); // game.player_ready(y_player.id).unwrap(); // game = game.resolve_phase_start(); - // while let Some(Event { source: _, target: _, event, stages: _ }) = game.events.last().unwrap().pop() { - // match event { - // Event::Damage { amount: _, skill: _, mitigation: _, colour: _ } => - // panic!("{:#?} {:#?} damage event", game.events, event), + // while let Some(Resolution { source: _, target: _, Resolution, stages: _ }) = game.Resolutions.last().unwrap().pop() { + // match Resolution { + // Resolution::Damage { amount: _, skill: _, mitigation: _, colour: _ } => + // panic!("{:#?} {:#?} damage Resolution", game.Resolutions, Resolution), // _ => (), // } // }; @@ -1554,6 +1558,6 @@ mod tests { game.resolve(Cast::new(source, player_id, target, Skill::Bash)); - println!("{:?}", game.events); + println!("{:?}", game.resolutions); } } diff --git a/core/src/skill.rs b/core/src/skill.rs index fd538ad6..3d198768 100644 --- a/core/src/skill.rs +++ b/core/src/skill.rs @@ -57,10 +57,10 @@ impl Cast { let mut actions = vec![]; if self.skill.cast_animation() { - actions.push(Action::Cast { cast: *self }); + actions.push(Action::Cast { construct: self.source }); } - actions.push(Action::Hit { cast: *self }); + actions.push(Action::Hit { construct: self.target }); let mut rest = match self.skill { Skill::Attack => vec![ @@ -89,21 +89,18 @@ impl Cast { Skill::Amplify => vec![ Action::Effect { - cast: *self, construct: self.target, effect: ConstructEffect { effect: Effect::Amplify, duration: 2, meta: Some(EffectMeta::Multiplier(150)), tick: None }, }, ], Skill::AmplifyPlus => vec![ Action::Effect { - cast: *self, construct: self.target, effect: ConstructEffect { effect: Effect::Amplify, duration: 3, meta: Some(EffectMeta::Multiplier(175)), tick: None }, }, ], Skill::AmplifyPlusPlus => vec![ Action::Effect { - cast: *self, construct: self.target, effect: ConstructEffect { effect: Effect::Amplify, duration: 4, meta: Some(EffectMeta::Multiplier(200)), tick: None }, }, @@ -122,7 +119,6 @@ impl Cast { ], Skill::AbsorbPlus => vec![ Action::Effect { - cast: *self, construct: self.target, effect: ConstructEffect { effect: Effect::Absorb, duration: 1, meta: Some(EffectMeta::Skill(Skill::AbsorptionPlus)), tick: None }, }, @@ -134,7 +130,6 @@ impl Cast { ], Skill::AbsorbPlusPlus => vec![ Action::Effect { - cast: *self, construct: self.target, effect: ConstructEffect { effect: Effect::Absorb, duration: 1, meta: Some(EffectMeta::Skill(Skill::AbsorptionPlusPlus)), tick: None }, }, @@ -159,7 +154,6 @@ impl Cast { values: vec![Value::Stat { construct: self.target, stat: Stat::BlueLife, mult: self.skill.multiplier() }], }, Action::Effect { - cast: *self, construct: self.target, effect: ConstructEffect { effect: Effect::Banish, duration: 2, meta: None, tick: None } } @@ -169,7 +163,6 @@ impl Cast { Skill::BashPlus | Skill::BashPlusPlus => vec![ Action::Damage { - cast: *self, construct: self.target, colour: Colour::Red, values: vec![ @@ -178,12 +171,10 @@ impl Cast { ], }, Action::Effect { - cast: *self, construct: self.target, effect: ConstructEffect {effect: Effect::Stun, duration: 2, meta: None, tick: None } }, Action::IncreaseCooldowns { - cast: *self, construct: self.target, turns: 1, }, @@ -193,7 +184,6 @@ impl Cast { Skill::BlastPlus | Skill::BlastPlusPlus => vec![ Action::Damage { - cast: *self, construct: self.target, colour: Colour::Blue, values: vec![Value::Stat { construct: self.source, stat: Stat::BluePower, mult: self.skill.multiplier() }], @@ -274,7 +264,6 @@ impl Cast { Skill::CounterAttackPlus | Skill::CounterAttackPlusPlus => vec![ Action::Damage { - cast: *self, construct: self.target, colour: Colour::Red, values: vec![Value::Stat { construct: self.source, stat: Stat::RedPower, mult: self.skill.multiplier() }], @@ -1583,14 +1572,17 @@ mod tests { let actions = cast.actions(); match actions[0] { - Action::Hit { cast } => { - assert_eq!(cast.skill, Skill::Attack); - }, + Action::Cast { construct: _ } => (), _ => panic!("{:?}", actions), }; match actions[1] { - Action::Damage { cast: _, construct: _, values: _, colour } => { + Action::Hit { construct: _ } => (), + _ => panic!("{:?}", actions), + }; + + match actions[2] { + Action::Damage { construct: _, values: _, colour } => { assert_eq!(colour, Colour::Red); }, _ => panic!("{:?}", actions),