add u8 to resolution struct for breaking up resolution parts

This commit is contained in:
Mashy 2019-05-31 16:20:33 +10:00
parent c7ee7361dd
commit b10c4f988c
4 changed files with 112 additions and 93 deletions

View File

@ -43,7 +43,7 @@ function registerEvents(store) {
return eachSeries(newRes, (r, cb) => { return eachSeries(newRes, (r, cb) => {
if (['Disable', 'TargetKo'].includes(r.event[0])) return cb(); if (['Disable', 'TargetKo'].includes(r.event[0])) return cb();
// Create sub events for combat animations // Create sub events for combat animations
const sequence = getCombatSequence(r.event); const sequence = getCombatSequence(r);
return eachSeries(sequence, (stage, sCb) => { return eachSeries(sequence, (stage, sCb) => {
const { skip } = store.getState(); const { skip } = store.getState();
if (skip) return sCb(); if (skip) return sCb();

View File

@ -276,38 +276,22 @@ function eventClasses(resolution, construct) {
return ''; return '';
} }
function getCombatSequence(event) { function getCombatSequence(resolution) {
if (!event) return false; if (!resolution.event) return false;
// Skip combat animations depending on event type, expandable in future if (resolution.event[0] === 'Inversion') return false;
if (['Inversion'].includes(event[0])) return false; if (resolution.event[0] === 'Skill') return ['START_SKILL', 'END_SKILL'];
if (['Skill', 'AoeSkill'].includes(event[0])) return ['START_SKILL', 'END_SKILL']; if (resolution.event[0] === 'Ko') return ['POST_SKILL'];
if (['Immunity'].includes(event[0])) return ['START_SKILL', 'POST_SKILL'];
if (['Removal'].includes(event[0])) return ['POST_SKILL'];
if (['Healing'].includes(event[0]) switch (resolution.stages) {
&& (event[1].skill.includes('Slay') case 1: return ['START_SKILL', 'END_SKILL'];
|| event[1].skill.includes('SiphonTick') case 2: return ['START_SKILL', 'POST_SKILL'];
|| event[1].skill.includes('Purify') case 3: return ['START_SKILL'];
|| event[1].skill.includes('Sleep'))) return ['POST_SKILL']; case 4: return ['END_SKILL', 'POST_SKILL'];
case 5: return ['END_SKILL'];
if (['Recharge'].includes(event[0]) case 6: return ['POST_SKILL'];
&& (event[1].skill.includes('Reflect'))) return ['POST_SKILL']; case 7: return false;
default: return ['START_SKILL', 'END_SKILL', 'POST_SKILL'];
}
if (event[0] === 'Effect'
&& (['Ruin', 'Taunt', 'Strangling', 'Parry'].includes(event[1].skill)
|| (event[1].skill.includes('Decay') && event[1].effect === 'Wither'))) return ['POST_SKILL'];
if (['Power'].includes(event[0])
&& ((event[1].skill.includes('Chaos') && event[1].colour === 'Red')
|| event[1].skill.includes('Silence')
|| event[1].skill.includes('Snare'))) return ['POST_SKILL'];
if (['Ko'].includes(event[0])
|| (event[1].skill.includes('Throw') && event[1].effect === 'Vulnerable')) return ['POST_SKILL'];
if (['Tick'].includes(event[1].skill)) return ['END_SKILL', 'POST_SKILL'];
return ['START_SKILL', 'END_SKILL', 'POST_SKILL'];
} }
function getCombatText(construct, resolution) { function getCombatText(construct, resolution) {

View File

@ -495,7 +495,7 @@ impl Game {
} }
fn log_resolution(&mut self, speed: u64, resolution: &Resolution) -> &mut Game { fn log_resolution(&mut self, speed: u64, resolution: &Resolution) -> &mut Game {
let Resolution { source, target, event } = resolution; let Resolution { source, target, event, stages } = resolution;
match event { match event {
Event::Ko { skill: _ }=> Event::Ko { skill: _ }=>
self.log.push(format!("{:} KO!", target.name)), self.log.push(format!("{:} KO!", target.name)),
@ -532,10 +532,6 @@ impl Game {
self.log.push(format!("[{:}] {:} {:?} {:} {:?} {:}T", self.log.push(format!("[{:}] {:} {:?} {:} {:?} {:}T",
speed, source.name, skill, target.name, effect, duration)), speed, source.name, skill, target.name, effect, duration)),
Event::AoeSkill { skill } =>
self.log.push(format!("[{:}] {:} {:?} {:}",
speed, source.name, skill, target.name)),
Event::Skill { skill } => Event::Skill { skill } =>
self.log.push(format!("[{:}] {:} {:?} {:}", self.log.push(format!("[{:}] {:} {:?} {:}",
speed, source.name, skill, target.name)), speed, source.name, skill, target.name)),
@ -1263,13 +1259,13 @@ mod tests {
game = game.resolve_phase_start(); game = game.resolve_phase_start();
assert!(game.construct_by_id(x_construct.id).unwrap().affected(Effect::Scatter)); assert!(game.construct_by_id(x_construct.id).unwrap().affected(Effect::Scatter));
let Resolution { source: _, target: _, event } = game.resolved.pop().unwrap(); let Resolution { source: _, target: _, event, stages: _ } = game.resolved.pop().unwrap();
match event { match event {
Event::Effect { effect, skill: _, duration: _, construct_effects: _ } => assert_eq!(effect, Effect::Scatter), Event::Effect { effect, skill: _, duration: _, construct_effects: _ } => assert_eq!(effect, Effect::Scatter),
_ => panic!("not siphon"), _ => panic!("not siphon"),
}; };
let Resolution { source: _, target: _, event } = game.resolved.pop().unwrap(); let Resolution { source: _, target: _, event, stages: _ } = game.resolved.pop().unwrap();
match event { match event {
Event::Recharge { red: _, blue: _, skill: _ } => (), Event::Recharge { red: _, blue: _, skill: _ } => (),
_ => panic!("scatter result was not recharge"), _ => panic!("scatter result was not recharge"),
@ -1281,7 +1277,7 @@ mod tests {
game.player_ready(y_player.id).unwrap(); game.player_ready(y_player.id).unwrap();
game = game.resolve_phase_start(); game = game.resolve_phase_start();
let Resolution { source: _, target, event } = game.resolved.pop().unwrap(); let Resolution { source: _, target, event, stages: _ } = game.resolved.pop().unwrap();
assert_eq!(target.id, y_construct.id); assert_eq!(target.id, y_construct.id);
match event { match event {
Event::Damage { amount, skill: _, mitigation: _, colour: _} => Event::Damage { amount, skill: _, mitigation: _, colour: _} =>
@ -1354,7 +1350,7 @@ mod tests {
let ruins = game.resolved let ruins = game.resolved
.into_iter() .into_iter()
.filter(|r| { .filter(|r| {
let Resolution { source, target: _, event } = r; let Resolution { source, target: _, event, stages: _ } = r;
match source.id == x_construct.id { match source.id == x_construct.id {
true => match event { true => match event {
Event::Effect { effect, duration, skill: _, construct_effects: _ } => { Event::Effect { effect, duration, skill: _, construct_effects: _ } => {
@ -1362,7 +1358,7 @@ mod tests {
assert!(*duration == 1); assert!(*duration == 1);
true true
}, },
Event::AoeSkill { skill: _ } => false, Event::Skill { skill: _ } => false,
_ => panic!("ruin result not effect {:?}", event), _ => panic!("ruin result not effect {:?}", event),
} }
false => false, false => false,
@ -1403,7 +1399,7 @@ mod tests {
assert!(game.resolved.len() == 5); assert!(game.resolved.len() == 5);
while let Some(r) = game.resolved.pop() { while let Some(r) = game.resolved.pop() {
let Resolution { source , target, event: _ } = r; let Resolution { source , target, event: _, stages: _ } = r;
if [i_construct.id, j_construct.id].contains(&source.id) { if [i_construct.id, j_construct.id].contains(&source.id) {
assert!(target.id == x_construct.id); assert!(target.id == x_construct.id);
} }
@ -1493,7 +1489,7 @@ mod tests {
game = game.resolve_phase_start(); game = game.resolve_phase_start();
assert!(game.construct_by_id(y_construct.id).unwrap().affected(Effect::Decay)); assert!(game.construct_by_id(y_construct.id).unwrap().affected(Effect::Decay));
let Resolution { source: _, target: _, event } = game.resolved.pop().unwrap(); let Resolution { source: _, target: _, event, stages: _ } = game.resolved.pop().unwrap();
match event { match event {
Event::Damage { amount: _, skill, mitigation: _, colour: _ } => assert_eq!(skill, Skill::DecayTickI), Event::Damage { amount: _, skill, mitigation: _, colour: _ } => assert_eq!(skill, Skill::DecayTickI),
_ => panic!("not decay"), _ => panic!("not decay"),
@ -1507,7 +1503,7 @@ mod tests {
game.player_ready(y_player.id).unwrap(); game.player_ready(y_player.id).unwrap();
game = game.resolve_phase_start(); game = game.resolve_phase_start();
while let Some(Resolution { source: _, target: _, event }) = game.resolved.pop() { while let Some(Resolution { source: _, target: _, event, stages: _ }) = game.resolved.pop() {
match event { match event {
Event::Damage { amount: _, skill: _, mitigation: _, colour: _ } => Event::Damage { amount: _, skill: _, mitigation: _, colour: _ } =>
panic!("{:?} damage event", event), panic!("{:?} damage event", event),
@ -1527,7 +1523,7 @@ mod tests {
game.player_ready(y_player.id).unwrap(); game.player_ready(y_player.id).unwrap();
game = game.resolve_phase_start(); game = game.resolve_phase_start();
while let Some(Resolution { source: _, target: _, event }) = game.resolved.pop() { while let Some(Resolution { source: _, target: _, event, stages: _ }) = game.resolved.pop() {
match event { match event {
Event::Damage { amount: _, skill: _, mitigation: _, colour: _ } => Event::Damage { amount: _, skill: _, mitigation: _, colour: _ } =>
panic!("{:#?} {:#?} damage event", game.resolved, event), panic!("{:#?} {:#?} damage event", game.resolved, event),

View File

@ -22,7 +22,7 @@ pub fn pre_resolve(cast: &Cast, game: &mut Game, mut resolutions: Resolutions) -
if skill.aoe() { // Send an aoe skill event for anims if skill.aoe() { // Send an aoe skill event for anims
resolutions.push(Resolution::new(&source, resolutions.push(Resolution::new(&source,
&game.construct_by_id(cast.target_construct_id).unwrap().clone()).event(Event::AoeSkill { skill })); &game.construct_by_id(cast.target_construct_id).unwrap().clone()).event(Event::Skill { skill }));
} }
for target_id in targets { for target_id in targets {
@ -282,7 +282,7 @@ pub fn resolve(skill: Skill, source: &mut Construct, target: &mut Construct, mut
} }
fn post_resolve(_skill: Skill, game: &mut Game, mut resolutions: Resolutions) -> Resolutions { fn post_resolve(_skill: Skill, game: &mut Game, mut resolutions: Resolutions) -> Resolutions {
for Resolution { source, target, event } in resolutions.clone() { for Resolution { source, target, event, stages: _ } in resolutions.clone() {
let mut source = game.construct_by_id(source.id).unwrap().clone(); let mut source = game.construct_by_id(source.id).unwrap().clone();
let mut target = game.construct_by_id(target.id).unwrap().clone(); let mut target = game.construct_by_id(target.id).unwrap().clone();
@ -393,11 +393,24 @@ pub struct LogConstruct {
pub blue: u64, pub blue: u64,
} }
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
pub enum LogStages {
AllStages, // 0 Anim Anim Anim
StartEnd, // 1 Anim Anim Skip
StartPost, // 2 Anim Skip Anim
StartOnly, // 3 Anim Skip Skip
EndPost, // 4 Skip Anim Anim
EndOnly, // 5 Skip Anim Skip
PostOnly, // 6 Skip Skip Anim
None, // 7 Skip Skip Skip
}
#[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] #[derive(Debug,Clone,PartialEq,Serialize,Deserialize)]
pub struct Resolution { pub struct Resolution {
pub source: LogConstruct, pub source: LogConstruct,
pub target: LogConstruct, pub target: LogConstruct,
pub event: Event, pub event: Event,
pub stages: u8,
} }
impl Resolution { impl Resolution {
@ -418,6 +431,7 @@ impl Resolution {
blue: target.blue_life(), blue: target.blue_life(),
}, },
event: Event::Incomplete, event: Event::Incomplete,
stages: LogStages::AllStages as u8,
} }
} }
@ -425,6 +439,11 @@ impl Resolution {
self.event = e; self.event = e;
self self
} }
fn stages(mut self, s: LogStages) -> Resolution {
self.stages = s as u8;
self
}
} }
@ -437,7 +456,6 @@ pub enum Event {
Recharge { skill: Skill, red: u64, blue: u64 }, Recharge { skill: Skill, red: u64, blue: u64 },
Inversion { skill: Skill }, Inversion { skill: Skill },
Reflection { skill: Skill }, Reflection { skill: Skill },
AoeSkill { skill: Skill },
Skill { skill: Skill }, Skill { skill: Skill },
Effect { skill: Skill, effect: Effect, duration: u8, construct_effects: Vec<ConstructEffect> }, Effect { skill: Skill, effect: Effect, duration: u8, construct_effects: Vec<ConstructEffect> },
Removal { effect: Effect, construct_effects: Vec<ConstructEffect> }, Removal { effect: Effect, construct_effects: Vec<ConstructEffect> },
@ -1486,7 +1504,7 @@ fn sleep(source: &mut Construct, target: &mut Construct, mut results: Resolution
let amount = source.green_power().pct(skill.multiplier()); let amount = source.green_power().pct(skill.multiplier());
target.deal_green_damage(skill, amount) target.deal_green_damage(skill, amount)
.into_iter() .into_iter()
.for_each(|e| results.push(Resolution::new(source, target).event(e))); .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::PostOnly)));
return results; return results;
} }
@ -1501,14 +1519,17 @@ fn taunt(source: &mut Construct, target: &mut Construct, mut results: Resolution
let red_amount = source.red_power().pct(skill.multiplier()); let red_amount = source.red_power().pct(skill.multiplier());
results.push(Resolution::new(source, target).event(target.recharge(skill, red_amount, 0))); results.push(Resolution::new(source, target).event(target.recharge(skill, red_amount, 0)));
skill.effect().into_iter() let taunt = skill.effect()[0];
.for_each(|e| (results.push(Resolution::new(source, target).event(target.add_effect(skill, e))))); results.push(Resolution::new(source, target).event(target.add_effect(skill, taunt)).stages(LogStages::PostOnly));
return results; return results;
} }
fn throw(source: &mut Construct, target: &mut Construct, mut results: Resolutions, skill: Skill) -> Resolutions { fn throw(source: &mut Construct, target: &mut Construct, mut results: Resolutions, skill: Skill) -> Resolutions {
skill.effect().into_iter() let stun = skill.effect()[0];
.for_each(|e| (results.push(Resolution::new(source, target).event(target.add_effect(skill, e))))); results.push(Resolution::new(source, target).event(target.add_effect(skill, stun)));
let vuln = skill.effect()[1];
results.push(Resolution::new(source, target).event(target.add_effect(skill, vuln)).stages(LogStages::PostOnly));
return results; return results;
} }
@ -1522,7 +1543,7 @@ fn strangle(source: &mut Construct, target: &mut Construct, mut results: Resolut
results.push(Resolution::new(source, target).event(target.add_effect(skill, strangle))); results.push(Resolution::new(source, target).event(target.add_effect(skill, strangle)));
let attacker_strangle = ConstructEffect::new(Effect::Strangling, duration); let attacker_strangle = ConstructEffect::new(Effect::Strangling, duration);
results.push(Resolution::new(source, source).event(source.add_effect(skill, attacker_strangle))); results.push(Resolution::new(source, source).event(source.add_effect(skill, attacker_strangle)).stages(LogStages::PostOnly));
return strangle_tick(source, target, results, tick_skill); return strangle_tick(source, target, results, tick_skill);
} }
@ -1530,7 +1551,7 @@ fn strangle_tick(source: &mut Construct, target: &mut Construct, mut results: Re
let amount = source.red_power().pct(skill.multiplier()); let amount = source.red_power().pct(skill.multiplier());
target.deal_red_damage(skill, amount) target.deal_red_damage(skill, amount)
.into_iter() .into_iter()
.for_each(|e| results.push(Resolution::new(source, target).event(e))); .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::EndPost)));
// remove immunity if target ko // remove immunity if target ko
if target.is_ko() { if target.is_ko() {
@ -1540,30 +1561,36 @@ fn strangle_tick(source: &mut Construct, target: &mut Construct, mut results: Re
.expect("no strangling on construct"); .expect("no strangling on construct");
source.effects.remove(i); source.effects.remove(i);
results.push(Resolution::new(source, source) results.push(Resolution::new(source, source)
.event(Event::Removal { effect: Effect::Strangling, construct_effects: target.effects.clone() })); .event(Event::Removal { effect: Effect::Strangling, construct_effects: target.effects.clone() })
.stages(LogStages::PostOnly));
} }
return results; return results;
} }
fn block(source: &mut Construct, target: &mut Construct, mut results: Resolutions, skill: Skill) -> Resolutions { fn block(source: &mut Construct, target: &mut Construct, mut results: Resolutions, skill: Skill) -> Resolutions {
skill.effect().into_iter() results.push(Resolution::new(source, target)
.for_each(|e| (results.push(Resolution::new(source, target).event(target.add_effect(skill, e))))); .event(target.add_effect(skill, skill.effect()[0]))
.stages(LogStages::StartEnd));
return results; return results;
} }
fn buff(source: &mut Construct, target: &mut Construct, mut results: Resolutions, skill: Skill) -> Resolutions { fn buff(source: &mut Construct, target: &mut Construct, mut results: Resolutions, skill: Skill) -> Resolutions {
skill.effect().into_iter() results.push(Resolution::new(source, target)
.for_each(|e| (results.push(Resolution::new(source, target).event(target.add_effect(skill, e))))); .event(target.add_effect(skill, skill.effect()[0])));
return results; return results;
} }
fn parry(source: &mut Construct, target: &mut Construct, mut results: Resolutions, skill: Skill) -> Resolutions { fn parry(source: &mut Construct, target: &mut Construct, mut results: Resolutions, skill: Skill) -> Resolutions {
let red_amount = source.red_power().pct(skill.multiplier()); let red_amount = source.red_power().pct(skill.multiplier());
results.push(Resolution::new(source, target).event(target.recharge(skill, red_amount, 0))); results.push(Resolution::new(source, target)
.event(target.recharge(skill, red_amount, 0))
.stages(LogStages::StartEnd));
skill.effect().into_iter() results.push(Resolution::new(source, target)
.for_each(|e| (results.push(Resolution::new(source, target).event(target.add_effect(skill, e))))); .event(target.add_effect(skill, skill.effect()[0]))
.stages(LogStages::PostOnly));
return results; return results;
} }
@ -1571,7 +1598,7 @@ fn riposte(source: &mut Construct, target: &mut Construct, mut results: Resoluti
let amount = source.red_power().pct(skill.multiplier()); let amount = source.red_power().pct(skill.multiplier());
target.deal_red_damage(skill, amount) target.deal_red_damage(skill, amount)
.into_iter() .into_iter()
.for_each(|e| results.push(Resolution::new(source, target).event(e))); .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::StartPost)));
return results; return results;
} }
@ -1590,7 +1617,7 @@ fn snare(source: &mut Construct, target: &mut Construct, mut results: Resolution
let amount = source.red_power().pct(skill.multiplier()).pct(s_multi); let amount = source.red_power().pct(skill.multiplier()).pct(s_multi);
target.deal_red_damage(skill, amount) target.deal_red_damage(skill, amount)
.into_iter() .into_iter()
.for_each(|e| results.push(Resolution::new(source, target).event(e))); .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::PostOnly)));
return results; return results;
@ -1606,7 +1633,7 @@ fn slay(source: &mut Construct, target: &mut Construct, mut results: Resolutions
results.push(Resolution::new(source, target).event(e)); results.push(Resolution::new(source, target).event(e));
let heal = source.deal_green_damage(skill, amount); let heal = source.deal_green_damage(skill, amount);
for h in heal { for h in heal {
results.push(Resolution::new(source, source).event(h)); results.push(Resolution::new(source, source).event(h).stages(LogStages::PostOnly));
}; };
}, },
_ => results.push(Resolution::new(source, target).event(e)), _ => results.push(Resolution::new(source, target).event(e)),
@ -1639,7 +1666,7 @@ fn triage_tick(source: &mut Construct, target: &mut Construct, mut results: Reso
let amount = source.green_power().pct(skill.multiplier()); let amount = source.green_power().pct(skill.multiplier());
target.deal_green_damage(skill, amount) target.deal_green_damage(skill, amount)
.into_iter() .into_iter()
.for_each(|e| results.push(Resolution::new(source, target).event(e))); .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::EndPost)));
return results; return results;
} }
@ -1654,7 +1681,7 @@ fn chaos(source: &mut Construct, target: &mut Construct, mut results: Resolution
let amount = source.red_power().pct(skill.multiplier()).pct(r_rng); let amount = source.red_power().pct(skill.multiplier()).pct(r_rng);
target.deal_red_damage(skill, amount) target.deal_red_damage(skill, amount)
.into_iter() .into_iter()
.for_each(|e| results.push(Resolution::new(source, target).event(e))); .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::PostOnly)));
return results; return results;
} }
@ -1692,7 +1719,9 @@ fn decay(source: &mut Construct, target: &mut Construct, mut results: Resolution
_ => panic!("no decay tick skill"), _ => panic!("no decay tick skill"),
}; };
let decay = ConstructEffect::new(effect, duration).set_tick(Cast::new_tick(source, target, tick_skill)); let decay = ConstructEffect::new(effect, duration).set_tick(Cast::new_tick(source, target, tick_skill));
results.push(Resolution::new(source, target).event(target.add_effect(skill, decay))); results.push(Resolution::new(source, target)
.event(target.add_effect(skill, decay))
.stages(LogStages::PostOnly));
return decay_tick(source, target, results, tick_skill); return decay_tick(source, target, results, tick_skill);
} }
@ -1701,7 +1730,7 @@ fn decay_tick(source: &mut Construct, target: &mut Construct, mut results: Resol
let amount = source.blue_power().pct(skill.multiplier()); let amount = source.blue_power().pct(skill.multiplier());
target.deal_blue_damage(skill, amount) target.deal_blue_damage(skill, amount)
.into_iter() .into_iter()
.for_each(|e| results.push(Resolution::new(source, target).event(e))); .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::EndPost)));
return results; return results;
} }
@ -1721,7 +1750,9 @@ fn corruption(source: &mut Construct, target: &mut Construct, mut results: Resol
_ => panic!("no corruption tick skill"), _ => panic!("no corruption tick skill"),
}; };
let corruption = ConstructEffect::new(effect, duration).set_tick(Cast::new_tick(source, target, tick_skill)); let corruption = ConstructEffect::new(effect, duration).set_tick(Cast::new_tick(source, target, tick_skill));
results.push(Resolution::new(source, target).event(target.add_effect(skill, corruption))); results.push(Resolution::new(source, target)
.event(target.add_effect(skill, corruption))
.stages(LogStages::StartPost));
return corruption_tick(source, target, results, tick_skill); return corruption_tick(source, target, results, tick_skill);
} }
@ -1729,12 +1760,14 @@ fn corruption_tick(source: &mut Construct, target: &mut Construct, mut results:
let amount = source.blue_power().pct(skill.multiplier()); let amount = source.blue_power().pct(skill.multiplier());
target.deal_blue_damage(skill, amount) target.deal_blue_damage(skill, amount)
.into_iter() .into_iter()
.for_each(|e| results.push(Resolution::new(source, target).event(e))); .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::EndPost)));
return results; return results;
} }
fn ruin(source: &mut Construct, target: &mut Construct, mut results: Resolutions, skill: Skill) -> Resolutions { fn ruin(source: &mut Construct, target: &mut Construct, mut results: Resolutions, skill: Skill) -> Resolutions {
results.push(Resolution::new(source, target).event(target.add_effect(skill, skill.effect()[0]))); results.push(Resolution::new(source, target)
.event(target.add_effect(skill, skill.effect()[0]))
.stages(LogStages::PostOnly));
return results;; return results;;
} }
@ -1751,7 +1784,9 @@ fn hostility(source: &mut Construct, target: &mut Construct, mut results: Resolu
fn hatred(source: &mut Construct, target: &mut Construct, mut results: Resolutions, reflect_skill: Skill, amount: u64, skill: Skill) -> Resolutions { fn hatred(source: &mut Construct, target: &mut Construct, mut results: Resolutions, reflect_skill: Skill, amount: u64, skill: Skill) -> Resolutions {
let hatred = skill.effect()[0].set_meta(EffectMeta::AddedDamage(amount)); let hatred = skill.effect()[0].set_meta(EffectMeta::AddedDamage(amount));
results.push(Resolution::new(source, target).event(target.add_effect(reflect_skill, hatred))); results.push(Resolution::new(source, target)
.event(target.add_effect(reflect_skill, hatred))
.stages(LogStages::PostOnly));
return results;; return results;;
} }
@ -1774,7 +1809,9 @@ fn reflect(source: &mut Construct, target: &mut Construct, mut results: Resoluti
results.push(Resolution::new(source, target).event(target.add_effect(skill, skill.effect()[0]))); results.push(Resolution::new(source, target).event(target.add_effect(skill, skill.effect()[0])));
let blue_amount = source.blue_power().pct(skill.multiplier()); let blue_amount = source.blue_power().pct(skill.multiplier());
results.push(Resolution::new(source, target).event(target.recharge(skill, 0, blue_amount))); results.push(Resolution::new(source, target)
.event(target.recharge(skill, 0, blue_amount))
.stages(LogStages::PostOnly));
return results;; return results;;
} }
@ -1806,13 +1843,13 @@ fn siphon_tick(source: &mut Construct, target: &mut Construct, mut results: Reso
for e in siphon_events { for e in siphon_events {
match e { match e {
Event::Damage { amount, mitigation: _, colour: _, skill: _ } => { Event::Damage { amount, mitigation: _, colour: _, skill: _ } => {
results.push(Resolution::new(source, target).event(e)); results.push(Resolution::new(source, target).event(e).stages(LogStages::EndPost));
let heal = source.deal_green_damage(skill, amount); let heal = source.deal_green_damage(skill, amount);
for h in heal { for h in heal {
results.push(Resolution::new(source, source).event(h)); results.push(Resolution::new(source, source).event(h).stages(LogStages::PostOnly));
}; };
}, },
_ => results.push(Resolution::new(source, target).event(e)), _ => results.push(Resolution::new(source, target).event(e).stages(LogStages::EndPost)),
} }
} }
@ -1824,7 +1861,7 @@ fn scatter(source: &mut Construct, target: &mut Construct, mut results: Resoluti
results.push(Resolution::new(source, target).event(target.recharge(skill, 0, blue_amount))); results.push(Resolution::new(source, target).event(target.recharge(skill, 0, blue_amount)));
let scatter = skill.effect()[0].set_meta(EffectMeta::ScatterTarget(target.id)); let scatter = skill.effect()[0].set_meta(EffectMeta::ScatterTarget(target.id));
results.push(Resolution::new(source, target).event(source.add_effect(skill, scatter))); results.push(Resolution::new(source, target).event(source.add_effect(skill, scatter)).stages(LogStages::PostOnly));
return results; return results;
} }
@ -1844,7 +1881,8 @@ fn scatter_hit(source: &Construct, target: &Construct, mut results: Resolutions,
}; };
results.push(Resolution::new(target, scatter_target).event(Event::Skill { skill: Skill::ScatterI })); results.push(Resolution::new(target, scatter_target).event(Event::Skill { skill: Skill::ScatterI }));
res.into_iter().for_each(|e| results.push(Resolution::new(&source, &scatter_target).event(e))); res.into_iter().for_each(|e| results.push(Resolution::new(&source, &scatter_target)
.event(e).stages(LogStages::EndPost)));
} else { } else {
panic!("not a scatter target {:?}", scatter); panic!("not a scatter target {:?}", scatter);
} }
@ -1868,7 +1906,7 @@ fn silence(source: &mut Construct, target: &mut Construct, mut results: Resoluti
let amount = source.blue_power().pct(skill.multiplier()).pct(s_multi); let amount = source.blue_power().pct(skill.multiplier()).pct(s_multi);
target.deal_blue_damage(skill, amount) target.deal_blue_damage(skill, amount)
.into_iter() .into_iter()
.for_each(|e| results.push(Resolution::new(source, target).event(e))); .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::PostOnly)));
return results; return results;
} }
@ -1893,10 +1931,11 @@ fn purify(source: &mut Construct, target: &mut Construct, mut results: Resolutio
.position(|ce| ce.effect.category() == EffectCategory::Debuff) { .position(|ce| ce.effect.category() == EffectCategory::Debuff) {
let ce = target.effects.remove(i); let ce = target.effects.remove(i);
results.push(Resolution::new(source, target) results.push(Resolution::new(source, target)
.event(Event::Removal { effect: ce.effect, construct_effects: target.effects.clone() })); .event(Event::Removal { effect: ce.effect, construct_effects: target.effects.clone() })
.stages(LogStages::PostOnly));
target.deal_green_damage(skill, amount) target.deal_green_damage(skill, amount)
.into_iter() .into_iter()
.for_each(|e| results.push(Resolution::new(source, target).event(e))); .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::PostOnly)));
} }
return results; return results;
@ -1960,7 +1999,7 @@ mod tests {
let mut results = attack(&mut x, &mut y, vec![], Skill::Attack); let mut results = attack(&mut x, &mut y, vec![], Skill::Attack);
let Resolution { source: _, target: _, event } = results.remove(0); let Resolution { source: _, target: _, event, stages: _ } = results.remove(0);
match event { match event {
Event::Damage { amount, mitigation: _, colour: _, skill: _ } => Event::Damage { amount, mitigation: _, colour: _, skill: _ } =>
assert!(amount < x.red_power().pct(Skill::Attack.multiplier())), assert!(amount < x.red_power().pct(Skill::Attack.multiplier())),
@ -1982,7 +2021,7 @@ mod tests {
assert!(y.affected(Effect::Clutch)); assert!(y.affected(Effect::Clutch));
let mut results = hex(&mut x, &mut y, vec![], Skill::HexI); let mut results = hex(&mut x, &mut y, vec![], Skill::HexI);
let Resolution { source: _, target: _, event } = results.remove(0); let Resolution { source: _, target: _, event, stages: _ } = results.remove(0);
match event { match event {
Event::Immunity { skill: _, immunity } => assert!(immunity.contains(&Effect::Clutch)), Event::Immunity { skill: _, immunity } => assert!(immunity.contains(&Effect::Clutch)),
_ => panic!("not immune cluthc"), _ => panic!("not immune cluthc"),
@ -1991,7 +2030,7 @@ mod tests {
let mut results = attack(&mut x, &mut y, vec![], Skill::Attack); let mut results = attack(&mut x, &mut y, vec![], Skill::Attack);
assert!(y.green_life() == 1); assert!(y.green_life() == 1);
let Resolution { source: _, target: _, event } = results.remove(0); let Resolution { source: _, target: _, event, stages: _ } = results.remove(0);
match event { match event {
Event::Damage { amount, mitigation: _, colour: _, skill: _ } => assert_eq!(amount, 1023), Event::Damage { amount, mitigation: _, colour: _, skill: _ } => assert_eq!(amount, 1023),
_ => panic!("not damage"), _ => panic!("not damage"),
@ -2065,13 +2104,13 @@ mod tests {
assert!(x.green_life() < 1024); assert!(x.green_life() < 1024);
let Resolution { source: _, target: _, event } = results.remove(0); let Resolution { source: _, target: _, event, stages: _ } = results.remove(0);
match event { match event {
Event::Reflection { skill } => assert_eq!(skill, Skill::Attack), Event::Reflection { skill } => assert_eq!(skill, Skill::Attack),
_ => panic!("not reflection"), _ => panic!("not reflection"),
}; };
let Resolution { source: _, target: _, event } = results.remove(0); let Resolution { source: _, target: _, event, stages: _ } = results.remove(0);
match event { match event {
Event::Damage { amount, mitigation: _, colour: _, skill: _ } => assert!(amount > 0), Event::Damage { amount, mitigation: _, colour: _, skill: _ } => assert!(amount > 0),
_ => panic!("not damage"), _ => panic!("not damage"),
@ -2093,19 +2132,19 @@ mod tests {
assert!(y.affected(Effect::Siphon)); assert!(y.affected(Effect::Siphon));
assert!(x.green_life() == (512 + 256.pct(Skill::SiphonTickI.multiplier()))); assert!(x.green_life() == (512 + 256.pct(Skill::SiphonTickI.multiplier())));
let Resolution { source: _, target: _, event } = results.remove(0); let Resolution { source: _, target: _, event, stages: _ } = results.remove(0);
match event { match event {
Event::Effect { effect, skill: _, duration: _, construct_effects: _ } => assert_eq!(effect, Effect::Siphon), Event::Effect { effect, skill: _, duration: _, construct_effects: _ } => assert_eq!(effect, Effect::Siphon),
_ => panic!("not siphon"), _ => panic!("not siphon"),
}; };
let Resolution { source: _, target: _, event } = results.remove(0); let Resolution { source: _, target: _, event, stages: _ } = results.remove(0);
match event { match event {
Event::Damage { amount, skill: _, mitigation: _, colour: _} => assert_eq!(amount, 256.pct(Skill::SiphonTickI.multiplier())), Event::Damage { amount, skill: _, mitigation: _, colour: _} => assert_eq!(amount, 256.pct(Skill::SiphonTickI.multiplier())),
_ => panic!("not damage siphon"), _ => panic!("not damage siphon"),
}; };
let Resolution { source: _, target, event } = results.remove(0); let Resolution { source: _, target, event, stages: _ } = results.remove(0);
match event { match event {
Event::Healing { amount, skill: _, overhealing: _ } => { Event::Healing { amount, skill: _, overhealing: _ } => {
assert_eq!(amount, 256.pct(Skill::SiphonTickI.multiplier())); assert_eq!(amount, 256.pct(Skill::SiphonTickI.multiplier()));
@ -2155,7 +2194,7 @@ mod tests {
let mut results = recharge(&mut x, &mut y, vec![], Skill::RechargeI); let mut results = recharge(&mut x, &mut y, vec![], Skill::RechargeI);
let Resolution { source: _, target: _, event } = results.remove(0); let Resolution { source: _, target: _, event, stages: _ } = results.remove(0);
match event { match event {
Event::Recharge { red, blue, skill: _ } => { Event::Recharge { red, blue, skill: _ } => {
assert!(red == 5); assert!(red == 5);