hastestrike and hybridblast
This commit is contained in:
parent
5e8d6a62af
commit
bf3c087155
@ -3,12 +3,7 @@
|
||||
last round of animations skipped cause no skill phase to add new vec
|
||||
check silence skill multiplier
|
||||
|
||||
tick skips for triage etc
|
||||
game ready not auto starting resolve phase
|
||||
remove immunity
|
||||
banish immunity
|
||||
|
||||
aoe event
|
||||
cooldown events leak skills
|
||||
|
||||
purify conditional healing
|
||||
|
||||
@ -378,6 +378,11 @@ impl Construct {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn additional_skills(&self, skill: Skill) -> Vec<Skill> {
|
||||
self.effects.iter()
|
||||
.filter_map(|e| skill.additional_skill(e.effect))
|
||||
.collect::<Vec<Skill>>()
|
||||
}
|
||||
|
||||
pub fn is_stunned(&self) -> bool {
|
||||
self.available_skills().len() == 0
|
||||
|
||||
@ -134,7 +134,7 @@ impl Game {
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn all_constructs(&self) -> Vec<Construct> {
|
||||
fn copy_constructs(&self) -> Vec<Construct> {
|
||||
self.players.clone()
|
||||
.into_iter()
|
||||
.flat_map(
|
||||
@ -426,7 +426,7 @@ impl Game {
|
||||
}
|
||||
|
||||
// find their statuses with ticks
|
||||
let mut ticks = self.all_constructs()
|
||||
let mut ticks = self.copy_constructs()
|
||||
.iter()
|
||||
.flat_map(
|
||||
|c| c.effects
|
||||
@ -477,6 +477,7 @@ impl Game {
|
||||
self.add_resolution(&cast, &Event::Disable { construct: cast.source, effects });
|
||||
return self;
|
||||
}
|
||||
|
||||
// for aoe events send the source / target animations before each set of casts
|
||||
if cast.skill.aoe() {
|
||||
if cast.skill.cast_animation() {
|
||||
@ -492,6 +493,8 @@ impl Game {
|
||||
self.execute(cast);
|
||||
}
|
||||
|
||||
self.progress_durations();
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
@ -515,8 +518,6 @@ impl Game {
|
||||
false => vec![cast],
|
||||
};
|
||||
|
||||
// check for reflect
|
||||
|
||||
return casts;
|
||||
}
|
||||
|
||||
@ -531,6 +532,13 @@ impl Game {
|
||||
return self;
|
||||
}
|
||||
|
||||
// hastestrike / hybridblast
|
||||
// i think this goes here...
|
||||
// maybe in modify casts or something
|
||||
for skill in self.construct(cast.target).additional_skills(cast.skill) {
|
||||
self.resolve(Cast { skill, ..cast });
|
||||
}
|
||||
|
||||
if let Some(immunity) = self.construct(cast.target).immune(cast.skill) {
|
||||
self.add_resolution(&cast, &Event::Immune { construct: cast.target, effects: immunity });
|
||||
return self;
|
||||
@ -716,17 +724,25 @@ impl Game {
|
||||
(x, y)
|
||||
}
|
||||
|
||||
fn progress_durations(&mut self, Resolutions: &Vec<Cast>) -> &mut Game {
|
||||
for mut construct in self.all_constructs() {
|
||||
// info!("progressing durations for {:}", construct.name);
|
||||
fn progress_durations(&mut self) -> &mut Game {
|
||||
let last = self.resolutions.len() - 1;
|
||||
let used_cooldown = self.resolutions[last].iter()
|
||||
.filter_map(|r| match r.event {
|
||||
Event::Cast { construct, player: _, direction: _ } => match r.skill.base_cd().is_some() {
|
||||
true => Some(construct),
|
||||
false => None,
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.collect::<Vec<Uuid>>();
|
||||
|
||||
for mut construct in self.copy_constructs() {
|
||||
if construct.is_ko() {
|
||||
continue;
|
||||
}
|
||||
|
||||
match Resolutions.iter().find(|s| s.source == construct.id) {
|
||||
Some(skill) => { construct.skill_set_cd(skill.skill); },
|
||||
None => { construct.reduce_cooldowns(); },
|
||||
if !used_cooldown.contains(&construct.id) {
|
||||
construct.reduce_cooldowns();
|
||||
};
|
||||
|
||||
// always reduce durations
|
||||
@ -737,66 +753,6 @@ impl Game {
|
||||
self
|
||||
}
|
||||
|
||||
// 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)),
|
||||
|
||||
// Resolution::Disable { skill, disable } =>
|
||||
// self.log.push(format!("{:} {:?} {:} disabled {:?}",
|
||||
// source.name, skill, target.name, disable)),
|
||||
|
||||
// Resolution::Immunity { skill, immunity } =>
|
||||
// self.log.push(format!("[{:}] {:} {:?} {:} immune {:?}",
|
||||
// speed, source.name, skill, target.name, immunity)),
|
||||
|
||||
// Resolution::TargetKo { skill } =>
|
||||
// self.log.push(format!("[{:}] {:} {:?} {:} - target is KO",
|
||||
// speed, source.name, skill, target.name)),
|
||||
|
||||
// Resolution::Damage { skill, amount, mitigation, colour: _ } =>
|
||||
// self.log.push(format!("[{:}] {:} {:?} {:} {:} ({:} mitigated)",
|
||||
// speed, source.name, skill, target.name, amount, mitigation)),
|
||||
|
||||
// Resolution::Healing { skill, amount, overhealing } =>
|
||||
// self.log.push(format!("[{:}] {:} {:?} {:} {:} healing ({:}OH)",
|
||||
// speed, source.name, skill, target.name, amount, overhealing)),
|
||||
|
||||
// Resolution::Inversion { skill } =>
|
||||
// self.log.push(format!("[{:}] {:} {:?} {:} INVERTED",
|
||||
// speed, source.name, skill, target.name)),
|
||||
|
||||
// Resolution::Reflection { skill } =>
|
||||
// self.log.push(format!("[{:}] {:} {:?} {:} REFLECTED",
|
||||
// speed, source.name, skill, target.name)),
|
||||
|
||||
// Resolution::Effect { skill, effect, duration, construct_effects: _ } =>
|
||||
// self.log.push(format!("[{:}] {:} {:?} {:} {:?} {:}T",
|
||||
// speed, source.name, skill, target.name, effect, duration)),
|
||||
|
||||
// Resolution::Skill { skill } =>
|
||||
// self.log.push(format!("[{:}] {:} {:?} {:}",
|
||||
// speed, source.name, skill, target.name)),
|
||||
|
||||
// Resolution::Removal { effect, construct_effects: _ } =>
|
||||
// self.log.push(format!("[{:}] {:?} removed {:} {:?}",
|
||||
// speed, source.name, target.name, effect)),
|
||||
|
||||
// Resolution::Recharge { skill, red, blue } =>
|
||||
// self.log.push(format!("[{:}] {:} {:?} {:} {:}R {:}B",
|
||||
// speed, source.name, skill, target.name, red, blue)),
|
||||
|
||||
// Resolution::Evasion { skill, evasion_rating } =>
|
||||
// self.log.push(format!("[{:}] {:} {:?} {:} evaded ({:}%)",
|
||||
// speed, source.name, skill, target.name, evasion_rating)),
|
||||
|
||||
// Resolution::Incomplete => panic!("incomplete resolution {:?}", resolution),
|
||||
// }
|
||||
|
||||
// self
|
||||
// }
|
||||
|
||||
pub fn finished(&self) -> bool {
|
||||
self.phase == Phase::Finished || self.players.iter().any(|t| t.constructs.iter().all(|c| c.is_ko()))
|
||||
}
|
||||
|
||||
@ -47,10 +47,6 @@ impl Cast {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn used_cooldown(&self) -> bool {
|
||||
return self.skill.base_cd().is_some();
|
||||
}
|
||||
|
||||
pub fn actions(&self) -> Vec<Action> {
|
||||
let mut rng = thread_rng();
|
||||
|
||||
@ -509,6 +505,14 @@ impl Cast {
|
||||
},
|
||||
],
|
||||
|
||||
Skill::HasteStrike => vec![
|
||||
Action::Damage {
|
||||
construct: self.target,
|
||||
colour: Colour::Red,
|
||||
values: vec![Value::Stat { construct: self.source, stat: Stat::Speed, mult: self.skill.multiplier() }],
|
||||
},
|
||||
],
|
||||
|
||||
Skill::Hybrid => vec![
|
||||
Action::Effect {
|
||||
construct: self.target,
|
||||
@ -528,6 +532,14 @@ impl Cast {
|
||||
},
|
||||
],
|
||||
|
||||
Skill::HybridBlast => vec![
|
||||
Action::Damage {
|
||||
construct: self.target,
|
||||
colour: Colour::Blue,
|
||||
values: vec![Value::Stat { construct: self.source, stat: Stat::GreenPower, mult: self.skill.multiplier() }],
|
||||
},
|
||||
],
|
||||
|
||||
Skill::Intercept |
|
||||
Skill::InterceptPlus |
|
||||
Skill::InterceptPlusPlus => vec![
|
||||
@ -1773,6 +1785,36 @@ impl Skill {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn additional_skill(&self, effect: Effect) -> Option<Skill> {
|
||||
match effect {
|
||||
Effect::Haste => match self {
|
||||
Skill::Slay |
|
||||
Skill::SlayPlus |
|
||||
Skill::SlayPlusPlus |
|
||||
Skill::Chaos |
|
||||
Skill::ChaosPlus |
|
||||
Skill::ChaosPlusPlus |
|
||||
Skill::Strike |
|
||||
Skill::StrikePlus |
|
||||
Skill::StrikePlusPlus => Some(Skill::HasteStrike),
|
||||
_ => None,
|
||||
},
|
||||
Effect::Hybrid => match self {
|
||||
Skill::Blast|
|
||||
Skill::BlastPlus |
|
||||
Skill::BlastPlusPlus |
|
||||
Skill::Chaos |
|
||||
Skill::ChaosPlus |
|
||||
Skill::ChaosPlusPlus |
|
||||
Skill::Siphon |
|
||||
Skill::SiphonPlus |
|
||||
Skill::SiphonPlusPlus => Some(Skill::HybridBlast),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn components(&self) -> Vec<Item> {
|
||||
let mut components = Item::from(*self).components();
|
||||
components.sort_unstable();
|
||||
@ -2145,177 +2187,5 @@ mod tests {
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
// Skill::Strike => game.event(
|
||||
// Event::Damage {
|
||||
// colour: Colour::Red,
|
||||
// amount: SkillPower { construct: cast.source, skill: Skill::Strike }
|
||||
// },
|
||||
// Event::LifeSteal {
|
||||
// amount: CastDamage { id: cast.id, colour: Colour::Red, target: cast.source },
|
||||
// },
|
||||
// ),
|
||||
|
||||
// Skill::Attack => game.event(Event::Damage {
|
||||
// colour: Colour::Red,
|
||||
// amount: Stat { construct: cast.source, stat: Stat::RedPower, pct: ATTACK_RED_POWER_PCT }
|
||||
// }),
|
||||
|
||||
|
||||
// Skill::Bash => game.event(Event::Damage {
|
||||
// colour: Colour::Red,
|
||||
// amounts: vec![
|
||||
// Stat { construct: cast.source, stat: Stat::RedPower, pct: ATTACK_RED_POWER_PCT },
|
||||
// Cooldowns { construct: cast.source },
|
||||
// ],
|
||||
// })
|
||||
|
||||
// // we clone the current state of the target and source
|
||||
// // so we can modify them during the resolution
|
||||
// // no more than 1 mutable ref allowed on game
|
||||
|
||||
// let mut source = game.construct_by_id(cast.source).unwrap().clone();
|
||||
// let mut target = game.construct_by_id(target_id).unwrap().clone();
|
||||
|
||||
// // bail out on ticks that have been removed
|
||||
// if skill.is_tick() && target.effects.iter().find(|ce| match ce.tick {
|
||||
// Some(t) => t.id == cast.id,
|
||||
// None => false,
|
||||
// }).is_none() {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if let Some(_disable) = source.disabled(skill) {
|
||||
// game.event(Event::new(source, target).event(Event::Disable { disable, skill }).stages(EventStages::PostOnly));
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if target.is_ko() {
|
||||
// game.event(Event::new(source, target).event(Event::TargetKo { skill }).stages(EventStages::PostOnly));
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if target.affected(Effect::Reflect) && skill.colours().contains(&Colour::Blue) && !skill.is_tick() {
|
||||
// // guard against overflow
|
||||
// if source.affected(Effect::Reflect) {
|
||||
// }
|
||||
// game.event(Event::new(source, target).event(Event::Reflection { skill }));
|
||||
// return cast_actions(skill, &mut source.clone(), source, resolutions);
|
||||
// }
|
||||
|
||||
|
||||
// // haste_strike_check(game)
|
||||
|
||||
// if source.affected(Effect::Haste) {
|
||||
// match skill {
|
||||
// Skill::Slay |
|
||||
// Skill::SlayPlus |
|
||||
// Skill::SlayPlusPlus |
|
||||
// Skill::Chaos |
|
||||
// Skill::ChaosPlus |
|
||||
// Skill::ChaosPlusPlus |
|
||||
// Skill::Strike |
|
||||
// Skill::StrikePlus |
|
||||
// Skill::StrikePlusPlus => {
|
||||
// let amount = source.speed().pct(Skill::HasteStrike.multiplier());
|
||||
// target.deal_red_damage(Skill::HasteStrike, amount)
|
||||
// .into_iter()
|
||||
// .for_each(|e| game.event(Event::new(source, target).event(e)));
|
||||
// },
|
||||
// _ => (),
|
||||
// }
|
||||
// }
|
||||
|
||||
// if source.affected(Effect::Hybrid) {
|
||||
// match skill {
|
||||
// Skill::Blast|
|
||||
// Skill::BlastPlus |
|
||||
// Skill::BlastPlusPlus |
|
||||
// Skill::Chaos |
|
||||
// Skill::ChaosPlus |
|
||||
// Skill::ChaosPlusPlus |
|
||||
// Skill::Siphon |
|
||||
// Skill::SiphonPlus |
|
||||
// Skill::SiphonPlusPlus => {
|
||||
// let amount = source.green_power().pct(Skill::HybridBlast.multiplier());
|
||||
// target.deal_blue_damage(Skill::HybridBlast, amount)
|
||||
// .into_iter()
|
||||
// .for_each(|e| game.event(Event::new(source, target).event(e)));
|
||||
// },
|
||||
// _ => (),
|
||||
// }
|
||||
// }
|
||||
|
||||
// match self.category() == EffectCategory::Red {
|
||||
// true => {
|
||||
// if let Some(evasion) = target.evade(*self) {
|
||||
// game.event(evasion);
|
||||
// return Event;
|
||||
// }
|
||||
// },
|
||||
// false => (),
|
||||
// }
|
||||
|
||||
// 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::CastOnHit(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::CastOnHit(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::CastOnHit(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));
|
||||
// }
|
||||
// },
|
||||
// _ => (),
|
||||
// };
|
||||
|
||||
|
||||
// game.update_construct(&mut source);
|
||||
// game.update_construct(&mut target);
|
||||
// };
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user