values
This commit is contained in:
parent
255131730c
commit
44c541edf8
@ -112,20 +112,22 @@ impl ConstructEffect {
|
||||
|
||||
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
||||
pub enum Stat {
|
||||
Str,
|
||||
Agi,
|
||||
Int,
|
||||
GreenLife,
|
||||
Speed,
|
||||
RedPower,
|
||||
BluePower,
|
||||
GreenPower,
|
||||
RedDamageTaken,
|
||||
BlueDamageTaken,
|
||||
GreenDamageTaken,
|
||||
RedLife,
|
||||
RedPower,
|
||||
RedDamageTaken,
|
||||
|
||||
GreenLife,
|
||||
GreenPower,
|
||||
GreenDamageTaken,
|
||||
|
||||
BlueLife,
|
||||
Evasion,
|
||||
BluePower,
|
||||
BlueDamageTaken,
|
||||
|
||||
Speed,
|
||||
|
||||
Cooldowns,
|
||||
Skills(Colour),
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
||||
@ -474,6 +476,29 @@ impl Construct {
|
||||
}
|
||||
|
||||
// Stats
|
||||
|
||||
// fixme put everything through this fn
|
||||
pub fn stat(&self, stat: Stat) -> usize {
|
||||
match stat {
|
||||
Stat::RedLife => self.red_life(),
|
||||
Stat::RedPower => self.red_power(),
|
||||
Stat::RedDamageTaken => unimplemented!(),
|
||||
|
||||
Stat::GreenLife => self.green_life(),
|
||||
Stat::GreenPower => self.green_power(),
|
||||
Stat::GreenDamageTaken => unimplemented!(),
|
||||
|
||||
Stat::BlueLife => self.blue_life(),
|
||||
Stat::BluePower => self.blue_power(),
|
||||
Stat::BlueDamageTaken => unimplemented!(),
|
||||
|
||||
Stat::Speed => self.speed(),
|
||||
|
||||
Stat::Cooldowns => unimplemented!(),
|
||||
Stat::Skills(Colour) => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn red_power(&self) -> usize {
|
||||
let red_power_mods = self.effects.iter()
|
||||
.filter(|e| e.effect.modifications().contains(&Stat::RedPower))
|
||||
|
||||
259
core/src/game.rs
259
core/src/game.rs
@ -12,6 +12,7 @@ use failure::err_msg;
|
||||
use construct::{Construct, ConstructEffect, Stat};
|
||||
use skill::{Skill, Cast};
|
||||
use effect::{Effect};
|
||||
use util::{IntPct};
|
||||
|
||||
use player::{Player};
|
||||
use instance::{TimeControl};
|
||||
@ -410,7 +411,63 @@ impl Game {
|
||||
self
|
||||
}
|
||||
|
||||
fn finalise_cast(&self, cast: Cast) -> Vec<Cast> {
|
||||
fn resolve_stack(mut self) -> Game {
|
||||
if self.phase != Phase::Resolve {
|
||||
panic!("game not in Resolve phase");
|
||||
}
|
||||
|
||||
// find their statuses with ticks
|
||||
let mut ticks = self.all_constructs()
|
||||
.iter()
|
||||
.flat_map(
|
||||
|c| c.effects
|
||||
.iter()
|
||||
.cloned()
|
||||
.filter_map(|e| e.tick))
|
||||
.collect::<Vec<Cast>>();
|
||||
|
||||
// add them to the stack
|
||||
self.stack.append(&mut ticks);
|
||||
|
||||
self.stack_sort_speed();
|
||||
|
||||
// temp vec of this round's resolving skills
|
||||
// because need to check cooldown use before pushing them into the complete list
|
||||
let mut casters = vec![];
|
||||
let mut r_animation_ms = 0;
|
||||
while let Some(cast) = self.stack.pop() {
|
||||
// info!("{:} casts ", cast);
|
||||
|
||||
let casts = self.pre_resolve(cast);
|
||||
|
||||
for cast in casts {
|
||||
self.resolve(cast);
|
||||
}
|
||||
|
||||
// r_animation_ms = Resolutions.iter().fold(r_animation_ms, |acc, r| acc + r.clone().get_delay());
|
||||
|
||||
// if theres no resolution Resolutions, the skill didn't trigger (disable etc)
|
||||
// if Resolutions.len() > 0 && cast.used_cooldown() {
|
||||
// casters.push(cast);
|
||||
// }
|
||||
|
||||
// sort the stack again in case speeds have changed
|
||||
self.stack_sort_speed();
|
||||
};
|
||||
|
||||
// info!("{:#?}", self.casts);
|
||||
|
||||
// handle cooldowns and statuses
|
||||
self.progress_durations(&casters);
|
||||
|
||||
if self.finished() {
|
||||
return self.finish()
|
||||
}
|
||||
|
||||
self.skill_phase_start(r_animation_ms)
|
||||
}
|
||||
|
||||
fn pre_resolve(&self, cast: Cast) -> Vec<Cast> {
|
||||
let target_player = self.players.iter()
|
||||
.find(|t| t.constructs.iter().any(|c| c.id == cast.target))
|
||||
.unwrap();
|
||||
@ -440,88 +497,144 @@ impl Game {
|
||||
return targets;
|
||||
}
|
||||
|
||||
fn calculate_amount(&mut self, values: &Vec<Value>, resolutions: &Vec<Resolution>) -> usize {
|
||||
values.iter()
|
||||
.fold(0, |total, value| {
|
||||
total + match value {
|
||||
Value::Stat { construct, stat, mult } =>
|
||||
self.construct_by_id(*construct).unwrap().stat(*stat).pct(*mult),
|
||||
|
||||
fn resolve_stack(mut self) -> Game {
|
||||
if self.phase != Phase::Resolve {
|
||||
panic!("game not in Resolve phase");
|
||||
}
|
||||
Value::Fixed { value } => *value,
|
||||
|
||||
// find their statuses with ticks
|
||||
let mut ticks = self.all_constructs()
|
||||
.iter()
|
||||
.flat_map(
|
||||
|c| c.effects
|
||||
.iter()
|
||||
.cloned()
|
||||
.filter_map(|e| e.tick))
|
||||
.collect::<Vec<Cast>>();
|
||||
Value::Cooldowns { construct, mult } => unimplemented!(),
|
||||
|
||||
// add them to the stack
|
||||
self.stack.append(&mut ticks);
|
||||
Value::ColourSkills { construct, colour, mult } => unimplemented!(),
|
||||
|
||||
self.stack_sort_speed();
|
||||
|
||||
// temp vec of this round's resolving skills
|
||||
// because need to check cooldown use before pushing them into the complete list
|
||||
let mut casters = vec![];
|
||||
let mut r_animation_ms = 0;
|
||||
while let Some(cast) = self.stack.pop() {
|
||||
// info!("{:} casts ", cast);
|
||||
|
||||
let casts = self.finalise_cast(cast);
|
||||
|
||||
for cast in casts {
|
||||
self.resolve(cast);
|
||||
}
|
||||
|
||||
// r_animation_ms = Resolutions.iter().fold(r_animation_ms, |acc, r| acc + r.clone().get_delay());
|
||||
|
||||
// if theres no resolution Resolutions, the skill didn't trigger (disable etc)
|
||||
// if Resolutions.len() > 0 && cast.used_cooldown() {
|
||||
// casters.push(cast);
|
||||
// }
|
||||
|
||||
// sort the stack again in case speeds have changed
|
||||
self.stack_sort_speed();
|
||||
};
|
||||
|
||||
// info!("{:#?}", self.casts);
|
||||
|
||||
// handle cooldowns and statuses
|
||||
self.progress_durations(&casters);
|
||||
|
||||
if self.finished() {
|
||||
return self.finish()
|
||||
}
|
||||
|
||||
self.skill_phase_start(r_animation_ms)
|
||||
Value::DamageTaken { construct, colour, mult } => unimplemented!(),
|
||||
// Skills { construct: Uuid, colour: Colour },
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn resolve(&mut self, cast: Cast) -> &mut Game {
|
||||
fn resolve(&mut self, cast: Cast) -> &mut Game {
|
||||
let skill = cast.skill;
|
||||
|
||||
// calculate values first?
|
||||
// for result damage value need to pass &Resolutions and .find()
|
||||
|
||||
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::<Vec<Resolution>>();
|
||||
let mut resolved = vec![];
|
||||
|
||||
self.resolutions.last_mut().unwrap().append(&mut resolutions);
|
||||
for action in cast.actions() {
|
||||
let events = match action {
|
||||
Action::Cast { construct } => self.cast(cast),
|
||||
Action::Hit { construct } => self.hit(cast),
|
||||
|
||||
Action::Damage { construct, values, colour } => {
|
||||
let amount = self.calculate_amount(&values, &resolved);
|
||||
self.damage(cast, construct, amount, colour)
|
||||
},
|
||||
|
||||
Action::Heal { construct, values, colour } => {
|
||||
let amount = self.calculate_amount(&values, &resolved);
|
||||
self.heal(cast, construct, amount, colour)
|
||||
},
|
||||
|
||||
Action::Effect { construct, effect } => self.effect(construct, effect),
|
||||
Action::IncreaseCooldowns { construct, turns } => self.increase_cooldowns(construct, turns),
|
||||
};
|
||||
|
||||
let mut resolutions = events.into_iter()
|
||||
.map(|event| Resolution::new(cast, event))
|
||||
.collect::<Vec<Resolution>>();
|
||||
|
||||
resolved.append(&mut resolutions);
|
||||
}
|
||||
|
||||
// fn slay(source: &mut Construct, target: &mut Construct, skill: Skill) {
|
||||
// let amount = source.red_power().pct(skill.multiplier()) + source.green_power().pct(skill.multiplier());
|
||||
// let slay_events = target.deal_red_damage(skill, amount);
|
||||
// for e in slay_events {
|
||||
// match e {
|
||||
// Event::Damage { amount, mitigation: _, colour: _, skill: _ } => {
|
||||
// game.event(Event::new(source, target).event(e));
|
||||
// let heal = source.deal_green_damage(skill, amount.pct(50));
|
||||
// for h in heal {
|
||||
// game.event(Event::new(source, source).event(h).stages(EventStages::PostOnly));
|
||||
// };
|
||||
// },
|
||||
// _ => game.event(Event::new(source, target).event(e)),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
self.resolutions.last_mut().unwrap().append(&mut resolved);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
fn post_resolve(&mut self, resolutions: &Vec<Resolution>) -> &mut Game {
|
||||
self
|
||||
// for Event { source: event_source, target: event_target, event, stages: _ } in resolutions.clone() {
|
||||
// let mut source = game.construct_by_id(event_source.id).unwrap().clone();
|
||||
// let mut target = game.construct_by_id(event_target.id).unwrap().clone();
|
||||
|
||||
// match event {
|
||||
// Event::Damage { amount, skill, mitigation, colour: c } => {
|
||||
// if target.affected(Effect::Electric) && !skill.is_tick() {
|
||||
// let ConstructEffect { effect: _, duration: _, meta, tick: _ } = target.effects.iter()
|
||||
// .find(|e| e.effect == Effect::Electric).unwrap().clone();
|
||||
// match meta {
|
||||
// Some(EffectMeta::Skill(s)) => {
|
||||
// // Gurad against reflect overflow
|
||||
// if !(source.affected(Effect::Reflect) && target.affected(Effect::Reflect)) {
|
||||
// // Check reflect don't bother if electrocute is procing on death
|
||||
// if source.affected(Effect::Reflect) && !target.is_ko() {
|
||||
// game.event(Event::new(&target, &source)
|
||||
// .event(Event::Reflection { skill: s }).stages(EventStages::EndPost));
|
||||
// electrocute(&mut source, &mut target, resolutions, s);
|
||||
// } else {
|
||||
// electrocute(&mut target, &mut source, resolutions, s);
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// _ => panic!("no electrify skill"),
|
||||
// };
|
||||
// }
|
||||
|
||||
// if target.affected(Effect::Absorb) && !target.is_ko() {
|
||||
// let ConstructEffect { effect: _, duration: _, meta, tick: _ } = target.effects.iter()
|
||||
// .find(|e| e.effect == Effect::Absorb).unwrap().clone();
|
||||
// match meta {
|
||||
// Some(EffectMeta::Skill(s)) => {
|
||||
// absorption(&mut source, &mut target, resolutions, skill, amount + mitigation, s);
|
||||
// },
|
||||
// _ => panic!("no absorb skill"),
|
||||
// };
|
||||
// }
|
||||
// if c == Colour::Red {
|
||||
// if target.affected(Effect::Counter) && !target.is_ko() {
|
||||
// let ConstructEffect { effect: _, duration: _, meta, tick: _ } = target.effects.iter()
|
||||
// .find(|e| e.effect == Effect::Counter).unwrap().clone();
|
||||
// match meta {
|
||||
// Some(EffectMeta::Skill(s)) => {
|
||||
// counter_attack(&mut target, &mut source, resolutions, s);
|
||||
// },
|
||||
// _ => panic!("no counter skill"),
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
|
||||
// if target.is_ko() && event_target.green == 0 {
|
||||
// // Make sure target ko is from this event
|
||||
// target.effects.clear();
|
||||
// game.event(Event::new(&source, &target).event(Event::Ko()).stages(EventStages::PostOnly));
|
||||
// }
|
||||
// },
|
||||
// _ => (),
|
||||
// };
|
||||
// }
|
||||
}
|
||||
|
||||
fn cast(&mut self, cast: Cast) -> Vec<Event> {
|
||||
vec![Event::Cast { construct: cast.source, player: cast.player, direction: self.direction(cast) }]
|
||||
}
|
||||
@ -530,9 +643,15 @@ impl Game {
|
||||
vec![Event::Hit { construct: cast.target, player: cast.player, direction: self.direction(cast) }]
|
||||
}
|
||||
|
||||
fn damage(&mut self, cast: Cast, construct: Uuid, values: Vec<Value>, colour: Colour) -> Vec<Event> {
|
||||
fn damage(&mut self, cast: Cast, construct: Uuid, amount: usize, colour: Colour) -> Vec<Event> {
|
||||
match colour {
|
||||
_ => self.construct_by_id(construct).unwrap().deal_red_damage(128) // fixme unwrap
|
||||
_ => self.construct_by_id(construct).unwrap().deal_red_damage(amount) // fixme unwrap
|
||||
}
|
||||
}
|
||||
|
||||
fn heal(&mut self, cast: Cast, construct: Uuid, value: usize, colour: Colour) -> Vec<Event> {
|
||||
match colour {
|
||||
_ => self.construct_by_id(construct).unwrap().deal_red_damage(value) // fixme unwrap
|
||||
}
|
||||
}
|
||||
|
||||
@ -744,7 +863,7 @@ pub enum Value {
|
||||
pub enum Action {
|
||||
Hit { construct: Uuid },
|
||||
Cast { construct: Uuid },
|
||||
Healing { construct: Uuid, values: Vec<Value>, colour: Colour },
|
||||
Heal { construct: Uuid, values: Vec<Value>, colour: Colour },
|
||||
Damage { construct: Uuid, values: Vec<Value>, colour: Colour },
|
||||
Effect { construct: Uuid, effect: ConstructEffect },
|
||||
IncreaseCooldowns { construct: Uuid, turns: usize },
|
||||
|
||||
@ -85,6 +85,12 @@ impl Cast {
|
||||
},
|
||||
],
|
||||
|
||||
Skill::Stun => vec![
|
||||
Action::Effect {
|
||||
construct: self.target,
|
||||
effect: ConstructEffect { effect: Effect::Stun, duration: 2, meta: None, tick: None },
|
||||
},
|
||||
],
|
||||
|
||||
|
||||
Skill::Amplify => vec![
|
||||
@ -111,7 +117,7 @@ impl Cast {
|
||||
construct: self.target,
|
||||
effect: ConstructEffect { effect: Effect::Absorb, duration: 1, meta: Some(EffectMeta::Skill(Skill::Absorption)), tick: None },
|
||||
},
|
||||
Action::Healing {
|
||||
Action::Heal {
|
||||
construct: self.target,
|
||||
values: vec![Value::Stat { construct: self.source, stat: Stat::BluePower, mult: self.skill.multiplier() }],
|
||||
colour: Colour::Blue,
|
||||
@ -122,7 +128,7 @@ impl Cast {
|
||||
construct: self.target,
|
||||
effect: ConstructEffect { effect: Effect::Absorb, duration: 1, meta: Some(EffectMeta::Skill(Skill::AbsorptionPlus)), tick: None },
|
||||
},
|
||||
Action::Healing {
|
||||
Action::Heal {
|
||||
construct: self.target,
|
||||
values: vec![Value::Stat { construct: self.source, stat: Stat::BluePower, mult: self.skill.multiplier() }],
|
||||
colour: Colour::Blue,
|
||||
@ -133,7 +139,7 @@ impl Cast {
|
||||
construct: self.target,
|
||||
effect: ConstructEffect { effect: Effect::Absorb, duration: 1, meta: Some(EffectMeta::Skill(Skill::AbsorptionPlusPlus)), tick: None },
|
||||
},
|
||||
Action::Healing {
|
||||
Action::Heal {
|
||||
construct: self.target,
|
||||
values: vec![Value::Stat { construct: self.source, stat: Stat::BluePower, mult: self.skill.multiplier() }],
|
||||
colour: Colour::Blue,
|
||||
@ -277,7 +283,7 @@ impl Cast {
|
||||
construct: self.target,
|
||||
effect: ConstructEffect {effect: Effect::Intercept, duration: 1, meta: None, tick: None},
|
||||
},
|
||||
Action::Healing {
|
||||
Action::Heal {
|
||||
construct: self.target,
|
||||
values: vec![Value::Stat { construct: self.source, stat: Stat::RedPower, mult: self.skill.multiplier() }],
|
||||
colour: Colour::Red,
|
||||
@ -307,38 +313,19 @@ impl Cast {
|
||||
colour: Colour::Red,
|
||||
values: vec![Value::Stat { construct: self.source, stat: Stat::RedPower, mult: self.skill.multiplier() }],
|
||||
},
|
||||
Action::Healing {
|
||||
Action::Heal {
|
||||
construct: self.target,
|
||||
colour: Colour::Green,
|
||||
values: vec![Value::DamageTaken { construct: self.target, colour: Colour::Red, mult: 50 }],
|
||||
},
|
||||
],
|
||||
|
||||
// fn slay(source: &mut Construct, target: &mut Construct, skill: Skill) {
|
||||
// let amount = source.red_power().pct(skill.multiplier()) + source.green_power().pct(skill.multiplier());
|
||||
// let slay_events = target.deal_red_damage(skill, amount);
|
||||
|
||||
// for e in slay_events {
|
||||
// match e {
|
||||
// Event::Damage { amount, mitigation: _, colour: _, skill: _ } => {
|
||||
// game.event(Event::new(source, target).event(e));
|
||||
// let heal = source.deal_green_damage(skill, amount.pct(50));
|
||||
// for h in heal {
|
||||
// game.event(Event::new(source, source).event(h).stages(EventStages::PostOnly));
|
||||
// };
|
||||
// },
|
||||
// _ => game.event(Event::new(source, target).event(e)),
|
||||
// }
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
Skill::Sleep => vec![
|
||||
Action::Effect {
|
||||
construct: self.target,
|
||||
effect: ConstructEffect {effect: Effect::Stun, duration: 2, meta: None, tick: None},
|
||||
},
|
||||
Action::Healing {
|
||||
Action::Heal {
|
||||
construct: self.target,
|
||||
values: vec![Value::Stat { construct: self.source, stat: Stat::GreenPower, mult: self.skill.multiplier() }],
|
||||
colour: Colour::Blue,
|
||||
@ -349,7 +336,7 @@ impl Cast {
|
||||
construct: self.target,
|
||||
effect: ConstructEffect {effect: Effect::Stun, duration: 2, meta: None, tick: None},
|
||||
},
|
||||
Action::Healing {
|
||||
Action::Heal {
|
||||
construct: self.target,
|
||||
values: vec![Value::Stat { construct: self.source, stat: Stat::GreenPower, mult: self.skill.multiplier() }],
|
||||
colour: Colour::Blue,
|
||||
@ -360,7 +347,7 @@ impl Cast {
|
||||
construct: self.target,
|
||||
effect: ConstructEffect {effect: Effect::Stun, duration: 2, meta: None, tick: None},
|
||||
},
|
||||
Action::Healing {
|
||||
Action::Heal {
|
||||
construct: self.target,
|
||||
values: vec![Value::Stat { construct: self.source, stat: Stat::GreenPower, mult: self.skill.multiplier() }],
|
||||
colour: Colour::Blue,
|
||||
@ -384,7 +371,7 @@ impl Cast {
|
||||
construct: self.target,
|
||||
effect: ConstructEffect {effect: Effect::Sustain, duration: 1, meta: None, tick: None},
|
||||
},
|
||||
Action::Healing {
|
||||
Action::Heal {
|
||||
construct: self.target,
|
||||
values: vec![Value::Stat { construct: self.source, stat: Stat::RedPower, mult: self.skill.multiplier() }],
|
||||
colour: Colour::Red,
|
||||
@ -1706,7 +1693,7 @@ mod tests {
|
||||
// //};
|
||||
|
||||
// match resolutions.remove(0).event {
|
||||
// Event::Healing { skill: _, overhealing: _, amount } => assert!(amount > 0),
|
||||
// Event::Heal { skill: _, overhealing: _, amount } => assert!(amount > 0),
|
||||
// _ => panic!("not healing from inversion"),
|
||||
// };
|
||||
|
||||
@ -1779,7 +1766,7 @@ mod tests {
|
||||
|
||||
// let Event { source: _, target, event, stages: _ } = resolutions.remove(0);
|
||||
// match event {
|
||||
// Event::Healing { amount, skill: _, overhealing: _ } => {
|
||||
// Event::Heal { amount, skill: _, overhealing: _ } => {
|
||||
// assert_eq!(amount, 256.pct(Skill::SiphonTick.multiplier()) + 220.pct(Skill::SiphonTick.multiplier()));
|
||||
// assert_eq!(target.id, x.id);
|
||||
// },
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user