diff --git a/src/npc/boss/mod.rs b/src/npc/boss/mod.rs index a0a5d3c..37d32d0 100644 --- a/src/npc/boss/mod.rs +++ b/src/npc/boss/mod.rs @@ -1,7 +1,7 @@ use std::mem::MaybeUninit; -use crate::weapon::bullet::BulletManager; -use crate::common::{Direction, interpolate_fix9_scale}; +use crate::common::{interpolate_fix9_scale, Direction}; +use crate::components::flash::Flash; use crate::entity::GameEntity; use crate::frame::Frame; use crate::framework::context::Context; @@ -11,6 +11,7 @@ use crate::npc::NPC; use crate::player::Player; use crate::shared_game_state::SharedGameState; use crate::stage::Stage; +use crate::weapon::bullet::BulletManager; pub mod balfrog; pub mod ballos; @@ -45,33 +46,41 @@ impl BossNPC { parts[0].cond.set_alive(true); for (i, part) in parts.iter_mut().enumerate() { - part.rng.load_state(((i as u32) - .wrapping_add(3271284409) - .rotate_left(5) - .wrapping_mul(3815776271) - .rotate_right(9) - .wrapping_sub(2626817629) & 0xffffffff) as u32); + part.rng.load_state( + ((i as u32) + .wrapping_add(3271284409) + .rotate_left(5) + .wrapping_mul(3815776271) + .rotate_right(9) + .wrapping_sub(2626817629) + & 0xffffffff) as u32, + ); } - BossNPC { - boss_type: 0, - parts, - hurt_sound: [0; 20], - death_sound: [0; 20], - } + BossNPC { boss_type: 0, parts, hurt_sound: [0; 20], death_sound: [0; 20] } } } -impl GameEntity<([&mut Player; 2], &NPCList, &mut Stage, &BulletManager)> for BossNPC { - fn tick(&mut self, state: &mut SharedGameState, (players, npc_list, _stage, bullet_manager): ([&mut Player; 2], &NPCList, &mut Stage, &BulletManager)) -> GameResult { +impl GameEntity<([&mut Player; 2], &NPCList, &mut Stage, &BulletManager, &mut Flash)> for BossNPC { + fn tick( + &mut self, + state: &mut SharedGameState, + (players, npc_list, _stage, bullet_manager, flash): ( + [&mut Player; 2], + &NPCList, + &mut Stage, + &BulletManager, + &mut Flash, + ), + ) -> GameResult { if !self.parts[0].cond.alive() { return Ok(()); } match self.boss_type { - 1 => self.tick_b01_omega(state, players, npc_list, bullet_manager), + 1 => self.tick_b01_omega(state, players, npc_list, bullet_manager, flash), 2 => self.tick_b02_balfrog(state, players, npc_list), - 3 => self.tick_b03_monster_x(state, players, npc_list), + 3 => self.tick_b03_monster_x(state, players, npc_list, flash), 4 => self.tick_b04_core(), 5 => self.tick_b05_ironhead(), 6 => self.tick_b06_twins(), @@ -90,25 +99,27 @@ impl GameEntity<([&mut Player; 2], &NPCList, &mut Stage, &BulletManager)> for Bo } fn draw(&self, state: &mut SharedGameState, ctx: &mut Context, frame: &Frame) -> GameResult { - let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, state.npc_table.tex_npc2_name.as_str())?; + let batch = + state.texture_set.get_or_load_batch(ctx, &state.constants, state.npc_table.tex_npc2_name.as_str())?; for npc in self.parts.iter().rev() { if !npc.cond.alive() || npc.cond.hidden() { continue; } - let off_x = if npc.direction == Direction::Left { npc.display_bounds.left } else { npc.display_bounds.right } as i32; - let shock = if npc.shock > 0 { - (2 * ((npc.shock as i32 / 2) % 2) - 1) as f32 - } else { 0.0 }; + let off_x = + if npc.direction == Direction::Left { npc.display_bounds.left } else { npc.display_bounds.right } + as i32; + let shock = if npc.shock > 0 { (2 * ((npc.shock as i32 / 2) % 2) - 1) as f32 } else { 0.0 }; batch.add_rect( - interpolate_fix9_scale(npc.prev_x - off_x - frame.prev_x, - npc.x - off_x - frame.x, - state.frame_time) + shock, - interpolate_fix9_scale(npc.prev_y - npc.display_bounds.top as i32 - frame.prev_y, - npc.y - npc.display_bounds.top as i32 - frame.y, - state.frame_time), + interpolate_fix9_scale(npc.prev_x - off_x - frame.prev_x, npc.x - off_x - frame.x, state.frame_time) + + shock, + interpolate_fix9_scale( + npc.prev_y - npc.display_bounds.top as i32 - frame.prev_y, + npc.y - npc.display_bounds.top as i32 - frame.y, + state.frame_time, + ), &npc.anim_rect, ); } diff --git a/src/npc/boss/monster_x.rs b/src/npc/boss/monster_x.rs index c187b0e..f135a4d 100644 --- a/src/npc/boss/monster_x.rs +++ b/src/npc/boss/monster_x.rs @@ -1,7 +1,8 @@ use num_traits::{abs, clamp}; use crate::caret::CaretType; -use crate::common::{CDEG_RAD, Direction, Rect}; +use crate::common::{Direction, Rect, CDEG_RAD}; +use crate::components::flash::Flash; use crate::framework::context::Context; use crate::framework::error::GameResult; use crate::npc::boss::BossNPC; @@ -12,7 +13,11 @@ use crate::rng::RNG; use crate::shared_game_state::SharedGameState; impl NPC { - pub(crate) fn tick_n158_fish_missile(&mut self, state: &mut SharedGameState, players: [&mut Player; 2]) -> GameResult { + pub(crate) fn tick_n158_fish_missile( + &mut self, + state: &mut SharedGameState, + players: [&mut Player; 2], + ) -> GameResult { match self.action_num { 0 | 1 => { if self.action_num == 0 { @@ -72,7 +77,13 @@ impl NPC { } impl BossNPC { - pub(crate) fn tick_b03_monster_x(&mut self, state: &mut SharedGameState, players: [&mut Player; 2], npc_list: &NPCList) { + pub(crate) fn tick_b03_monster_x( + &mut self, + state: &mut SharedGameState, + players: [&mut Player; 2], + npc_list: &NPCList, + flash: &mut Flash, + ) { match self.parts[0].action_num { 0 => { self.parts[0].life = 1; @@ -87,12 +98,8 @@ impl BossNPC { self.parts[0].y = 200 * 0x200; self.parts[0].size = 3; self.parts[0].event_num = 1000; - self.parts[0].hit_bounds = Rect { - left: 24 * 0x200, - top: 24 * 0x200, - right: 24 * 0x200, - bottom: 24 * 0x200, - }; + self.parts[0].hit_bounds = + Rect { left: 24 * 0x200, top: 24 * 0x200, right: 24 * 0x200, bottom: 24 * 0x200 }; self.parts[0].npc_flags.set_ignore_solidity(true); self.parts[0].npc_flags.set_event_when_killed(true); self.parts[0].npc_flags.set_show_damage(true); @@ -101,12 +108,8 @@ impl BossNPC { self.parts[1].cond.set_alive(true); self.parts[1].size = 3; self.parts[1].direction = Direction::Left; - self.parts[1].display_bounds = Rect { - left: 24 * 0x200, - top: 24 * 0x200, - right: 24 * 0x200, - bottom: 24 * 0x200, - }; + self.parts[1].display_bounds = + Rect { left: 24 * 0x200, top: 24 * 0x200, right: 24 * 0x200, bottom: 24 * 0x200 }; self.parts[1].npc_flags.set_ignore_solidity(true); self.parts[2] = self.parts[1].clone(); @@ -116,18 +119,10 @@ impl BossNPC { self.parts[3].life = 60; self.parts[3].size = 2; self.parts[3].target_x = 0; - self.parts[3].display_bounds = Rect { - left: 8 * 0x200, - top: 8 * 0x200, - right: 8 * 0x200, - bottom: 8 * 0x200, - }; - self.parts[3].hit_bounds = Rect { - left: 5 * 0x200, - top: 5 * 0x200, - right: 5 * 0x200, - bottom: 5 * 0x200, - }; + self.parts[3].display_bounds = + Rect { left: 8 * 0x200, top: 8 * 0x200, right: 8 * 0x200, bottom: 8 * 0x200 }; + self.parts[3].hit_bounds = + Rect { left: 5 * 0x200, top: 5 * 0x200, right: 5 * 0x200, bottom: 5 * 0x200 }; self.parts[3].npc_flags.set_ignore_solidity(true); self.hurt_sound[3] = 54; self.death_sound[3] = 71; @@ -147,18 +142,10 @@ impl BossNPC { self.parts[7].y = self.parts[0].y; self.parts[7].size = 3; self.parts[7].anim_num = 0; - self.parts[7].display_bounds = Rect { - left: 52 * 0x200, - top: 24 * 0x200, - right: 52 * 0x200, - bottom: 24 * 0x200, - }; - self.parts[7].hit_bounds = Rect { - left: 8 * 0x200, - top: 24 * 0x200, - right: 8 * 0x200, - bottom: 16 * 0x200, - }; + self.parts[7].display_bounds = + Rect { left: 52 * 0x200, top: 24 * 0x200, right: 52 * 0x200, bottom: 24 * 0x200 }; + self.parts[7].hit_bounds = + Rect { left: 8 * 0x200, top: 24 * 0x200, right: 8 * 0x200, bottom: 16 * 0x200 }; self.parts[7].npc_flags.set_ignore_solidity(true); self.parts[9].cond.set_alive(true); @@ -167,18 +154,10 @@ impl BossNPC { self.parts[9].size = 3; self.parts[9].action_num = 0; self.parts[9].direction = Direction::Up; - self.parts[9].display_bounds = Rect { - left: 36 * 0x200, - top: 8 * 0x200, - right: 36 * 0x200, - bottom: 24 * 0x200, - }; - self.parts[9].hit_bounds = Rect { - left: 28 * 0x200, - top: 8 * 0x200, - right: 28 * 0x200, - bottom: 16 * 0x200, - }; + self.parts[9].display_bounds = + Rect { left: 36 * 0x200, top: 8 * 0x200, right: 36 * 0x200, bottom: 24 * 0x200 }; + self.parts[9].hit_bounds = + Rect { left: 28 * 0x200, top: 8 * 0x200, right: 28 * 0x200, bottom: 16 * 0x200 }; self.hurt_sound[9] = 52; self.parts[9].npc_flags.set_rear_and_top_not_hurt(true); self.parts[9].npc_flags.set_ignore_solidity(true); @@ -201,12 +180,8 @@ impl BossNPC { self.parts[12].x = self.parts[0].x + 64 * 0x200; self.parts[13] = self.parts[9].clone(); - self.parts[13].display_bounds = Rect { - left: 30 * 0x200, - top: 16 * 0x200, - right: 42 * 0x200, - bottom: 16 * 0x200, - }; + self.parts[13].display_bounds = + Rect { left: 30 * 0x200, top: 16 * 0x200, right: 42 * 0x200, bottom: 16 * 0x200 }; self.parts[13].action_counter2 = 9; self.parts[13].anim_num = 0; self.parts[13].npc_flags.0 = 0; @@ -318,8 +293,11 @@ impl BossNPC { } if self.parts[0].action_counter > 50 { - if !self.parts[3].cond.alive() && !self.parts[4].cond.alive() - && !self.parts[5].cond.alive() && !self.parts[6].cond.alive() { + if !self.parts[3].cond.alive() + && !self.parts[4].cond.alive() + && !self.parts[5].cond.alive() + && !self.parts[6].cond.alive() + { self.parts[0].action_num = 600; } else { self.parts[0].action_num = 500; @@ -343,8 +321,11 @@ impl BossNPC { } if self.parts[0].action_counter > 50 { - if !self.parts[3].cond.alive() && !self.parts[4].cond.alive() - && !self.parts[5].cond.alive() && !self.parts[6].cond.alive() { + if !self.parts[3].cond.alive() + && !self.parts[4].cond.alive() + && !self.parts[5].cond.alive() + && !self.parts[6].cond.alive() + { self.parts[0].action_num = 600; } else { self.parts[0].action_num = 500; @@ -366,8 +347,11 @@ impl BossNPC { self.parts[0].action_counter = 0; } - if !self.parts[3].cond.alive() && !self.parts[4].cond.alive() - && !self.parts[5].cond.alive() && !self.parts[6].cond.alive() { + if !self.parts[3].cond.alive() + && !self.parts[4].cond.alive() + && !self.parts[5].cond.alive() + && !self.parts[6].cond.alive() + { self.parts[0].action_num = 502; self.parts[0].action_counter = 0; } @@ -399,7 +383,8 @@ impl BossNPC { self.parts[0].action_counter += 1; if (self.parts[0].life as i32) < self.parts[0].vel_y2.saturating_sub(200) - || self.parts[0].action_counter > 300 { + || self.parts[0].action_counter > 300 + { self.parts[0].action_num = 602; self.parts[0].action_counter = 0; } @@ -437,7 +422,7 @@ impl BossNPC { if self.parts[0].action_counter > 100 { self.parts[0].action_num = 1001; self.parts[0].action_counter = 0; - // todo flash + flash.set_cross(self.parts[0].x, self.parts[0].y); state.sound_manager.play_sfx(35); } } @@ -472,7 +457,8 @@ impl BossNPC { self.tick_b03_monster_x_track(11, state, &players); self.tick_b03_monster_x_track(12, state, &players); - self.parts[0].x += (((self.parts[9].x + self.parts[10].x + self.parts[11].x + self.parts[12].x) / 4) - self.parts[0].x) / 16; + self.parts[0].x += + (((self.parts[9].x + self.parts[10].x + self.parts[11].x + self.parts[12].x) / 4) - self.parts[0].x) / 16; self.tick_b03_monster_x_face(7, state); self.tick_b03_monster_x_frame(13, state, npc_list); @@ -483,10 +469,18 @@ impl BossNPC { self.tick_b03_monster_x_shield(1, state); self.tick_b03_monster_x_shield(2, state); - if self.parts[3].cond.alive() { self.tick_b03_monster_x_eye(3, state, &players, npc_list); } - if self.parts[4].cond.alive() { self.tick_b03_monster_x_eye(4, state, &players, npc_list); } - if self.parts[5].cond.alive() { self.tick_b03_monster_x_eye(5, state, &players, npc_list); } - if self.parts[6].cond.alive() { self.tick_b03_monster_x_eye(6, state, &players, npc_list); } + if self.parts[3].cond.alive() { + self.tick_b03_monster_x_eye(3, state, &players, npc_list); + } + if self.parts[4].cond.alive() { + self.tick_b03_monster_x_eye(4, state, &players, npc_list); + } + if self.parts[5].cond.alive() { + self.tick_b03_monster_x_eye(5, state, &players, npc_list); + } + if self.parts[6].cond.alive() { + self.tick_b03_monster_x_eye(6, state, &players, npc_list); + } if self.parts[0].life == 0 && self.parts[0].action_num < 1000 { self.parts[0].action_num = 1000; @@ -776,7 +770,13 @@ impl BossNPC { self.parts[i].anim_rect = state.constants.npc.b03_monster_x[dir_offset]; } - fn tick_b03_monster_x_eye(&mut self, i: usize, state: &mut SharedGameState, players: &[&mut Player; 2], npc_list: &NPCList) { + fn tick_b03_monster_x_eye( + &mut self, + i: usize, + state: &mut SharedGameState, + players: &[&mut Player; 2], + npc_list: &NPCList, + ) { match self.parts[i].action_num { 0 => { self.parts[i].npc_flags.set_shootable(false); @@ -789,8 +789,8 @@ impl BossNPC { self.parts[i].npc_flags.set_shootable(true); } - self.parts[i].anim_num = if self.parts[i].action_counter < 16 - && self.parts[i].action_counter / 2 % 2 != 0 { 1 } else { 0 }; + self.parts[i].anim_num = + if self.parts[i].action_counter < 16 && self.parts[i].action_counter / 2 % 2 != 0 { 1 } else { 0 }; if self.parts[i].action_counter > 0 { self.parts[i].action_counter -= 1; @@ -799,8 +799,7 @@ impl BossNPC { let px = self.parts[i].x - players[player_idx].x; let py = self.parts[i].y - players[player_idx].y; - let deg = f64::atan2(py as f64, px as f64) - + self.parts[i].rng.range(-2..2) as f64 * CDEG_RAD; + let deg = f64::atan2(py as f64, px as f64) + self.parts[i].rng.range(-2..2) as f64 * CDEG_RAD; let mut npc = NPC::create(156, &state.npc_table); npc.cond.set_alive(true); @@ -838,6 +837,7 @@ impl BossNPC { _ => {} } - self.parts[i].anim_rect = state.constants.npc.b03_monster_x[21 + self.parts[i].target_x as usize + 4 * self.parts[i].anim_num as usize]; + self.parts[i].anim_rect = state.constants.npc.b03_monster_x + [21 + self.parts[i].target_x as usize + 4 * self.parts[i].anim_num as usize]; } } diff --git a/src/npc/boss/omega.rs b/src/npc/boss/omega.rs index 82aca73..c9b4fdd 100644 --- a/src/npc/boss/omega.rs +++ b/src/npc/boss/omega.rs @@ -1,21 +1,19 @@ - - -use crate::weapon::bullet::BulletManager; use crate::caret::CaretType; use crate::common::{Direction, Rect}; +use crate::components::flash::Flash; +use crate::framework::context::Context; +use crate::framework::error::GameResult; use crate::npc::boss::BossNPC; use crate::npc::list::NPCList; use crate::npc::NPC; use crate::player::Player; use crate::rng::RNG; use crate::shared_game_state::SharedGameState; -use crate::framework::context::Context; -use crate::framework::error::GameResult; +use crate::weapon::bullet::BulletManager; impl NPC { pub(crate) fn tick_n048_omega_projectiles(&mut self, state: &mut SharedGameState) -> GameResult { - if (self.flags.hit_left_wall() && self.vel_x < 0) - || (self.flags.hit_right_wall() && self.vel_x > 0) { + if (self.flags.hit_left_wall() && self.vel_x < 0) || (self.flags.hit_right_wall() && self.vel_x > 0) { self.vel_x = -self.vel_x; } else if self.flags.hit_bottom_wall() { self.action_counter2 += 1; @@ -53,7 +51,14 @@ impl NPC { } impl BossNPC { - pub(crate) fn tick_b01_omega(&mut self, state: &mut SharedGameState, players: [&mut Player; 2], npc_list: &NPCList, bullet_manager: &BulletManager) { + pub(crate) fn tick_b01_omega( + &mut self, + state: &mut SharedGameState, + players: [&mut Player; 2], + npc_list: &NPCList, + bullet_manager: &BulletManager, + flash: &mut Flash, + ) { match self.parts[0].action_num { 0 => { self.parts[0].cond.set_alive(true); @@ -68,26 +73,14 @@ impl BossNPC { self.parts[0].y = 16 * 16 * 0x200; self.parts[0].target_x = self.parts[0].x; self.parts[0].target_y = self.parts[0].y; - self.parts[0].display_bounds = Rect { - left: 40 * 0x200, - top: 40 * 0x200, - right: 40 * 0x200, - bottom: 16 * 0x200, - }; - self.parts[0].hit_bounds = Rect { - left: 8 * 0x200, - top: 24 * 0x200, - right: 8 * 0x200, - bottom: 16 * 0x200, - }; + self.parts[0].display_bounds = + Rect { left: 40 * 0x200, top: 40 * 0x200, right: 40 * 0x200, bottom: 16 * 0x200 }; + self.parts[0].hit_bounds = + Rect { left: 8 * 0x200, top: 24 * 0x200, right: 8 * 0x200, bottom: 16 * 0x200 }; self.parts[1].cond.set_alive(true); - self.parts[1].display_bounds = Rect { - left: 12 * 0x200, - top: 8 * 0x200, - right: 12 * 0x200, - bottom: 8 * 0x200, - }; + self.parts[1].display_bounds = + Rect { left: 12 * 0x200, top: 8 * 0x200, right: 12 * 0x200, bottom: 8 * 0x200 }; self.parts[1].npc_flags.set_ignore_solidity(true); self.parts[1].direction = Direction::Left; @@ -101,18 +94,10 @@ impl BossNPC { self.parts[3].direction = Direction::Left; self.parts[3].x = self.parts[0].x + 16 * 0x200; self.parts[3].y = self.parts[0].y; - self.parts[3].display_bounds = Rect { - left: 24 * 0x200, - top: 16 * 0x200, - right: 16 * 0x200, - bottom: 16 * 0x200, - }; - self.parts[3].hit_bounds = Rect { - left: 8 * 0x200, - top: 8 * 0x200, - right: 8 * 0x200, - bottom: 8 * 0x200, - }; + self.parts[3].display_bounds = + Rect { left: 24 * 0x200, top: 16 * 0x200, right: 16 * 0x200, bottom: 16 * 0x200 }; + self.parts[3].hit_bounds = + Rect { left: 8 * 0x200, top: 8 * 0x200, right: 8 * 0x200, bottom: 8 * 0x200 }; self.hurt_sound[3] = 52; self.parts[4].cond.set_alive(true); @@ -191,11 +176,7 @@ impl BossNPC { npc.y = self.parts[0].y - 16 * 0x200; npc.vel_x = self.parts[0].rng.range(-0x100..0x100) as i32; npc.vel_y = -0x333; - npc.direction = if self.parts[0].rng.range(0..9) <= 7 { - Direction::Left - } else { - Direction::Right - }; + npc.direction = if self.parts[0].rng.range(0..9) <= 7 { Direction::Left } else { Direction::Right }; let _ = npc_list.spawn(0x100, npc); state.sound_manager.play_sfx(39); @@ -264,12 +245,13 @@ impl BossNPC { if self.parts[0].anim_counter > 2 { self.parts[0].anim_counter = 0; self.parts[0].anim_num += 1; - if self.parts[0].anim_num == 3 { - self.parts[0].action_num = 120; - self.parts[0].action_counter = 0; - self.parts[0].hit_bounds.left = 16 * 0x200; - self.parts[0].hit_bounds.right = 16 * 0x200; - } + } + + if self.parts[0].anim_num == 3 { + self.parts[0].action_num = 120; + self.parts[0].action_counter = 0; + self.parts[0].hit_bounds.left = 16 * 0x200; + self.parts[0].hit_bounds.right = 16 * 0x200; } } 120 => { @@ -282,7 +264,7 @@ impl BossNPC { state.sound_manager.play_sfx(102); } - if self.parts[0].action_counter <= 29 && self.parts[0].action_counter % 5 == 0 { + if self.parts[0].action_counter < 30 && self.parts[0].action_counter % 5 == 0 { let mut npc = NPC::create(48, &state.npc_table); npc.cond.set_alive(true); npc.x = self.parts[0].x; @@ -300,30 +282,33 @@ impl BossNPC { if self.parts[0].anim_counter > 2 { self.parts[0].anim_counter = 0; self.parts[0].anim_num -= 1; + } - match self.parts[0].anim_num { - 1 => self.parts[0].damage = 20, - 0 => { - self.parts[0].action_num = 140; - self.parts[0].npc_flags.set_shootable(true); - self.parts[0].hit_bounds.left = 16 * 0x200; - self.parts[0].hit_bounds.right = 16 * 0x200; - let player = self.parts[0].get_closest_player_mut(players); - self.parts[0].vel_x = (player.x - self.parts[0].x).signum() * 0x100; - self.parts[0].damage = 0; - self.parts[0].hit_bounds.top = 36 * 0x200; - } - _ => {} + match self.parts[0].anim_num { + 0 => { + self.parts[0].action_num = 140; + self.parts[0].npc_flags.set_shootable(true); + self.parts[0].hit_bounds.left = 16 * 0x200; + self.parts[0].hit_bounds.right = 16 * 0x200; + let player = self.parts[0].get_closest_player_mut(players); + self.parts[0].vel_x = (player.x - self.parts[0].x).signum() * 0x100; + self.parts[0].vel_y = -0x5ff; + self.parts[0].damage = 0; + self.parts[5].hit_bounds.top = 0x4800; + + state.sound_manager.play_sfx(12); + state.sound_manager.play_sfx(25); + state.sound_manager.play_sfx(102); } + 1 => { + self.parts[0].damage = 20; + } + _ => {} } } 140 => { let player = self.parts[5].get_closest_player_mut(players); - self.parts[5].damage = if player.flags.hit_bottom_wall() && self.parts[0].vel_y > 0 { - 20 - } else { - 0 - }; + self.parts[5].damage = if player.flags.hit_bottom_wall() && self.parts[0].vel_y > 0 { 20 } else { 0 }; self.parts[0].vel_y += 0x24; if self.parts[0].vel_y > 0x5ff { self.parts[0].vel_y = 0x5ff; @@ -352,20 +337,15 @@ impl BossNPC { state.sound_manager.play_sfx(52); } - let dest_x = self.parts[0].x + self.parts[0].rng.range(-0x30..0x30) as i32 * 0x200; - let dest_y = self.parts[0].y + self.parts[0].rng.range(-0x30..0x18) as i32 * 0x200; + let dest_x = self.parts[0].x + self.parts[0].rng.range(-0x30..0x30) * 0x200; + let dest_y = self.parts[0].y + self.parts[0].rng.range(-0x30..0x18) * 0x200; - let mut npc = NPC::create(4, &state.npc_table); - npc.cond.set_alive(true); - npc.x = dest_x; - npc.y = dest_y; - let _ = npc_list.spawn(0x100, npc); - state.create_caret(dest_x, dest_y, CaretType::Explosion, Direction::Left); + npc_list.create_death_smoke(dest_x, dest_y, 1, 1, state, &self.parts[0].rng); if self.parts[0].action_counter > 100 { self.parts[0].action_num = 160; self.parts[0].action_counter = 0; - // todo flash + flash.set_cross(self.parts[0].x, self.parts[0].y); state.sound_manager.play_sfx(35); } } @@ -397,30 +377,27 @@ impl BossNPC { self.parts[i].y = self.parts[0].y; match i { - 3 => self.parts[i].x = self.parts[0].x - 16 * 0x200, - 4 => self.parts[i].x = self.parts[0].x + 16 * 0x200, + 3 => self.parts[i].x = self.parts[0].x - 0x2000, + 4 => self.parts[i].x = self.parts[0].x + 0x2000, _ => {} } } 3 => { - self.parts[i].target_y = self.parts[0].y + 24 * 0x200; + self.parts[i].target_y = self.parts[0].y + 0x3000; match i { - 3 => self.parts[i].x = self.parts[0].x - 16 * 0x200, - 4 => self.parts[i].x = self.parts[0].x + 16 * 0x200, + 3 => self.parts[i].x = self.parts[0].x - 0x2000, + 4 => self.parts[i].x = self.parts[0].x + 0x2000, _ => {} } - self.parts[i].y += (self.parts[0].target_y - self.parts[0].y) / 2; + self.parts[i].y += (self.parts[i].target_y - self.parts[i].y) / 2; } _ => {} } - if self.parts[i].flags.hit_bottom_wall() || self.parts[i].y <= self.parts[i].target_y { - self.parts[i].anim_num = 0; - } else { - self.parts[i].anim_num = 1; - } + self.parts[i].anim_num = + if !self.parts[i].flags.hit_bottom_wall() && self.parts[i].y > self.parts[i].target_y { 1 } else { 0 }; let dir_offset = if self.parts[i].direction == Direction::Left { 0 } else { 2 }; @@ -429,7 +406,7 @@ impl BossNPC { for &i in [1, 2].iter() { self.parts[i].x = self.parts[0].x + self.parts[i].direction.vector_x() * 16 * 0x200; - self.parts[i].y = (self.parts[0].y + self.parts[i + 2].y - 8 * 0x200) / 2; + self.parts[i].y = (self.parts[0].y + self.parts[i + 2].y - 0x1000) / 2; let dir_offset = if self.parts[i].direction == Direction::Left { 0 } else { 1 }; @@ -440,12 +417,8 @@ impl BossNPC { self.parts[5].action_num = 1; self.parts[5].npc_flags.set_solid_soft(true); self.parts[5].npc_flags.set_ignore_solidity(true); - self.parts[5].hit_bounds = Rect { - left: 20 * 0x200, - top: 36 * 0x200, - right: 20 * 0x200, - bottom: 16 * 0x200, - }; + self.parts[5].hit_bounds = + Rect { left: 20 * 0x200, top: 36 * 0x200, right: 20 * 0x200, bottom: 16 * 0x200 }; } self.parts[5].x = self.parts[0].x;