diff --git a/src/engine_constants/npcs.rs b/src/engine_constants/npcs.rs index 6e696a3..9ddb012 100644 --- a/src/engine_constants/npcs.rs +++ b/src/engine_constants/npcs.rs @@ -505,8 +505,8 @@ pub struct NPCConsts { #[serde(default = "default_n168_boulder")] pub n168_boulder: Rect, - #[serde(default = "default_n169_balrog_missile_group")] - pub n169_balrog_missile_group: [Rect; 18], + #[serde(default = "default_n169_balrog_shooting_missiles")] + pub n169_balrog_shooting_missiles: [Rect; 18], #[serde(default = "default_n170_balrog_missile")] pub n170_balrog_missile: [Rect; 4], @@ -2970,7 +2970,7 @@ fn default_n168_boulder() -> Rect { Rect { left: 264, top: 56, right: 320, bottom: 96 } } -fn default_n169_balrog_missile_group() -> [Rect; 18] { +fn default_n169_balrog_shooting_missiles() -> [Rect; 18] { [ Rect { left: 0, top: 0, right: 40, bottom: 24 }, Rect { left: 0, top: 48, right: 40, bottom: 72 }, diff --git a/src/npc/ai/balrog.rs b/src/npc/ai/balrog.rs index a1c28f8..4d6f552 100644 --- a/src/npc/ai/balrog.rs +++ b/src/npc/ai/balrog.rs @@ -997,7 +997,7 @@ impl NPC { Ok(()) } - pub(crate) fn tick_n169_balrog_missile_group( + pub(crate) fn tick_n169_balrog_shooting_missiles( &mut self, state: &mut SharedGameState, mut players: [&mut Player; 2], @@ -1205,9 +1205,15 @@ impl NPC { if self.vel_y > 0x5FF { self.vel_y = 0x5FF; } + self.x += self.vel_x; self.y += self.vel_y; + let dir_offset = if self.direction == Direction::Left { 0 } else { 9 }; + + self.anim_rect = state.constants.npc.n169_balrog_shooting_missiles[self.anim_num as usize + dir_offset]; + + Ok(()) } @@ -1269,6 +1275,10 @@ impl NPC { self.x += self.vel_x; self.y += self.vel_y; + let dir_offset = if self.direction == Direction::Left { 0 } else { 2 }; + + self.anim_rect = state.constants.npc.n170_balrog_missile[self.anim_num as usize + dir_offset]; + Ok(()) } } diff --git a/src/npc/ai/egg_corridor.rs b/src/npc/ai/egg_corridor.rs index 317faca..dbde043 100644 --- a/src/npc/ai/egg_corridor.rs +++ b/src/npc/ai/egg_corridor.rs @@ -475,6 +475,7 @@ impl NPC { } else { self.y -= 0x200; } + self.animate(1, 0, 1); } 3 => { self.action_counter += 1; @@ -491,6 +492,7 @@ impl NPC { } else { self.y -= 0x200; } + self.animate(1, 0, 1); } 5 => { self.action_counter += 1; @@ -507,6 +509,7 @@ impl NPC { } else { self.y += 0x200; } + self.animate(1, 0, 1); } 7 => { self.action_counter += 1; @@ -523,23 +526,12 @@ impl NPC { } else { self.y += 0x200; } + self.animate(1, 0, 1); } _ => {} } - if [2, 4, 6, 8].contains(&self.action_num) { - self.anim_counter += 1; - if self.anim_counter > 1 { - self.anim_num += 1; - if self.anim_num > 1 { - self.anim_num = 0; - } - } - } - - if self.anim_counter == 1 { - self.anim_rect = state.constants.npc.n025_lift[self.anim_num as usize]; - } + self.anim_rect = state.constants.npc.n025_lift[self.anim_num as usize]; Ok(()) } diff --git a/src/npc/ai/maze.rs b/src/npc/ai/maze.rs index 518b2f1..e84d001 100644 --- a/src/npc/ai/maze.rs +++ b/src/npc/ai/maze.rs @@ -1,5 +1,5 @@ use crate::caret::CaretType; -use crate::common::{CDEG_RAD, Direction}; +use crate::common::{Direction, CDEG_RAD}; use crate::framework::error::GameResult; use crate::npc::list::NPCList; use crate::npc::NPC; @@ -906,6 +906,100 @@ impl NPC { Ok(()) } + pub(crate) fn tick_n171_fire_whirrr( + &mut self, + state: &mut SharedGameState, + players: [&mut Player; 2], + npc_list: &NPCList, + ) -> GameResult { + if self.action_num == 0 { + self.action_num = 1; + self.action_counter = self.rng.range(0..50) as u16; + self.action_counter3 = 100; + self.target_y = self.y; + } + + if self.action_num == 1 { + if self.action_counter > 0 { + self.action_counter -= 1; + } else { + self.action_num = 10; + self.vel_y = 0x200; + } + } + + self.animate(0, 0, 1); + + self.vel_y = if self.y >= self.target_y { self.vel_y - 0x10 } else { self.vel_y + 0x10 }; + self.vel_y = self.vel_y.clamp(-0x200, 0x200); + self.y += self.vel_y; + + let player = self.get_closest_player_mut(players); + + if self.x <= player.x { + self.direction = Direction::Right; + } else { + self.direction = Direction::Left; + } + + if self.direction != Direction::Left { + if player.y < self.y + 0xA000 + && player.y > self.y - 0xA000 + && player.x < self.x + 0x14000 + && player.x > self.x + { + self.action_counter3 += 1; + } + } else if player.y < self.y + 0xA000 + && player.y > self.y - 0xA000 + && player.x < self.x + && player.x > self.x - 0x14000 + { + self.action_counter3 += 1; + } + + if self.action_counter3 > 120 { + self.action_counter3 = 0; + state.npc_curly_counter = self.rng.range(80..100) as u16; + state.npc_curly_target = (self.x, self.y); + + let mut npc = NPC::create(172, &state.npc_table); + npc.cond.set_alive(true); + npc.x = self.x; + npc.y = self.y; + npc.direction = self.direction; + + let _ = npc_list.spawn(0x100, npc); + } + + let dir_offset = if self.direction == Direction::Left { 0 } else { 2 }; + + self.anim_rect = state.constants.npc.n171_fire_whirrr[self.anim_num as usize + dir_offset]; + + Ok(()) + } + + pub(crate) fn tick_n172_fire_whirrr_projectile(&mut self, state: &mut SharedGameState) -> GameResult { + if self.action_num == 0 { + // pixel what? + self.action_num = 1; + } + + if self.action_num == 1 { + self.animate(1, 0, 2); + self.x += self.direction.vector_x() * 0x200; + + if self.flags.hit_left_wall() || self.flags.hit_right_wall() { + state.create_caret(self.x, self.y, CaretType::ProjectileDissipation, Direction::Left); + self.vanish(state); + } + } + + self.anim_rect = state.constants.npc.n172_fire_whirrr_projectile[self.anim_num as usize]; + + Ok(()) + } + pub(crate) fn tick_n173_gaudi_armored( &mut self, state: &mut SharedGameState, diff --git a/src/npc/mod.rs b/src/npc/mod.rs index 9677ae4..a652c12 100644 --- a/src/npc/mod.rs +++ b/src/npc/mod.rs @@ -333,8 +333,10 @@ impl GameEntity<([&mut Player; 2], &NPCList, &mut Stage, &BulletManager, &mut Fl 166 => self.tick_n166_chaba(state), 167 => self.tick_n167_booster_falling(state, npc_list), 168 => self.tick_n168_boulder(state), - 169 => self.tick_n169_balrog_missile_group(state, players, npc_list), + 169 => self.tick_n169_balrog_shooting_missiles(state, players, npc_list), 170 => self.tick_n170_balrog_missile(state, players, npc_list), + 171 => self.tick_n171_fire_whirrr(state, players, npc_list), + 172 => self.tick_n172_fire_whirrr_projectile(state), 192 => self.tick_n192_scooter(state), 193 => self.tick_n193_broken_scooter(state), 194 => self.tick_n194_broken_blue_robot(state),