From c2ad3dd6430ec0b23ba749fc3f9a15d692e9c215 Mon Sep 17 00:00:00 2001 From: periwinkle Date: Wed, 27 Sep 2023 22:14:26 -0400 Subject: [PATCH] Accuracy fixes for Waterway through Hell (#237) * Accuracy fixes for Waterway through Balcony * Hell accuracy fixes --- src/game/npc/ai/balcony.rs | 12 +++++++++- src/game/npc/ai/doctor.rs | 20 ++++++++-------- src/game/npc/ai/hell.rs | 4 ++-- src/game/npc/ai/igor.rs | 7 +++--- src/game/npc/ai/last_cave.rs | 17 ++++++++++---- src/game/npc/ai/misery.rs | 17 ++++++++------ src/game/npc/ai/plantation.rs | 10 ++++---- src/game/npc/boss/ballos.rs | 39 ++++++++++++++++++++------------ src/game/npc/boss/heavy_press.rs | 3 ++- src/game/npc/boss/ironhead.rs | 28 ++++++++++++----------- src/game/npc/boss/undead_core.rs | 14 ++++++++---- src/game/npc/mod.rs | 2 +- 12 files changed, 104 insertions(+), 69 deletions(-) diff --git a/src/game/npc/ai/balcony.rs b/src/game/npc/ai/balcony.rs index 51510cc..15fb44b 100644 --- a/src/game/npc/ai/balcony.rs +++ b/src/game/npc/ai/balcony.rs @@ -64,7 +64,7 @@ impl NPC { let _ = npc_list.spawn(0x100, npc); // chaco - let mut npc = NPC::create(223, &state.npc_table); + let mut npc = NPC::create(93, &state.npc_table); npc.cond.set_alive(true); npc.x = self.x - 0x4600; npc.y = self.y - 0x1c00; @@ -116,6 +116,16 @@ impl NPC { _ => (), } + if let Some(parent) = self.get_parent_ref_mut(npc_list) { + if self.direction == Direction::Left { + self.x = parent.x + 0x2400; + self.y = parent.y - 0x7200; + } else { + self.x = parent.x - 0x4000; + self.y = parent.y - 0x6800; + } + } + let dir_offset = if self.direction == Direction::Left { 0 } else { 4 }; self.anim_rect = state.constants.npc.n255_helicopter_blades[self.anim_num as usize + dir_offset]; diff --git a/src/game/npc/ai/doctor.rs b/src/game/npc/ai/doctor.rs index 7d81898..feca767 100644 --- a/src/game/npc/ai/doctor.rs +++ b/src/game/npc/ai/doctor.rs @@ -364,8 +364,8 @@ impl NPC { npc.y = self.y; for i in (8..256).step_by(16) { - npc.vel_x = ((i as f64 * CDEG_RAD).cos() * -1024.0) as i32; - npc.vel_y = ((i as f64 * CDEG_RAD).sin() * -1024.0) as i32; + npc.vel_x = ((i as f64 * CDEG_RAD).cos() * 1024.0) as i32; + npc.vel_y = ((i as f64 * CDEG_RAD).sin() * 1024.0) as i32; let _ = npc_list.spawn(0x100, npc.clone()); } @@ -375,7 +375,6 @@ impl NPC { self.action_counter += 1; if self.action_counter > 50 { self.action_num = 100; - self.anim_num = 0; } } 100 | 101 => { @@ -507,8 +506,8 @@ impl NPC { self.target_x += self.vel_x; let angle = self.action_counter2 as f64 * CDEG_RAD; - self.x = self.target_x + self.action_counter as i32 * (angle.cos() * -512.0) as i32 / 8; - self.y = self.target_y + self.action_counter as i32 * (angle.sin() * -512.0) as i32 / 2; + self.x = self.target_x + self.action_counter as i32 * (angle.cos() * 512.0) as i32 / 8; + self.y = self.target_y + self.action_counter as i32 * (angle.sin() * 512.0) as i32 / 2; let mut npc = NPC::create(265, &state.npc_table); npc.cond.set_alive(true); @@ -652,7 +651,7 @@ impl NPC { self.direction = if self.x > player.x { Direction::Left } else { Direction::Right }; if self.flags.hit_bottom_wall() { - if self.life + 20 > self.action_counter3 { + if self.life + 20 >= self.action_counter3 { self.animate(10, 1, 2); } else if player.flags.hit_bottom_wall() && player.x > self.x - 0x6000 && player.x < self.x + 0x6000 && self.anim_num != 6 { @@ -900,9 +899,8 @@ impl NPC { } } 103 => { - if self.action_counter > 0 { - self.action_counter -= 2; - } else { + self.action_counter = self.action_counter.saturating_sub(2); + if self.action_counter == 0 { self.action_num = 16; self.vel_x = 0; self.vel_y = -0x200; @@ -936,7 +934,7 @@ impl NPC { if self.action_counter / 2 % 2 != 0 { self.x = self.target_x; } else { - self.x = self.x.wrapping_add(0x200); + self.x = self.target_x.wrapping_add(0x200); } } 510 | 511 => { @@ -1072,7 +1070,7 @@ impl NPC { self.x += self.vel_x; self.y += self.vel_y; - if self.action_counter > 50 || self.flags.any_flag() { + if self.action_counter > 50 || self.flags.hit_anything() { self.cond.set_alive(false) } } else if self.direction == Direction::Right { diff --git a/src/game/npc/ai/hell.rs b/src/game/npc/ai/hell.rs index 8e99e24..a9730a1 100644 --- a/src/game/npc/ai/hell.rs +++ b/src/game/npc/ai/hell.rs @@ -83,7 +83,7 @@ impl NPC { self.action_num = 1; if (self.direction == Direction::Left && player.x > self.x - 0x24000 && player.x < self.x - 0x22000) - || (player.x < self.x + 0x24000 && player.x > self.x + 0x22000) + || (self.direction != Direction::Left && player.x < self.x + 0x24000 && player.x > self.x + 0x22000) { self.action_num = 10; } @@ -730,7 +730,7 @@ impl NPC { _ => (), } - self.animate(1, 0, 2); + self.animate(0, 0, 2); self.anim_rect = state.constants.npc.n319_mesa_block[self.anim_num as usize]; Ok(()) diff --git a/src/game/npc/ai/igor.rs b/src/game/npc/ai/igor.rs index 49db62a..897ec05 100644 --- a/src/game/npc/ai/igor.rs +++ b/src/game/npc/ai/igor.rs @@ -280,6 +280,7 @@ impl NPC { 0 | 1 => { if self.action_num == 0 { self.action_num = 1; + state.sound_manager.play_sfx(72); let player = self.get_closest_player_mut(players); self.direction = if self.x > player.x { Direction::Left } else { Direction::Right }; @@ -428,7 +429,7 @@ impl NPC { self.action_counter = 0; self.anim_num = 0; self.action_counter = 0; - self.direction = if self.x < player.x { Direction::Right } else { Direction::Left }; + self.direction = if self.x <= player.x { Direction::Right } else { Direction::Left }; } self.vel_x = self.direction.vector_x() * 0x200; @@ -495,8 +496,8 @@ impl NPC { let deg = (if self.direction == Direction::Left { 0x88 } else { 0xf8 } + self.rng.range(-16..16)) as f64 * CDEG_RAD; - let vel_x = (deg.cos() * 1536.0) as i32; - let vel_y = (deg.sin() * 1536.0) as i32; + let vel_x = (deg.cos() * 2560.0) as i32; + let vel_y = (deg.sin() * 2560.0) as i32; let mut npc = NPC::create(11, &state.npc_table); diff --git a/src/game/npc/ai/last_cave.rs b/src/game/npc/ai/last_cave.rs index c6df8c0..6c25a0d 100644 --- a/src/game/npc/ai/last_cave.rs +++ b/src/game/npc/ai/last_cave.rs @@ -5,6 +5,7 @@ use crate::game::npc::list::NPCList; use crate::game::npc::NPC; use crate::game::player::Player; use crate::game::shared_game_state::SharedGameState; +use crate::game::stage::Stage; use crate::util::rng::RNG; impl NPC { @@ -103,7 +104,11 @@ impl NPC { Ok(()) } - pub(crate) fn tick_n242_bat_last_cave(&mut self, state: &mut SharedGameState) -> GameResult { + pub(crate) fn tick_n242_bat_last_cave(&mut self, state: &mut SharedGameState, stage: &mut Stage) -> GameResult { + if self.x < 0 || self.x > stage.map.width as i32 * state.tile_size.as_int() * 0x200 { + self.vanish(state); + return Ok(()); + } loop { match self.action_num { 0 => { @@ -183,7 +188,7 @@ impl NPC { if hit { for _ in 0..3 { - state.create_caret(self.x, self.y, CaretType::Bubble, Direction::Right); + state.create_caret(self.x, self.y + 0x800, CaretType::Bubble, Direction::Right); } let player = self.get_closest_player_ref(&players); @@ -289,7 +294,7 @@ impl NPC { 10 | 11 => { if self.action_num == 10 { self.action_num = 11; - self.anim_num = 2; + self.anim_num = 3; self.action_counter = 0; self.npc_flags.set_shootable(true); } @@ -297,6 +302,7 @@ impl NPC { self.action_counter += 1; match self.action_counter { 30 | 40 | 50 => { + self.anim_num = 4; let player = self.get_closest_player_ref(&players); let mut npc = NPC::create(277, &state.npc_table); @@ -341,14 +347,15 @@ impl NPC { self.action_counter += 1; match self.action_counter { 30 | 40 | 50 => { + self.anim_num = 6; let player = self.get_closest_player_ref(&players); let mut npc = NPC::create(277, &state.npc_table); npc.cond.set_alive(true); npc.x = self.x; - npc.y = self.y; + npc.y = self.y - 0x1400; - let angle = f64::atan2((self.y - player.y) as f64, (self.x - player.x) as f64); + let angle = f64::atan2((self.y - 0x1400 - player.y) as f64, (self.x - player.x) as f64); npc.vel_x = (-2048.0 * angle.cos()) as i32; npc.vel_y = (-2048.0 * angle.sin()) as i32; diff --git a/src/game/npc/ai/misery.rs b/src/game/npc/ai/misery.rs index 5ca8fb4..f07b40e 100644 --- a/src/game/npc/ai/misery.rs +++ b/src/game/npc/ai/misery.rs @@ -25,8 +25,8 @@ impl NPC { self.target_y = npc.y; let angle = ((self.y - self.target_y) as f64 / (self.x - self.target_x) as f64).atan(); - self.vel_x = (angle.cos() * 1024.0) as i32; - self.vel_y = (angle.sin() * 1024.0) as i32; + self.vel_x = (angle.cos() * -1024.0) as i32; + self.vel_y = (angle.sin() * -1024.0) as i32; } if self.action_counter2 == 0 { @@ -144,6 +144,7 @@ impl NPC { npc.cond.set_alive(true); npc.x = self.x; npc.y = self.y - 0x2000; + npc.parent_id = self.id; // This NPC doesn't do anything with its parent...but we'll set it anyways let _ = npc_list.spawn(0, npc); } @@ -270,6 +271,7 @@ impl NPC { let mut npc = NPC::create(66, &state.npc_table); npc.x = self.x; npc.y = self.y - 0x2000; + npc.parent_id = self.id; // This NPC doesn't do anything with its parent...but we'll set it anyways npc.cond.set_alive(true); let _ = npc_list.spawn(0, npc); @@ -612,7 +614,7 @@ impl NPC { } let player = self.get_closest_player_ref(&players); - self.action_num = if player.x > self.x - 0xe000 && player.x <= self.x + 0xe000 { 100 } else { 160 }; + self.action_num = if player.x >= self.x - 0xe000 && player.x <= self.x + 0xe000 { 100 } else { 160 }; } } 160 | 161 => { @@ -701,7 +703,7 @@ impl NPC { } pub(crate) fn tick_n248_misery_boss_vanishing(&mut self, state: &mut SharedGameState) -> GameResult { - if self.flags.any_flag() { + if self.flags.hit_anything() { self.cond.set_alive(false); state.create_caret(self.x, self.y, CaretType::ProjectileDissipation, Direction::Left); } @@ -815,7 +817,7 @@ impl NPC { self.anim_num = (self.anim_num + 1) & 1; self.y += 0x1000; - if self.flags.any_flag() { + if self.flags.hit_anything() { npc_list.create_death_smoke(self.x, self.y, self.display_bounds.right as usize, 3, state, &self.rng); self.cond.set_alive(false); } @@ -849,10 +851,10 @@ impl NPC { if let Some(parent) = self.get_parent_ref_mut(npc_list) { self.x = parent.x - + self.action_counter as i32 * ((self.action_counter2 as f64 * CDEG_RAD).cos() * -512.0) as i32 + + self.action_counter as i32 * ((self.action_counter2 as f64 * CDEG_RAD).cos() * 512.0) as i32 / 4; self.y = parent.y - + self.action_counter as i32 * ((self.action_counter2 as f64 * CDEG_RAD).sin() * -512.0) as i32 + + self.action_counter as i32 * ((self.action_counter2 as f64 * CDEG_RAD).sin() * 512.0) as i32 / 4; if parent.action_num == 151 { @@ -1198,6 +1200,7 @@ impl NPC { if self.y > stage.map.height as i32 * state.tile_size.as_int() * 0x200 { self.vanish(state); + return Ok(()); } } _ => (), diff --git a/src/game/npc/ai/plantation.rs b/src/game/npc/ai/plantation.rs index f68e81f..4f5e387 100644 --- a/src/game/npc/ai/plantation.rs +++ b/src/game/npc/ai/plantation.rs @@ -537,8 +537,8 @@ impl NPC { 0 | 1 => { if self.action_num == 0 { self.action_num = 1; - self.vel_x = ((self.rng.range(0..255) as f64 * CDEG_RAD).cos() * -512.0) as i32; - self.vel_y = ((self.rng.range(0..255) as f64 * CDEG_RAD).sin() * -512.0) as i32; + self.vel_x = ((self.rng.range(0..255) as f64 * CDEG_RAD).cos() * 512.0) as i32; + self.vel_y = ((self.rng.range(0..255) as f64 * CDEG_RAD).sin() * 512.0) as i32; self.action_counter2 = 120; self.vel_y2 = self.rng.range(-32..32) * 0x200; @@ -902,7 +902,7 @@ impl NPC { self.x += self.vel_x; self.y += self.vel_y; - if self.flags.any_flag() { + if self.flags.hit_anything() { let mut npc = NPC::create(4, &state.npc_table); npc.cond.set_alive(true); npc.x = self.x; @@ -994,9 +994,9 @@ impl NPC { let mut npc = NPC::create(273, &state.npc_table); npc.cond.set_alive(true); npc.x = self.x; - npc.y = self.y; + npc.y = self.y - 0x1400; - let angle = f64::atan2((player.y - 0x1400 - self.y) as f64, (player.x - self.x) as f64); + let angle = f64::atan2((player.y + 0x1400 - self.y) as f64, (player.x - self.x) as f64); npc.vel_x = (2048.0 * angle.cos()) as i32; npc.vel_y = (2048.0 * angle.sin()) as i32; diff --git a/src/game/npc/boss/ballos.rs b/src/game/npc/boss/ballos.rs index 1610db3..5e6183a 100644 --- a/src/game/npc/boss/ballos.rs +++ b/src/game/npc/boss/ballos.rs @@ -40,7 +40,7 @@ impl NPC { self.anim_counter = 0; let anim = self.anim_num as i32 + (self.direction.vector_x() * -1); if anim < 0 { - self.anim_num = 4; + self.anim_num = 3; } else if anim > 3 { self.anim_num = 0; } else { @@ -106,7 +106,7 @@ impl NPC { state.sound_manager.play_sfx(103); } self.action_counter += 1; - self.anim_num = (self.action_counter + 1) % 2; + self.anim_num = 1 - (self.action_counter & 2) / 2; if self.direction == Direction::Left && self.action_counter == 20 { let mut npc = NPC::create(146, &state.npc_table); npc.cond.set_alive(true); @@ -149,8 +149,8 @@ impl NPC { if self.x < 0 || self.y < 0 - || self.x > (stage.map.width as i32) * state.tile_size.as_int() * 0x200 + 0x4000 - || self.y > (stage.map.height as i32) * state.tile_size.as_int() * 0x200 + 0x4000 + || self.x > (stage.map.width as i32) * state.tile_size.as_int() * 0x200 + || self.y > (stage.map.height as i32) * state.tile_size.as_int() * 0x200 { self.vanish(state); return Ok(()); @@ -304,6 +304,7 @@ impl NPC { self.action_counter = 0; self.anim_num = 6; self.anim_counter = 0; + self.vel_y = 0; self.damage = 10; self.face_player(player); @@ -352,6 +353,7 @@ impl NPC { } self.vel_y = if self.action_num == 221 { -0x800 } else { 0x800 }; + self.action_counter += 1; self.anim_num = if self.action_counter & 0x02 != 0 { 8 } else { 9 }; if (self.y < 0x6000 && self.action_num == 221) @@ -524,11 +526,12 @@ impl NPC { // I think Pixel meant for the smoke radius to be 16 pixels (0x2000) instead of 16 units, // because as it is, this just gets divided by 0x200 units/px and becomes 0 npc_list.create_death_smoke(self.x, self.y, 16, 16, state, &self.rng); + state.sound_manager.play_sfx(72); } self.vel_y += 0x20; self.clamp_fall_speed(); - self.action_counter; + self.action_counter += 1; self.x = self.target_x + if self.action_counter & 0x02 != 0 { 0x200 } else { -0x200 }; if self.flags.hit_bottom_wall() { self.action_num = 1002; @@ -950,7 +953,6 @@ impl NPC { self.npc_flags.set_ignore_solidity(false); } - self.action_counter += 1; if self.action_counter & 0x02 != 0 { let mut npc = NPC::create(4, &state.npc_table); npc.cond.set_alive(true); @@ -958,6 +960,7 @@ impl NPC { npc.y = self.y; let _ = npc_list.spawn(0x100, npc); } + self.action_counter += 1; // This gets incremented after the previous check for some reason if self.flags.hit_bottom_wall() { self.action_num = 110; @@ -981,7 +984,7 @@ impl NPC { 110 => { self.vel_y += 0x40; - if self.y > (stage.map.height as i32) * state.tile_size.as_int() * 0x200 + 0x4000 { + if self.y > (stage.map.height as i32 + 2) * state.tile_size.as_int() * 0x200 { self.cond.set_alive(false); return Ok(()); } @@ -1013,7 +1016,9 @@ impl NPC { 0 | 10 => { if self.action_num == 0 { self.action_num = 10; + // self.action_counter2 set by Ballos code, no need to set it here self.action_counter3 = 192; + self.vel_y2 = 0; } if self.action_counter3 >= 448 { self.action_num = 11; @@ -1069,6 +1074,7 @@ impl NPC { } } 100 => { + self.vel_y2 = 0; if boss.parts[0].action_num == 424 { self.action_num = 30; } else if boss.parts[0].action_num == 428 { @@ -1109,18 +1115,19 @@ impl NPC { match self.action_num { 20 | 30 => { if self.action_counter2 % 4 == 0 { - self.vel_y = (self.target_y - self.y) / 4; + self.vel_y2 = (self.target_y - self.y) / 4; } } 40 | 50 => { if self.action_counter2 & 0x02 == 0 { - self.vel_y = (self.target_y - self.y) / 2; + self.vel_y2 = (self.target_y - self.y) / 2; } } _ => { - self.vel_y = self.target_y - self.y; + self.vel_y2 = self.target_y - self.y; } } + self.vel_y = self.vel_y2; } self.x += self.vel_x; @@ -1391,7 +1398,9 @@ impl NPC { if stage.change_tile(x as usize, y as usize, 109) { npc.x = x * state.tile_size.as_int() * 0x200; npc.y = y * state.tile_size.as_int() * 0x200; - let _ = npc_list.spawn(0x100, npc.clone()); + let _ = npc_list.spawn(0, npc.clone()); + let _ = npc_list.spawn(0, npc.clone()); + let _ = npc_list.spawn(0, npc.clone()); } } } @@ -1680,7 +1689,7 @@ impl BossNPC { let mut npc = NPC::create(344, &state.npc_table); npc.cond.set_alive(true); npc.x = self.parts[0].x + 0x3000 * dir.vector_x(); - npc.y = self.parts[0].y + 0x4800; + npc.y = self.parts[0].y - 0x4800; npc.direction = dir; let _ = npc_list.spawn(0x20, npc); } @@ -1786,7 +1795,7 @@ impl BossNPC { let mut npc = NPC::create(344, &state.npc_table); npc.cond.set_alive(true); npc.x = self.parts[0].x + 0x3000 * dir.vector_x(); - npc.y = self.parts[0].y + 0x4800; + npc.y = self.parts[0].y - 0x4800; npc.direction = dir; let _ = npc_list.spawn(0x20, npc); } @@ -1808,7 +1817,7 @@ impl BossNPC { npc.cond.set_alive(true); npc.x = (((self.parts[0].action_counter as i32 / 30) * 2) + 2) * 0x2000; npc.y = 0x2A000; - let _ = npc_list.spawn(0x100, npc); + let _ = npc_list.spawn(0x180, npc); } if (self.parts[0].action_counter / 3 % 2) > 0 { @@ -1962,7 +1971,7 @@ impl BossNPC { npc.x = self.parts[0].x + self.parts[0].rng.range(-40..40) * 0x200; npc.y = self.parts[0].y + self.parts[0].rng.range(0..40) * 0x200; npc.direction = Direction::Bottom; - let _ = npc_list.spawn(0x100, npc); + let _ = npc_list.spawn(0, npc); } } diff --git a/src/game/npc/boss/heavy_press.rs b/src/game/npc/boss/heavy_press.rs index 65287cf..e42c6fe 100644 --- a/src/game/npc/boss/heavy_press.rs +++ b/src/game/npc/boss/heavy_press.rs @@ -250,7 +250,8 @@ impl BossNPC { // Need to calculate offset from the default starting location for i in 0..7 { stage.change_tile(i + 7, 14, 0); - npc_list.create_death_smoke((i as i32 + 7) * 0x2000, 0x1C000, 0, 1, state, &self.parts[0].rng); + // This should be called with an amount of 0, but change_tile also needs to make smoke + npc_list.create_death_smoke((i as i32 + 7) * 0x2000, 0x1C000, 0, 3, state, &self.parts[0].rng); state.sound_manager.play_sfx(12); } } diff --git a/src/game/npc/boss/ironhead.rs b/src/game/npc/boss/ironhead.rs index db8bcdd..90d53f7 100644 --- a/src/game/npc/boss/ironhead.rs +++ b/src/game/npc/boss/ironhead.rs @@ -11,7 +11,7 @@ impl NPC { pub(crate) fn tick_n196_ironhead_wall(&mut self, state: &mut SharedGameState) -> GameResult { self.x -= 0xC00; if self.x <= if !state.constants.is_switch { 0x26000 } else { 0x1E000 } { - self.x += if !state.constants.is_switch { 0x2C000 } else { 0x3C000 }; + self.x += if !state.constants.is_switch { 0x2C000 } else { 0x3B400 }; } let dir_offset = if self.direction == Direction::Left { 0 } else { 1 }; @@ -158,7 +158,7 @@ impl NPC { } 10 => { self.action_counter += 1; - if self.action_counter % 6 == 0 { + if self.action_counter % 4 == 1 { let mut npc = NPC::create(335, &state.npc_table); npc.cond.set_alive(true); npc.x = self.x; @@ -269,19 +269,21 @@ impl BossNPC { self.parts[0].action_num = 100; } - self.parts[0].action_counter += 1; - if [300, 310, 320].contains(&self.parts[0].action_counter) { - state.sound_manager.play_sfx(39); + if self.parts[0].direction == Direction::Left { + self.parts[0].action_counter += 1; + if [300, 310, 320].contains(&self.parts[0].action_counter) { + state.sound_manager.play_sfx(39); - let mut npc = NPC::create(198, &state.npc_table); - npc.cond.set_alive(true); - npc.x = self.parts[0].x + 0x1400; - npc.y = self.parts[0].y + 0x200; - npc.vel_x = self.parts[0].rng.range(-3..0) * 0x200; - npc.vel_y = self.parts[0].rng.range(-3..3) * 0x200; - npc.direction = Direction::Right; + let mut npc = NPC::create(198, &state.npc_table); + npc.cond.set_alive(true); + npc.x = self.parts[0].x + 0x1400; + npc.y = self.parts[0].y + 0x200; + npc.vel_x = self.parts[0].rng.range(-3..0) * 0x200; + npc.vel_y = self.parts[0].rng.range(-3..3) * 0x200; + npc.direction = Direction::Right; - let _ = npc_list.spawn(0x100, npc); + let _ = npc_list.spawn(0x100, npc); + } } self.parts[0].animate(2, 0, 7); diff --git a/src/game/npc/boss/undead_core.rs b/src/game/npc/boss/undead_core.rs index 7f9410d..bd13df3 100644 --- a/src/game/npc/boss/undead_core.rs +++ b/src/game/npc/boss/undead_core.rs @@ -170,8 +170,8 @@ impl NPC { self.vel_x += self.direction.vector_x() * 0x15; self.target_x += self.vel_x; - self.x = self.target_x + 4 * ((self.action_counter2 as f64).cos() * -512.0) as i32; - self.y = self.target_y + 6 * ((self.action_counter2 as f64).sin() * -512.0) as i32; + self.x = self.target_x + 4 * ((self.action_counter2 as f64).cos() * 512.0) as i32; + self.y = self.target_y + 6 * ((self.action_counter2 as f64).sin() * 512.0) as i32; let mut npc = NPC::create(286, &state.npc_table); npc.cond.set_alive(true); @@ -292,12 +292,12 @@ impl NPC { npc.x = self.x; npc.y = self.y; - npc.vel_y = self.direction.vector_y() * 0x400; + npc.vel_y = self.direction.opposite().vector_y() * 0x400; let _ = npc_list.spawn(0x100, npc); } - if self.x < 0x2000 || self.x > (stage.map.width as i32 + 1) * state.tile_size.as_int() * 0x200 { + if self.x < 0x2000 || self.x > (stage.map.width as i32 - 1) * state.tile_size.as_int() * 0x200 { self.cond.set_alive(false); } } @@ -400,6 +400,10 @@ impl BossNPC { self.parts[7].action_counter2 = 1; self.parts[7].action_counter3 = 128; + for i in [2, 6, 7] { + self.hurt_sound[i] = self.hurt_sound[1]; + } + self.parts[19].action_counter = self.parts[0].life; for i in 0u16..20 { @@ -1043,7 +1047,7 @@ impl BossNPC { part.vel_x += 0x20; part.x += part.vel_x; - if part.x > (stage.map.width as i32) * state.tile_size.as_int() * 0x200 + 0x4000 { + if part.x > (stage.map.width as i32 + 2) * state.tile_size.as_int() * 0x200 { part.cond.set_alive(false); } } diff --git a/src/game/npc/mod.rs b/src/game/npc/mod.rs index defd882..0a17f83 100644 --- a/src/game/npc/mod.rs +++ b/src/game/npc/mod.rs @@ -493,7 +493,7 @@ impl GameEntity<([&mut Player; 2], &NPCList, &mut Stage, &mut BulletManager, &mu 239 => self.tick_n239_cage_bars(state), 240 => self.tick_n240_mimiga_jailed(state), 241 => self.tick_n241_critter_red(state, players), - 242 => self.tick_n242_bat_last_cave(state), + 242 => self.tick_n242_bat_last_cave(state, stage), 243 => self.tick_n243_bat_generator(state, npc_list), 244 => self.tick_n244_lava_drop(state, players), 245 => self.tick_n245_lava_drop_generator(state, npc_list),