fix(rules): preserve lock holes when arming effect seven
Record 148 writes player item 20 and its own type-three contact sentinel. It does not clear lock-hole items or contacts 129 through 133; the panel completion path owns that reset. Rust treated record 148 as a wheel-reset sensor and erased all five lock holes immediately. Rename the recovered mechanism to the special/effect-seven hole and preserve existing lock progress when it is captured. Keep its multiball-ready state, contact 2 publication, and later special-respawn suppression unchanged. Test Plan: - `cargo test --workspace --all-targets --all-features` -- 120 passed - `cargo clippy --workspace --all-targets --all-features -- -D warnings` -- passed - `rumdl check --flavor commonmark RECONSTRUCTION.md CHANGELOG.md` -- passed - `git diff --cached --check` -- passed
This commit is contained in:
+26
-25
@@ -11,7 +11,7 @@ use crate::{
|
||||
real48::Real48,
|
||||
table::{
|
||||
BUMPERS, EFFECT_SENSOR, LOCK_HOLES, PASSIVE_CIRCLES, TARGET_SENSORS, WALLS,
|
||||
WHEEL_RESET_SENSOR,
|
||||
SPECIAL_HOLE_SENSOR,
|
||||
},
|
||||
};
|
||||
use macroquad::prelude::{Rect, Vec2, vec2};
|
||||
@@ -228,7 +228,7 @@ enum BallDoubleState {
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||
enum WheelResetGate {
|
||||
enum SpecialHoleGate {
|
||||
#[default]
|
||||
Enabled,
|
||||
Suppressed,
|
||||
@@ -354,7 +354,7 @@ pub struct Game {
|
||||
target_effect: u8,
|
||||
claw_frame_seconds: f32,
|
||||
multiball_state: MultiballState,
|
||||
wheel_reset_gate: WheelResetGate,
|
||||
special_hole_gate: SpecialHoleGate,
|
||||
score_mode: ScoreMode,
|
||||
ball_double: BallDoubleState,
|
||||
}
|
||||
@@ -398,7 +398,7 @@ impl Game {
|
||||
target_effect: 0,
|
||||
claw_frame_seconds: CLAW_FRAME_SECONDS,
|
||||
multiball_state: MultiballState::Unavailable,
|
||||
wheel_reset_gate: WheelResetGate::Enabled,
|
||||
special_hole_gate: SpecialHoleGate::Enabled,
|
||||
score_mode: ScoreMode::Normal,
|
||||
ball_double: BallDoubleState::Inactive,
|
||||
}
|
||||
@@ -986,7 +986,7 @@ impl Game {
|
||||
EFFECT_SENSOR.radius,
|
||||
))
|
||||
{
|
||||
self.wheel_reset_gate = WheelResetGate::Enabled;
|
||||
self.special_hole_gate = SpecialHoleGate::Enabled;
|
||||
}
|
||||
self.check_target_sensors(
|
||||
ball,
|
||||
@@ -995,7 +995,7 @@ impl Game {
|
||||
140..=147,
|
||||
events,
|
||||
);
|
||||
if let Some(completed_action) = self.check_wheel_reset(
|
||||
if let Some(completed_action) = self.check_special_hole(
|
||||
ball,
|
||||
ball_number,
|
||||
ball_count,
|
||||
@@ -1458,7 +1458,7 @@ impl Game {
|
||||
EFFECT_SENSOR.radius,
|
||||
))
|
||||
{
|
||||
self.wheel_reset_gate = WheelResetGate::Enabled;
|
||||
self.special_hole_gate = SpecialHoleGate::Enabled;
|
||||
}
|
||||
if old_position.y >= 250_000 {
|
||||
return SensorScanResult {
|
||||
@@ -1512,7 +1512,7 @@ impl Game {
|
||||
events,
|
||||
);
|
||||
if let Some(completed_action) =
|
||||
self.check_wheel_reset(
|
||||
self.check_special_hole(
|
||||
ball,
|
||||
ball_number,
|
||||
ball_count,
|
||||
@@ -1583,7 +1583,7 @@ impl Game {
|
||||
|
||||
if surface_distance < -11_000
|
||||
&& contact_allowed
|
||||
&& !(record_id == 148 && self.wheel_reset_gate == WheelResetGate::Suppressed)
|
||||
&& !(record_id == 148 && self.special_hole_gate == SpecialHoleGate::Suppressed)
|
||||
{
|
||||
if ball.capture_age < 300 {
|
||||
let mut velocity = MilliVec::from_velocity_per_second(ball.velocity);
|
||||
@@ -1720,7 +1720,7 @@ impl Game {
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn check_wheel_reset(
|
||||
fn check_special_hole(
|
||||
&mut self,
|
||||
ball: &mut Ball,
|
||||
ball_number: u16,
|
||||
@@ -1734,9 +1734,9 @@ impl Game {
|
||||
ball,
|
||||
ball_number,
|
||||
ball_count,
|
||||
WHEEL_RESET_SENSOR.id,
|
||||
WHEEL_RESET_SENSOR.center,
|
||||
WHEEL_RESET_SENSOR.radius,
|
||||
SPECIAL_HOLE_SENSOR.id,
|
||||
SPECIAL_HOLE_SENSOR.center,
|
||||
SPECIAL_HOLE_SENSOR.radius,
|
||||
old_position,
|
||||
predicted_position,
|
||||
best_capture,
|
||||
@@ -1745,7 +1745,6 @@ impl Game {
|
||||
CaptureStep::Outside | CaptureStep::Holding => return None,
|
||||
CaptureStep::Complete => {}
|
||||
}
|
||||
self.wheel_holes.fill(false);
|
||||
self.multiball_state = MultiballState::Ready;
|
||||
events.push(Event::Wheel);
|
||||
Some(if ball_count == 1 {
|
||||
@@ -1906,7 +1905,7 @@ impl Game {
|
||||
{
|
||||
return false;
|
||||
}
|
||||
self.wheel_reset_gate = WheelResetGate::Enabled;
|
||||
self.special_hole_gate = SpecialHoleGate::Enabled;
|
||||
let damping = Real48::from_bytes([0x80, 0x66, 0x66, 0x66, 0x66, 0x66]);
|
||||
velocity.x = Real48::from_i32(velocity.x).multiply(damping).round_i32();
|
||||
let vertical_factor = Real48::from_i32(1).subtract(
|
||||
@@ -2085,11 +2084,11 @@ impl Game {
|
||||
};
|
||||
self.multiball_state = MultiballState::Unavailable;
|
||||
self.record_contacts[148] = 0;
|
||||
self.wheel_reset_gate = WheelResetGate::Suppressed;
|
||||
self.special_hole_gate = SpecialHoleGate::Suppressed;
|
||||
return;
|
||||
}
|
||||
self.ball_double = BallDoubleState::Inactive;
|
||||
self.wheel_reset_gate = WheelResetGate::Enabled;
|
||||
self.special_hole_gate = SpecialHoleGate::Enabled;
|
||||
let player = &mut self.players[self.current_player];
|
||||
if player.extra_balls > 0 {
|
||||
player.extra_balls -= 1;
|
||||
@@ -2776,7 +2775,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wheel_reset_arms_effect_seven_multiball() {
|
||||
fn special_hole_arms_effect_seven_multiball() {
|
||||
let mut game = Game::new_with_seed(1, 7);
|
||||
let mut events = Vec::new();
|
||||
game.multiball_state = MultiballState::Ready;
|
||||
@@ -2824,7 +2823,7 @@ mod tests {
|
||||
);
|
||||
assert_eq!(game.multiball_state, MultiballState::Unavailable);
|
||||
assert_eq!(game.record_contacts[148], 0);
|
||||
assert_eq!(game.wheel_reset_gate, WheelResetGate::Suppressed);
|
||||
assert_eq!(game.special_hole_gate, SpecialHoleGate::Suppressed);
|
||||
|
||||
game.fixed_update(&mut events);
|
||||
assert!(!game.ball.in_launcher);
|
||||
@@ -2842,12 +2841,12 @@ mod tests {
|
||||
y: 3_055,
|
||||
}
|
||||
);
|
||||
assert_eq!(game.wheel_reset_gate, WheelResetGate::Suppressed);
|
||||
assert_eq!(game.special_hole_gate, SpecialHoleGate::Suppressed);
|
||||
|
||||
game.ball.position = vec2(17.0, 31.0);
|
||||
game.ball.velocity = Vec2::ZERO;
|
||||
game.fixed_update(&mut events);
|
||||
assert_eq!(game.wheel_reset_gate, WheelResetGate::Enabled);
|
||||
assert_eq!(game.special_hole_gate, SpecialHoleGate::Enabled);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -2875,7 +2874,7 @@ mod tests {
|
||||
}
|
||||
);
|
||||
assert_eq!(game.multiball_state, MultiballState::Unavailable);
|
||||
assert_eq!(game.wheel_reset_gate, WheelResetGate::Suppressed);
|
||||
assert_eq!(game.special_hole_gate, SpecialHoleGate::Suppressed);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -2893,7 +2892,7 @@ mod tests {
|
||||
assert_eq!(game.ball.position, vec2(17.0, 23.0));
|
||||
assert_eq!(game.multiball_state, MultiballState::Unavailable);
|
||||
assert_eq!(game.record_contacts[148], 0);
|
||||
assert_eq!(game.wheel_reset_gate, WheelResetGate::Suppressed);
|
||||
assert_eq!(game.special_hole_gate, SpecialHoleGate::Suppressed);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -3901,10 +3900,12 @@ mod tests {
|
||||
|
||||
complete_stationary_type_three_capture(
|
||||
&mut game,
|
||||
WHEEL_RESET_SENSOR.center,
|
||||
SPECIAL_HOLE_SENSOR.center,
|
||||
&mut events,
|
||||
);
|
||||
assert!(game.wheel_holes.iter().all(|filled| !*filled));
|
||||
assert!(game.wheel_holes.iter().all(|filled| *filled));
|
||||
assert_eq!(game.multiball_state, MultiballState::Ready);
|
||||
assert_eq!(game.record_contacts[148], 2);
|
||||
assert_eq!(events.last(), Some(&Event::Wheel));
|
||||
assert_eq!(
|
||||
events
|
||||
|
||||
Reference in New Issue
Block a user