add flash effect to current bosses and fix some glitches

This commit is contained in:
Alula 2021-03-15 22:10:32 +01:00
parent b34422ac7f
commit 211108674f
No known key found for this signature in database
GPG Key ID: 3E00485503A1D8BA
3 changed files with 184 additions and 200 deletions

View File

@ -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,
);
}

View File

@ -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];
}
}

View File

@ -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;