add flash effect to current bosses and fix some glitches
This commit is contained in:
parent
b34422ac7f
commit
211108674f
|
@ -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,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue