mirror of
https://github.com/doukutsu-rs/doukutsu-rs
synced 2025-03-23 02:19:43 +00:00
All remaning NPCs
This commit is contained in:
parent
39267048c7
commit
b492be2203
|
@ -993,14 +993,14 @@ pub struct NPCConsts {
|
|||
#[serde(default = "default_n341_ballos_1_head")]
|
||||
pub n341_ballos_1_head: [Rect<u16>; 3],
|
||||
|
||||
#[serde(default = "default_n342_ballos_1_eye")]
|
||||
pub n342_ballos_1_eye: [Rect<u16>; 3],
|
||||
#[serde(default = "default_n342_ballos_orbiting_eye")]
|
||||
pub n342_ballos_orbiting_eye: [Rect<u16>; 3],
|
||||
|
||||
#[serde(default = "default_n343_ballos_2_cutscene")]
|
||||
pub n343_ballos_2_cutscene: Rect<u16>,
|
||||
#[serde(default = "default_n343_ballos_3_cutscene")]
|
||||
pub n343_ballos_3_cutscene: Rect<u16>,
|
||||
|
||||
#[serde(default = "default_n344_ballos_2_eyes")]
|
||||
pub n344_ballos_2_eyes: [Rect<u16>; 2],
|
||||
#[serde(default = "default_n344_ballos_3_eyes")]
|
||||
pub n344_ballos_3_eyes: [Rect<u16>; 2],
|
||||
|
||||
#[serde(default = "default_n345_ballos_skull_projectile")]
|
||||
pub n345_ballos_skull_projectile: [Rect<u16>; 4],
|
||||
|
@ -4453,7 +4453,7 @@ fn default_n341_ballos_1_head() -> [Rect<u16>; 3] {
|
|||
]
|
||||
}
|
||||
|
||||
fn default_n342_ballos_1_eye() -> [Rect<u16>; 3] {
|
||||
fn default_n342_ballos_orbiting_eye() -> [Rect<u16>; 3] {
|
||||
[
|
||||
Rect { left: 240, top: 48, right: 280, bottom: 88 },
|
||||
Rect { left: 240, top: 88, right: 280, bottom: 128 },
|
||||
|
@ -4461,11 +4461,11 @@ fn default_n342_ballos_1_eye() -> [Rect<u16>; 3] {
|
|||
]
|
||||
}
|
||||
|
||||
fn default_n343_ballos_2_cutscene() -> Rect<u16> {
|
||||
fn default_n343_ballos_3_cutscene() -> Rect<u16> {
|
||||
Rect { left: 0, top: 0, right: 120, bottom: 120 }
|
||||
}
|
||||
|
||||
fn default_n344_ballos_2_eyes() -> [Rect<u16>; 2] {
|
||||
fn default_n344_ballos_3_eyes() -> [Rect<u16>; 2] {
|
||||
[Rect { left: 272, top: 0, right: 296, bottom: 16 }, Rect { left: 296, top: 0, right: 320, bottom: 16 }]
|
||||
}
|
||||
|
||||
|
@ -4567,10 +4567,12 @@ fn default_n352_ending_characters() -> [Rect<u16>; 28] {
|
|||
|
||||
fn default_n353_bute_sword_flying() -> [Rect<u16>; 8] {
|
||||
[
|
||||
// Entering
|
||||
Rect { left: 168, top: 160, right: 184, bottom: 184 },
|
||||
Rect { left: 184, top: 160, right: 200, bottom: 184 },
|
||||
Rect { left: 168, top: 184, right: 184, bottom: 208 },
|
||||
Rect { left: 184, top: 184, right: 200, bottom: 208 },
|
||||
// Flying
|
||||
Rect { left: 200, top: 160, right: 216, bottom: 176 },
|
||||
Rect { left: 216, top: 160, right: 232, bottom: 176 },
|
||||
Rect { left: 200, top: 176, right: 216, bottom: 192 },
|
||||
|
|
|
@ -1312,4 +1312,58 @@ impl NPC {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n356_balrog_rescuing(&mut self, state: &mut SharedGameState, npc_list: &NPCList) -> GameResult {
|
||||
match self.action_num {
|
||||
0 | 11 => {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 11;
|
||||
self.anim_counter = 0;
|
||||
self.target_x = self.x - 0xC00;
|
||||
self.target_y = self.y - 0x2000;
|
||||
self.vel_y = 0;
|
||||
let mut npc = NPC::create(355, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
npc.parent_id = self.id;
|
||||
npc.direction = Direction::Bottom;
|
||||
let _ = npc_list.spawn(0xAA, npc.clone());
|
||||
npc.direction = Direction::Right;
|
||||
let _ = npc_list.spawn(0xAA, npc);
|
||||
}
|
||||
|
||||
self.vel_x += 8 * if self.x < self.target_x { 1 } else { -1 };
|
||||
self.vel_y += 8 * if self.y < self.target_y { 1 } else { -1 };
|
||||
|
||||
self.x += self.vel_x;
|
||||
self.y += self.vel_y;
|
||||
}
|
||||
20 | 21 => {
|
||||
if self.action_num == 20 {
|
||||
self.action_num = 21;
|
||||
self.vel_x = -0x400;
|
||||
self.vel_y = 0x200;
|
||||
}
|
||||
self.anim_counter += 1;
|
||||
self.vel_x += 16;
|
||||
self.vel_y -= 8;
|
||||
self.x += self.vel_x;
|
||||
self.y += self.vel_y;
|
||||
|
||||
if self.x > 0x78000 {
|
||||
self.action_num = 22;
|
||||
}
|
||||
}
|
||||
22 => {
|
||||
self.vel_x = 0;
|
||||
self.vel_y = 0;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
self.animate(4, 0, 1);
|
||||
|
||||
self.anim_rect = state.constants.npc.n356_balrog_rescuing[self.anim_num as usize];
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2364,6 +2364,38 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n334_sweat(&mut self, state: &mut SharedGameState, players: [&mut Player; 2]) -> GameResult {
|
||||
let player = self.get_closest_player_mut(players);
|
||||
|
||||
match self.action_num {
|
||||
0 | 10 => {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 10;
|
||||
if self.direction == Direction::Left {
|
||||
self.x += 0x1400;
|
||||
self.y -= 0x2400;
|
||||
} else {
|
||||
self.x = player.x - 0x1400;
|
||||
self.y = player.y - 0x400;
|
||||
}
|
||||
}
|
||||
|
||||
self.action_counter += 1;
|
||||
self.anim_num = if self.action_counter / 8 % 2 != 0 { 0 } else { 1 };
|
||||
|
||||
if self.action_counter >= 64 {
|
||||
self.cond.set_alive(false);
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let dir_offset = if self.direction == Direction::Left { 0 } else { 2 };
|
||||
self.anim_rect = state.constants.npc.n334_sweat[self.anim_num as usize + dir_offset];
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n349_statue(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
|
|
|
@ -432,8 +432,7 @@ impl NPC {
|
|||
self.vel_y = 0x5FF;
|
||||
}
|
||||
|
||||
self.anim_counter += 1;
|
||||
self.anim_num = if self.anim_counter & 0x02 != 0 { 4 } else { 5 };
|
||||
self.animate(1, 4, 5);
|
||||
|
||||
if self.flags.hit_bottom_wall() {
|
||||
self.action_num = 242;
|
||||
|
@ -515,8 +514,7 @@ impl NPC {
|
|||
self.action_num = 240;
|
||||
}
|
||||
|
||||
self.anim_counter += 1;
|
||||
self.anim_num = if self.anim_counter & 0x02 != 0 { 4 } else { 5 };
|
||||
self.animate(1, 4, 5);
|
||||
}
|
||||
1000 | 1001 => {
|
||||
if self.action_num == 1000 {
|
||||
|
@ -570,9 +568,7 @@ impl NPC {
|
|||
flash.set_blink();
|
||||
state.sound_manager.play_sfx(29);
|
||||
}
|
||||
|
||||
self.anim_counter += 1;
|
||||
self.anim_num = if self.anim_counter & 0x02 != 0 { 8 } else { 9 };
|
||||
self.animate(1, 8, 9);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
@ -609,7 +605,7 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n342_ballos_1_eye(
|
||||
pub(crate) fn tick_n342_ballos_orbiting_eye(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
players: [&mut Player; 2],
|
||||
|
@ -890,10 +886,514 @@ impl NPC {
|
|||
self.x += self.vel_x;
|
||||
self.y += self.vel_y;
|
||||
|
||||
self.anim_rect = state.constants.npc.n342_ballos_1_eye[self.anim_num as usize];
|
||||
self.anim_rect = state.constants.npc.n342_ballos_orbiting_eye[self.anim_num as usize];
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n343_ballos_3_cutscene(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
boss: &mut BossNPC,
|
||||
) -> GameResult {
|
||||
self.action_counter += 1;
|
||||
if self.action_counter > 100 {
|
||||
self.cond.set_alive(false);
|
||||
}
|
||||
|
||||
self.x = boss.parts[0].x;
|
||||
self.y = boss.parts[0].y;
|
||||
|
||||
self.anim_rect = state.constants.npc.n343_ballos_3_cutscene;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n344_ballos_3_eyes(&mut self, state: &mut SharedGameState, boss: &mut BossNPC) -> GameResult {
|
||||
self.action_counter += 1;
|
||||
if self.action_counter > 100 {
|
||||
self.cond.set_alive(false);
|
||||
}
|
||||
|
||||
self.x = boss.parts[0].x + (0x3000 * self.direction.vector_x());
|
||||
self.y = boss.parts[0].y - 0x4800;
|
||||
|
||||
self.anim_rect = state.constants.npc.n344_ballos_3_eyes[if self.direction == Direction::Left { 0 } else { 1 }];
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n345_ballos_skull_projectile(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
npc_list: &NPCList,
|
||||
stage: &mut Stage,
|
||||
) -> GameResult {
|
||||
match self.action_num {
|
||||
0 | 100 => {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 100;
|
||||
self.anim_num = (self.rng.range(0..16) % 4) as u16;
|
||||
}
|
||||
self.vel_y += 0x40;
|
||||
if self.vel_y > 0x700 {
|
||||
self.vel_y = 0x700;
|
||||
}
|
||||
|
||||
if self.y > 0x10000 {
|
||||
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);
|
||||
npc.x = self.x;
|
||||
npc.y = self.y;
|
||||
let _ = npc_list.spawn(0x100, npc);
|
||||
}
|
||||
|
||||
if self.flags.hit_bottom_wall() {
|
||||
self.action_num = 110;
|
||||
self.vel_y = -0x200;
|
||||
self.npc_flags.set_ignore_solidity(true);
|
||||
state.sound_manager.play_sfx(12);
|
||||
state.quake_counter = 10;
|
||||
|
||||
for _ in 0..4 {
|
||||
let mut npc = NPC::create(4, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
npc.x = self.x + self.rng.range(-12..12) * 0x200;
|
||||
npc.y = self.y + 0x2000;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155);
|
||||
npc.vel_y = self.rng.range(-0x600..0);
|
||||
let _ = npc_list.spawn(0x100, npc);
|
||||
}
|
||||
}
|
||||
}
|
||||
110 => {
|
||||
self.vel_y += 0x40;
|
||||
|
||||
if self.y > (stage.map.height as i32) * state.tile_size.as_int() * 0x200 + 0x4000 {
|
||||
self.cond.set_alive(false);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
self.animate(8, 0, 3);
|
||||
|
||||
self.y += self.vel_y;
|
||||
|
||||
self.anim_rect = state.constants.npc.n345_ballos_skull_projectile[self.anim_num as usize];
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n346_ballos_orbiting_platform(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
players: [&mut Player; 2],
|
||||
stage: &mut Stage,
|
||||
boss: &mut BossNPC,
|
||||
) -> GameResult {
|
||||
if self.action_num < 1000 && boss.parts[0].action_num >= 1000 {
|
||||
self.action_num = 1000;
|
||||
}
|
||||
|
||||
match self.action_num {
|
||||
0 | 10 => {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 10;
|
||||
self.action_counter3 = 192;
|
||||
}
|
||||
if self.action_counter3 >= 448 {
|
||||
self.action_num = 11;
|
||||
} else {
|
||||
self.action_counter3 += 8;
|
||||
}
|
||||
}
|
||||
11 => {
|
||||
if boss.parts[0].action_num == 411 {
|
||||
self.action_num = 20;
|
||||
}
|
||||
}
|
||||
20 => {
|
||||
if self.action_counter2 > 0 {
|
||||
self.action_counter2 -= 1;
|
||||
} else {
|
||||
self.action_counter2 += 0x400;
|
||||
}
|
||||
|
||||
if boss.parts[0].action_num == 421 {
|
||||
self.action_num = 40;
|
||||
} else if boss.parts[0].action_num == 423 {
|
||||
self.action_num = 100;
|
||||
}
|
||||
}
|
||||
30 => {
|
||||
self.action_counter2 += 1;
|
||||
self.action_counter2 %= 0x400;
|
||||
|
||||
if boss.parts[0].action_num == 425 {
|
||||
self.action_num = 50;
|
||||
} else if boss.parts[0].action_num == 427 {
|
||||
self.action_num = 100;
|
||||
}
|
||||
}
|
||||
40 => {
|
||||
if self.action_counter2 > 1 {
|
||||
self.action_counter2 -= 2;
|
||||
} else {
|
||||
self.action_counter2 += 0x400;
|
||||
}
|
||||
|
||||
if boss.parts[0].action_num == 422 {
|
||||
self.action_num = 20;
|
||||
}
|
||||
}
|
||||
50 => {
|
||||
self.action_counter2 += 2;
|
||||
self.action_counter2 %= 0x400;
|
||||
|
||||
if boss.parts[0].action_num == 426 {
|
||||
self.action_num = 30;
|
||||
}
|
||||
}
|
||||
100 => {
|
||||
if boss.parts[0].action_num == 424 {
|
||||
self.action_num = 30;
|
||||
} else if boss.parts[0].action_num == 428 {
|
||||
self.action_num = 20;
|
||||
}
|
||||
}
|
||||
1000 | 1001 => {
|
||||
if self.action_num == 1000 {
|
||||
self.action_num = 1001;
|
||||
self.vel_x = 0;
|
||||
self.vel_y = 0;
|
||||
self.npc_flags.set_solid_hard(false);
|
||||
}
|
||||
self.vel_y += 0x40;
|
||||
|
||||
if self.y > (stage.map.height as i32) * state.tile_size.as_int() * 0x200 {
|
||||
self.cond.set_alive(false);
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
if self.action_num < 1000 {
|
||||
let player = self.get_closest_player_mut(players);
|
||||
|
||||
if player.y > self.y - 0x1000 && player.vel_y < 0 {
|
||||
self.npc_flags.set_solid_hard(false);
|
||||
} else {
|
||||
self.npc_flags.set_solid_hard(true);
|
||||
}
|
||||
|
||||
let deg = (self.action_counter2 as f64 / 4.0) * CDEG_RAD;
|
||||
self.target_x = boss.parts[0].x + (self.action_counter3 as f64 * deg.cos() * 128.0) as i32;
|
||||
self.target_y = boss.parts[0].y + (self.action_counter3 as f64 * deg.sin() * 128.0) as i32 + 0x2000;
|
||||
|
||||
self.vel_x = self.target_x - self.x;
|
||||
|
||||
match self.action_num {
|
||||
20 | 30 => {
|
||||
if self.action_counter2 % 4 == 0 {
|
||||
self.vel_y = (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_y = self.target_y - self.y;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.vel_y = 0;
|
||||
}
|
||||
|
||||
self.x += self.vel_x;
|
||||
self.y += self.vel_y;
|
||||
|
||||
self.anim_rect = state.constants.npc.n346_ballos_orbiting_platform;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n348_ballos_4_spikes(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
match self.action_num {
|
||||
0 | 1 => {
|
||||
self.action_num = 1;
|
||||
|
||||
self.action_counter += 1;
|
||||
if self.action_counter < 128 {
|
||||
self.y -= 0x80;
|
||||
|
||||
self.animate(1, 0, 1);
|
||||
} else {
|
||||
self.action_num = 10;
|
||||
self.anim_num = 0;
|
||||
self.damage = 2;
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
self.anim_rect = state.constants.npc.n348_ballos_4_spikes[self.anim_num as usize];
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n350_flying_bute_archer(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
players: [&mut Player; 2],
|
||||
npc_list: &NPCList,
|
||||
stage: &mut Stage,
|
||||
) -> GameResult {
|
||||
let player = self.get_closest_player_mut(players);
|
||||
|
||||
match self.action_num {
|
||||
0 | 1 => {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
self.target_x = self.x + 0x10000 * self.direction.vector_x();
|
||||
self.target_y = self.y;
|
||||
self.vel_x = self.rng.range(-0x200..0x200) * 2;
|
||||
self.vel_y = self.rng.range(-0x200..0x200) * 2;
|
||||
}
|
||||
|
||||
self.animate(1, 0, 1);
|
||||
|
||||
// The equal to target case is missing
|
||||
if self.direction == Direction::Left && self.x < self.target_x {
|
||||
self.action_num = 20;
|
||||
}
|
||||
if self.direction != Direction::Left && self.x > self.target_x {
|
||||
self.action_num = 20;
|
||||
}
|
||||
}
|
||||
20 | 21 => {
|
||||
if self.action_num == 20 {
|
||||
self.action_num = 21;
|
||||
self.action_counter = self.rng.range(0..150) as u16;
|
||||
self.anim_num = 2;
|
||||
self.anim_counter = 0;
|
||||
}
|
||||
|
||||
self.animate(2, 2, 3);
|
||||
|
||||
self.action_counter += 1;
|
||||
if self.action_num > 300 {
|
||||
self.action_num = 30;
|
||||
}
|
||||
if player.x < self.x + 0xE000
|
||||
&& player.x > self.x - 0xE000
|
||||
&& player.y < self.y + 0x2000
|
||||
&& player.y > self.y - 0x2000
|
||||
{
|
||||
self.action_num = 30;
|
||||
}
|
||||
}
|
||||
30 | 31 => {
|
||||
if self.action_num == 30 {
|
||||
self.action_num = 31;
|
||||
self.action_counter = 0;
|
||||
self.anim_counter = 0;
|
||||
}
|
||||
|
||||
self.animate(1, 3, 4);
|
||||
|
||||
self.action_counter += 1;
|
||||
if self.action_counter > 30 {
|
||||
self.action_num = 40;
|
||||
self.anim_num = 5;
|
||||
|
||||
let mut npc = NPC::create(312, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
npc.x = self.x;
|
||||
npc.y = self.y;
|
||||
npc.vel_x = 0x800 * self.direction.vector_x();
|
||||
let _ = npc_list.spawn(0x100, npc);
|
||||
}
|
||||
}
|
||||
40 | 41 => {
|
||||
if self.action_num == 40 {
|
||||
self.action_num = 41;
|
||||
self.action_counter = 0;
|
||||
self.anim_counter = 0;
|
||||
}
|
||||
|
||||
self.animate(2, 5, 6);
|
||||
|
||||
self.action_counter += 1;
|
||||
if self.action_counter > 40 {
|
||||
self.action_num = 50;
|
||||
self.anim_num = 0;
|
||||
self.vel_x = 0;
|
||||
self.vel_y = 0;
|
||||
}
|
||||
}
|
||||
50 => {
|
||||
self.animate(1, 0, 1);
|
||||
|
||||
self.vel_x += 0x20 * self.direction.vector_x();
|
||||
|
||||
if self.x < 0 || self.x > (stage.map.width as i32) * state.tile_size.as_int() * 0x200 {
|
||||
self.vanish(state);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
if self.action_num < 50 {
|
||||
let direction_x = self.target_x - self.x;
|
||||
let direction_y = self.target_y - self.y;
|
||||
|
||||
self.vel_x += 0x2A * direction_x.signum();
|
||||
self.vel_y += 0x2A * direction_y.signum();
|
||||
|
||||
self.vel_x = self.vel_x.clamp(-0x400, 0x400);
|
||||
self.vel_y = self.vel_y.clamp(-0x400, 0x400);
|
||||
}
|
||||
|
||||
self.x += self.vel_x;
|
||||
self.y += self.vel_y;
|
||||
|
||||
let dir_offset = if self.direction == Direction::Left { 0 } else { 7 };
|
||||
self.anim_rect = state.constants.npc.n350_flying_bute_archer[self.anim_num as usize + dir_offset];
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n353_bute_sword_flying(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
players: [&mut Player; 2],
|
||||
) -> GameResult {
|
||||
let player = self.get_closest_player_mut(players);
|
||||
|
||||
match self.action_num {
|
||||
0 | 1 => {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
self.vel_x = 0x600 * self.direction.vector_x();
|
||||
self.vel_y = 0x600 * self.direction.vector_y();
|
||||
}
|
||||
|
||||
self.action_counter += 1;
|
||||
if self.action_counter == 8 {
|
||||
self.npc_flags.set_ignore_solidity(false);
|
||||
}
|
||||
|
||||
self.x += self.vel_x;
|
||||
self.y += self.vel_y;
|
||||
|
||||
if self.action_counter == 16 {
|
||||
self.action_num = 10;
|
||||
}
|
||||
|
||||
self.animate(2, 0, 3);
|
||||
}
|
||||
10 | 11 => {
|
||||
if self.action_num == 10 {
|
||||
self.action_num = 11;
|
||||
self.anim_num = 0;
|
||||
self.npc_flags.set_shootable(true);
|
||||
self.npc_flags.set_ignore_solidity(false);
|
||||
self.damage = 5;
|
||||
self.display_bounds.top = 0x1000;
|
||||
}
|
||||
|
||||
self.direction = if self.x > player.x { Direction::Left } else { Direction::Right };
|
||||
|
||||
self.vel_x2 += 0x10 * self.direction.vector_x() * if player.y - 0x3000 > self.y { -1 } else { 1 };
|
||||
self.vel_y2 += 0x10 * if self.y > player.y { -1 } else { 1 };
|
||||
|
||||
if self.vel_x2 < 0 && self.flags.hit_left_wall() {
|
||||
self.vel_x2 *= -1
|
||||
};
|
||||
if self.vel_x2 > 0 && self.flags.hit_right_wall() {
|
||||
self.vel_x2 *= -1
|
||||
};
|
||||
if self.vel_y2 < 0 && self.flags.hit_top_wall() {
|
||||
self.vel_y2 *= -1
|
||||
};
|
||||
if self.vel_y2 < 0 && self.flags.hit_bottom_wall() {
|
||||
self.vel_y2 *= -1
|
||||
};
|
||||
|
||||
self.vel_x2 = self.vel_x2.clamp(-0x5FF, 0x5FF);
|
||||
self.vel_y2 = self.vel_y2.clamp(-0x5FF, 0x5FF);
|
||||
|
||||
self.x += self.vel_x2;
|
||||
self.y += self.vel_y2;
|
||||
|
||||
self.animate(1, 4, 5);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
if self.action_num < 10 {
|
||||
self.anim_rect = state.constants.npc.n353_bute_sword_flying[self.anim_num as usize];
|
||||
} else {
|
||||
let dir_offset = if self.direction == Direction::Left { 0 } else { 2 };
|
||||
self.anim_rect = state.constants.npc.n353_bute_sword_flying[self.anim_num as usize + dir_offset];
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n354_invisible_deathtrap_wall(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
npc_list: &NPCList,
|
||||
stage: &mut Stage,
|
||||
) -> GameResult {
|
||||
match self.action_num {
|
||||
0 => {
|
||||
self.hit_bounds.bottom = 0x23000;
|
||||
}
|
||||
10 => {
|
||||
self.action_num = 11;
|
||||
self.action_counter = 0;
|
||||
self.x += 0x2000 * self.direction.vector_x() * -1;
|
||||
}
|
||||
11 => {
|
||||
self.action_counter += 1;
|
||||
if self.action_counter > 100 {
|
||||
self.action_counter = 0;
|
||||
state.quake_counter = 20;
|
||||
state.sound_manager.play_sfx(26);
|
||||
state.sound_manager.play_sfx(12);
|
||||
|
||||
self.x += 0x2000 * self.direction.vector_x();
|
||||
|
||||
let mut npc = NPC::create(4, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
|
||||
for iter in 0..20 {
|
||||
let x = self.x / (state.tile_size.as_int() * 0x200);
|
||||
let y = iter + (self.y / (state.tile_size.as_int() * 0x200));
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl BossNPC {
|
||||
|
@ -1002,7 +1502,7 @@ impl BossNPC {
|
|||
for _ in 0..16 {
|
||||
let mut npc = NPC::create(4, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
npc.x = self.parts[0].rng.range(-40..40) * 0x200;
|
||||
npc.x = self.parts[0].x + self.parts[0].rng.range(-40..40) * 0x200;
|
||||
npc.y = self.parts[0].y + 0x5000;
|
||||
let _ = npc_list.spawn(0x100, npc);
|
||||
}
|
||||
|
@ -1256,7 +1756,7 @@ impl BossNPC {
|
|||
self.parts[0].action_num = 410;
|
||||
|
||||
// platforms
|
||||
for iter in 0..5 {
|
||||
for iter in 0..8 {
|
||||
let mut npc = NPC::create(346, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
npc.x = self.parts[0].x;
|
||||
|
@ -1417,6 +1917,7 @@ impl BossNPC {
|
|||
* 0x2000)
|
||||
/ 4;
|
||||
npc.y = (self.parts[0].rng.range(8..68) * 0x2000) / 4;
|
||||
npc.direction = if player.x > self.parts[0].x { Direction::Left } else { Direction::Right };
|
||||
let _ = npc_list.spawn(0x100, npc);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -574,7 +574,7 @@ impl GameEntity<([&mut Player; 2], &NPCList, &mut Stage, &mut BulletManager, &mu
|
|||
331 => self.tick_n331_ballos_bone_projectile(state),
|
||||
332 => self.tick_n332_ballos_shockwave(state, npc_list),
|
||||
333 => self.tick_n333_ballos_lightning(state, players, npc_list),
|
||||
// 334 => self.tick_n334_sweat(state),
|
||||
334 => self.tick_n334_sweat(state, players),
|
||||
335 => self.tick_n335_ikachan(state),
|
||||
336 => self.tick_n336_ikachan_generator(state, players, npc_list),
|
||||
337 => self.tick_n337_numahachi(state),
|
||||
|
@ -582,21 +582,21 @@ impl GameEntity<([&mut Player; 2], &NPCList, &mut Stage, &mut BulletManager, &mu
|
|||
339 => self.tick_n339_green_devil_generator(state, npc_list),
|
||||
340 => self.tick_n340_ballos(state, players, npc_list, flash),
|
||||
341 => self.tick_n341_ballos_1_head(state, npc_list),
|
||||
342 => self.tick_n342_ballos_1_eye(state, players, npc_list, boss),
|
||||
// 343 => self.tick_n343_ballos_2_cutscene(state),
|
||||
// 344 => self.tick_n344_ballos_2_eyes(state),
|
||||
// 345 => self.tick_n345_ballos_skull_projectile(state),
|
||||
// 346 => self.tick_n346_ballos_orbiting_platform(state),
|
||||
342 => self.tick_n342_ballos_orbiting_eye(state, players, npc_list, boss),
|
||||
343 => self.tick_n343_ballos_3_cutscene(state, boss),
|
||||
344 => self.tick_n344_ballos_3_eyes(state, boss),
|
||||
345 => self.tick_n345_ballos_skull_projectile(state, npc_list, stage),
|
||||
346 => self.tick_n346_ballos_orbiting_platform(state, players, stage, boss),
|
||||
347 => self.tick_n347_hoppy(state, players),
|
||||
// 348 => self.tick_n348_ballos_4_spikes(state),
|
||||
348 => self.tick_n348_ballos_4_spikes(state),
|
||||
349 => self.tick_n349_statue(state),
|
||||
// 350 => self.tick_n350_flying_bute_archer(state),
|
||||
350 => self.tick_n350_flying_bute_archer(state, players, npc_list, stage),
|
||||
351 => self.tick_n351_statue_shootable(state, npc_list),
|
||||
352 => self.tick_n352_ending_characters(state, npc_list),
|
||||
// 353 => self.tick_n353_bute_red(state),
|
||||
// 354 => self.tick_n354_invisible_deathtrap_wall(state),
|
||||
353 => self.tick_n353_bute_sword_flying(state, players),
|
||||
354 => self.tick_n354_invisible_deathtrap_wall(state, npc_list, stage),
|
||||
355 => self.tick_n355_quote_and_curly_on_balrog(state, npc_list),
|
||||
// 356 => self.tick_n356_balrog_rescuing(state),
|
||||
356 => self.tick_n356_balrog_rescuing(state, npc_list),
|
||||
357 => self.tick_n357_puppy_ghost(state),
|
||||
358 => self.tick_n358_misery_credits(state),
|
||||
359 => self.tick_n359_water_droplet_generator(state, players, npc_list),
|
||||
|
|
Loading…
Reference in a new issue