tick effect matching reimpl
This commit is contained in:
parent
153b3a1e9c
commit
6e3675364e
@ -5,6 +5,9 @@ _ntr_
|
||||
* can't reset password without knowing password =\
|
||||
* hard reload client on version change
|
||||
|
||||
electrify on death / stun
|
||||
siphon stack removed check
|
||||
|
||||
* audio
|
||||
* animation effects
|
||||
* vbox combine / buy / equip etc
|
||||
|
||||
@ -27,6 +27,3 @@ ssh -q "$TARGET" ls -lah "$CLIENT_DIST_DIR"
|
||||
|
||||
echo "restarting mnml service"
|
||||
ssh -q -t "$TARGET" sudo service mnml restart && sleep 1 && systemctl --no-pager status mnml
|
||||
|
||||
echo "restarting nginx service"
|
||||
ssh -q -t "$TARGET" sudo service nginx restart && sleep 1 && systemctl --no-pager status nginx
|
||||
|
||||
@ -65,7 +65,7 @@ impl ConstructSkill {
|
||||
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
||||
pub enum EffectMeta {
|
||||
CastOnHit(Skill), // maybe needs source/target
|
||||
CastTick { source: Uuid, target: Uuid, skill: Skill, speed: usize, amount: usize },
|
||||
CastTick { source: Uuid, target: Uuid, skill: Skill, speed: usize, amount: usize, id: Uuid },
|
||||
AddedDamage(usize),
|
||||
Multiplier(usize),
|
||||
}
|
||||
@ -100,12 +100,19 @@ impl ConstructEffect {
|
||||
|
||||
pub fn get_skill(&self) -> Option<Skill> {
|
||||
match self.meta {
|
||||
Some(EffectMeta::CastTick { source: _, target: _, skill, speed: _, amount: _ }) => Some(skill),
|
||||
Some(EffectMeta::CastTick { source: _, target: _, skill, speed: _, amount: _, id: _ }) => Some(skill),
|
||||
Some(EffectMeta::CastOnHit(s)) => Some(s),
|
||||
_ => None,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn get_tick_id(&self) -> Option<Uuid> {
|
||||
match self.meta {
|
||||
Some(EffectMeta::CastTick { source: _, target: _, skill: _, speed: _, amount: _, id }) => Some(id),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
||||
@ -561,7 +568,7 @@ impl Construct {
|
||||
fn tick_damage(&self, effect: Effect) -> usize {
|
||||
match self.effects.iter().find_map(|ce| match ce.effect == effect {
|
||||
true => match ce.meta {
|
||||
Some(EffectMeta::CastTick { source: _, target: _, skill: _, speed: _, amount }) => Some(amount),
|
||||
Some(EffectMeta::CastTick { source: _, target: _, skill: _, speed: _, amount, id: _ }) => Some(amount),
|
||||
_ => None,
|
||||
},
|
||||
false => None,
|
||||
|
||||
137
core/src/game.rs
137
core/src/game.rs
@ -428,8 +428,12 @@ impl Game {
|
||||
.cloned()
|
||||
.filter_map(|e| e.meta)
|
||||
.filter_map(move |m| match m {
|
||||
EffectMeta::CastTick { source, target, skill, speed, amount: _ } =>
|
||||
Some(Cast::new(source, c.account, target, skill).set_speed(speed)),
|
||||
EffectMeta::CastTick { source, target, skill, speed, amount: _, id } =>
|
||||
Some(
|
||||
Cast::new(source, c.account, target, skill)
|
||||
.set_speed(speed)
|
||||
.set_id(id)
|
||||
),
|
||||
_ => None,
|
||||
})
|
||||
)
|
||||
@ -506,6 +510,20 @@ impl Game {
|
||||
fn resolve(&mut self, cast: Cast) -> &mut Game {
|
||||
if self.finished() { return self }
|
||||
|
||||
// match tick skills with the effect on the target
|
||||
// if no match is found the effect must have been removed during this turn
|
||||
// and the skill should no longer resolve
|
||||
if cast.skill.is_tick() {
|
||||
let effect_match = self.construct(cast.target).effects.iter()
|
||||
.filter_map(|ce| ce.get_tick_id())
|
||||
.find(|id| cast.id == *id)
|
||||
.is_some();
|
||||
|
||||
if !effect_match {
|
||||
return self;
|
||||
}
|
||||
}
|
||||
|
||||
// If the skill is disabled for source nothing else will happen
|
||||
if let Some(effects) = self.construct(cast.source).disabled(cast.skill) {
|
||||
self.add_resolution(&cast, &Event::Disable { construct: cast.source, effects });
|
||||
@ -1054,6 +1072,7 @@ mod tests {
|
||||
.learn(Skill::Block)
|
||||
.learn(Skill::Counter)
|
||||
.learn(Skill::Siphon)
|
||||
.learn(Skill::Purify)
|
||||
.learn(Skill::Amplify)
|
||||
.learn(Skill::Stun)
|
||||
.learn(Skill::Ruin)
|
||||
@ -1069,6 +1088,7 @@ mod tests {
|
||||
.learn(Skill::Block)
|
||||
.learn(Skill::Counter)
|
||||
.learn(Skill::Siphon)
|
||||
.learn(Skill::Purify)
|
||||
.learn(Skill::Amplify)
|
||||
.learn(Skill::Stun)
|
||||
.learn(Skill::Block);
|
||||
@ -1874,85 +1894,6 @@ mod tests {
|
||||
return;
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn tick_removal_test() {
|
||||
// let mut game = create_test_game();
|
||||
|
||||
// let x_player = game.players[0].clone();
|
||||
// let y_player = game.players[1].clone();
|
||||
|
||||
// let x_construct = x_player.constructs[0].clone();
|
||||
// let y_construct = y_player.constructs[0].clone();
|
||||
|
||||
// // make the purify construct super fast so it beats out decay
|
||||
// game.construct_by_id(y_construct.id).unwrap().speed.force(10000000);
|
||||
|
||||
// game.construct_by_id(x_construct.id).unwrap().learn_mut(Skill::Decay);
|
||||
// while game.construct_by_id(x_construct.id).unwrap().skill_on_cd(Skill::Decay).is_some() {
|
||||
// game.construct_by_id(x_construct.id).unwrap().reduce_cooldowns();
|
||||
// }
|
||||
|
||||
// game.construct_by_id(x_construct.id).unwrap().learn_mut(Skill::Siphon);
|
||||
// while game.construct_by_id(x_construct.id).unwrap().skill_on_cd(Skill::Siphon).is_some() {
|
||||
// game.construct_by_id(x_construct.id).unwrap().reduce_cooldowns();
|
||||
// }
|
||||
|
||||
// game.construct_by_id(y_construct.id).unwrap().learn_mut(Skill::Purify);
|
||||
// while game.construct_by_id(y_construct.id).unwrap().skill_on_cd(Skill::Purify).is_some() {
|
||||
// game.construct_by_id(y_construct.id).unwrap().reduce_cooldowns();
|
||||
// }
|
||||
|
||||
// // apply buff
|
||||
// game.add_skill(x_player.id, x_construct.id, y_construct.id, Skill::Decay).unwrap();
|
||||
// game.player_ready(x_player.id).unwrap();
|
||||
// game.player_ready(y_player.id).unwrap();
|
||||
// game = game.resolve_phase_start();
|
||||
// assert!(game.construct_by_id(y_construct.id).unwrap().affected(Effect::Decay));
|
||||
|
||||
// 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.Resolutions.clear();
|
||||
|
||||
// // remove
|
||||
// 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(Resolution { source: _, target: _, Resolution, stages: _ }) = game.Resolutions.last().unwrap().pop() {
|
||||
// match Resolution {
|
||||
// Resolution::Damage { amount: _, skill: _, mitigation: _, colour: _ } =>
|
||||
// panic!("{:?} damage Resolution", Resolution),
|
||||
// _ => (),
|
||||
// }
|
||||
// };
|
||||
|
||||
// game.add_skill(y_player.id, x_construct.id, y_construct.id, Skill::Siphon).unwrap();
|
||||
// game.player_ready(x_player.id).unwrap();
|
||||
// game.player_ready(y_player.id).unwrap();
|
||||
// game = game.resolve_phase_start();
|
||||
|
||||
// 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(Resolution { source: _, target: _, Resolution, stages: _ }) = game.Resolutions.last().unwrap().pop() {
|
||||
// match Resolution {
|
||||
// Resolution::Damage { amount: _, skill: _, mitigation: _, colour: _ } =>
|
||||
// panic!("{:#?} {:#?} damage Resolution", game.Resolutions, Resolution),
|
||||
// _ => (),
|
||||
// }
|
||||
// };
|
||||
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn upkeep_test() {
|
||||
let mut game = create_2v2_test_game();
|
||||
@ -2524,4 +2465,38 @@ mod tests {
|
||||
assert_eq!(siphon_tick_dmg, siphon_dmg);
|
||||
assert_eq!(siphon_tick_speed, siphon_speed);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tick_removal_test() {
|
||||
let mut game = create_test_game();
|
||||
let player_id = game.players[0].id;
|
||||
let opponent_id = game.players[1].id;
|
||||
let source = game.players[0].constructs[0].id;
|
||||
let target = game.players[1].constructs[0].id;
|
||||
|
||||
game.add_skill(player_id, source, target, Skill::Siphon).unwrap();
|
||||
|
||||
game.player_ready(player_id).unwrap();
|
||||
game.player_ready(opponent_id).unwrap();
|
||||
|
||||
game = game.resolve_phase_start();
|
||||
|
||||
game.add_skill(player_id, source, target, Skill::Purify).unwrap();
|
||||
|
||||
game.player_ready(player_id).unwrap();
|
||||
game.player_ready(opponent_id).unwrap();
|
||||
|
||||
game = game.resolve_phase_start();
|
||||
|
||||
// println!("{:#?}", game.resolutions);
|
||||
|
||||
let last = game.resolutions.len() - 1;
|
||||
let resolutions = &game.resolutions[last];
|
||||
|
||||
// There should be no damage events on the target
|
||||
assert!(resolutions.iter().any(|r| match r.event {
|
||||
Event::Damage { construct: _, colour: _, amount: _, mitigation: _, display: _ } => true,
|
||||
_ => false,
|
||||
}) == false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,6 +41,15 @@ impl Cast {
|
||||
}
|
||||
}
|
||||
|
||||
// used for ticks to match
|
||||
// a cast with an effect
|
||||
pub fn set_id(self, id: Uuid) -> Cast {
|
||||
Cast {
|
||||
id,
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve(self, game: &mut Game) {
|
||||
match self.skill {
|
||||
Skill::Attack => attack(self, game, Attack::Base),
|
||||
@ -1134,7 +1143,7 @@ fn siphon(cast: Cast, game: &mut Game, values: Siphon) {
|
||||
Action::Effect {
|
||||
construct: cast.target,
|
||||
effect: ConstructEffect { effect: Effect::Siphon, duration: values.duration(), meta:
|
||||
Some(EffectMeta::CastTick { source: cast.source, target: cast.target, skill: Skill::SiphonTick, speed: cast.speed, amount }) },
|
||||
Some(EffectMeta::CastTick { id: Uuid::new_v4(), source: cast.source, target: cast.target, skill: Skill::SiphonTick, speed: cast.speed, amount }) },
|
||||
}
|
||||
);
|
||||
|
||||
@ -1729,7 +1738,7 @@ fn decay(cast: Cast, game: &mut Game, values: Decay) {
|
||||
Action::Effect {
|
||||
construct: cast.target,
|
||||
effect: ConstructEffect { effect: Effect::Decay, duration: values.decay_duration(), meta:
|
||||
Some(EffectMeta::CastTick { source: cast.source, target: cast.target, skill: Skill::DecayTick, speed: cast.speed, amount }) },
|
||||
Some(EffectMeta::CastTick { id: Uuid::new_v4(), source: cast.source, target: cast.target, skill: Skill::DecayTick, speed: cast.speed, amount }) },
|
||||
}
|
||||
);
|
||||
|
||||
@ -1837,10 +1846,10 @@ fn electrocute(cast: Cast, game: &mut Game, values: Electrocute) {
|
||||
Action::Effect {
|
||||
construct: cast.target,
|
||||
effect: ConstructEffect { effect: Effect::Electrocute, duration: values.duration(), meta:
|
||||
Some(EffectMeta::CastTick { source: cast.source, target: cast.target, skill: Skill::ElectrocuteTick, speed: cast.speed, amount }) },
|
||||
Some(EffectMeta::CastTick { id: Uuid::new_v4(), source: cast.source, target: cast.target, skill: Skill::ElectrocuteTick, speed: cast.speed, amount }) },
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
if !game.affected(cast.target, Effect::Electrocuted) {
|
||||
game.action(cast,
|
||||
Action::Damage {
|
||||
@ -2362,7 +2371,7 @@ fn triage(cast: Cast, game: &mut Game, values: Triage) {
|
||||
Action::Effect {
|
||||
construct: cast.target,
|
||||
effect: ConstructEffect { effect: Effect::Triage, duration: values.duration(), meta:
|
||||
Some(EffectMeta::CastTick { source: cast.source, target: cast.target, skill: Skill::TriageTick, speed: cast.speed, amount }) },
|
||||
Some(EffectMeta::CastTick { id: Uuid::new_v4(), source: cast.source, target: cast.target, skill: Skill::TriageTick, speed: cast.speed, amount }) },
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@ -109,6 +109,7 @@ pub fn start() {
|
||||
#[cfg(unix)]
|
||||
setup_logger().unwrap();
|
||||
dotenv::from_path(Path::new("/etc/mnml/gs.conf")).ok();
|
||||
info!("starting server");
|
||||
|
||||
let pool = pg::create_pool();
|
||||
let http_pool = pool.clone();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user