2020-11-04 09:06:02 +00:00
|
|
|
use crate::caret::CaretType;
|
|
|
|
use crate::common::{Direction, Rect, CDEG_RAD};
|
2020-11-04 23:25:18 +00:00
|
|
|
use ggez::GameResult;
|
2020-11-04 09:06:02 +00:00
|
|
|
use crate::npc::{NPC, NPCMap};
|
2020-11-02 02:20:16 +00:00
|
|
|
use crate::npc::boss::BossNPC;
|
2020-11-02 14:01:30 +00:00
|
|
|
use crate::player::Player;
|
2020-11-02 02:20:16 +00:00
|
|
|
use crate::shared_game_state::SharedGameState;
|
|
|
|
|
2020-11-04 09:06:02 +00:00
|
|
|
impl NPC {
|
|
|
|
pub(crate) fn tick_n108_balfrog_projectile(&mut self, state: &mut SharedGameState) -> GameResult {
|
|
|
|
if self.action_counter > 300 || (self.flags.0 & 0xff) != 0 {
|
|
|
|
self.cond.set_alive(false);
|
|
|
|
state.create_caret(self.x, self.y, CaretType::ProjectileDissipation, Direction::Left);
|
|
|
|
}
|
|
|
|
|
|
|
|
self.x += self.vel_x;
|
|
|
|
self.y += self.vel_y;
|
|
|
|
|
|
|
|
self.action_counter += 1;
|
|
|
|
self.anim_counter += 1;
|
|
|
|
if self.anim_counter > 1 {
|
|
|
|
self.anim_counter = 0;
|
|
|
|
self.anim_num += 1;
|
|
|
|
if self.anim_num > 2 {
|
|
|
|
self.anim_num = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
self.anim_rect = state.constants.npc.n108_balfrog_projectile[self.anim_num as usize];
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-02 02:20:16 +00:00
|
|
|
impl BossNPC {
|
2020-11-02 14:01:30 +00:00
|
|
|
pub(crate) fn tick_b02_balfrog(&mut self, state: &mut SharedGameState, player: &Player) {
|
2020-11-02 02:20:16 +00:00
|
|
|
match self.parts[0].action_num {
|
|
|
|
0 => {
|
2020-11-02 14:01:30 +00:00
|
|
|
self.hurt_sound[0] = 52;
|
2020-11-02 02:20:16 +00:00
|
|
|
self.parts[0].x = 6 * 16 * 0x200;
|
|
|
|
self.parts[0].y = 12 * 16 * 0x200;
|
|
|
|
self.parts[0].direction = Direction::Right;
|
|
|
|
self.parts[0].display_bounds = Rect {
|
|
|
|
left: 48 * 0x200,
|
|
|
|
top: 48 * 0x200,
|
|
|
|
right: 32 * 0x200,
|
|
|
|
bottom: 16 * 0x200,
|
|
|
|
};
|
|
|
|
self.parts[0].hit_bounds = Rect {
|
|
|
|
left: 24 * 0x200,
|
|
|
|
top: 16 * 0x200,
|
|
|
|
right: 24 * 0x200,
|
|
|
|
bottom: 16 * 0x200,
|
|
|
|
};
|
|
|
|
self.parts[0].size = 3;
|
|
|
|
self.parts[0].exp = 1;
|
|
|
|
self.parts[0].event_num = 1000;
|
|
|
|
self.parts[0].npc_flags.set_event_when_killed(true);
|
|
|
|
self.parts[0].npc_flags.set_show_damage(true);
|
|
|
|
self.parts[0].life = 300;
|
|
|
|
}
|
|
|
|
10 => {
|
|
|
|
self.parts[0].action_num = 11;
|
|
|
|
self.parts[0].anim_num = 3;
|
|
|
|
self.parts[0].cond.set_alive(true);
|
|
|
|
self.parts[0].anim_rect = state.constants.npc.b02_balfrog[9];
|
|
|
|
|
|
|
|
self.parts[1].cond.set_alive(true);
|
|
|
|
self.parts[1].cond.set_damage_boss(true);
|
|
|
|
self.parts[1].damage = 5;
|
|
|
|
|
|
|
|
self.parts[2].cond.set_alive(true);
|
|
|
|
self.parts[2].damage = 5;
|
|
|
|
|
|
|
|
let mut npc = NPCMap::create_npc(4, &state.npc_table);
|
|
|
|
|
|
|
|
for _ in 0..8 {
|
|
|
|
npc.cond.set_alive(true);
|
|
|
|
npc.direction = Direction::Left;
|
|
|
|
npc.x = self.parts[0].x + state.game_rng.range(-12..12) as isize * 0x200;
|
|
|
|
npc.y = self.parts[0].y + state.game_rng.range(-12..12) as isize * 0x200;
|
|
|
|
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
|
|
|
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
|
|
|
|
|
|
|
state.new_npcs.push(npc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
20 | 21 => {
|
|
|
|
if self.parts[0].action_num == 20 {
|
2020-11-04 09:06:02 +00:00
|
|
|
self.parts[0].action_num = 21;
|
2020-11-02 02:20:16 +00:00
|
|
|
self.parts[0].action_counter = 0
|
|
|
|
}
|
|
|
|
|
|
|
|
self.parts[0].action_counter += 1;
|
2020-11-04 09:06:02 +00:00
|
|
|
if (self.parts[0].action_counter / 2 % 2) != 0 {
|
2020-11-02 02:20:16 +00:00
|
|
|
self.parts[0].anim_num = 3;
|
|
|
|
} else {
|
|
|
|
self.parts[0].anim_num = 0;
|
|
|
|
}
|
|
|
|
}
|
2020-11-02 14:01:30 +00:00
|
|
|
100 | 101 => {
|
|
|
|
if self.parts[0].action_num == 100 {
|
|
|
|
self.parts[0].action_num = 101;
|
|
|
|
self.parts[0].action_counter = 0;
|
|
|
|
self.parts[0].anim_num = 1;
|
|
|
|
self.parts[0].vel_x = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.parts[0].action_counter += 1;
|
|
|
|
if self.parts[0].action_counter > 50 {
|
|
|
|
self.parts[0].action_num = 102;
|
|
|
|
self.parts[0].anim_counter = 0;
|
|
|
|
self.parts[0].anim_num = 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
102 => {
|
|
|
|
self.parts[0].anim_counter += 1;
|
|
|
|
|
|
|
|
if self.parts[0].anim_counter > 10 {
|
|
|
|
self.parts[0].action_num = 103;
|
|
|
|
self.parts[0].anim_counter = 0;
|
|
|
|
self.parts[0].anim_num = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
103 => {
|
|
|
|
self.parts[0].anim_counter += 1;
|
|
|
|
if self.parts[0].anim_counter > 4 {
|
|
|
|
self.parts[0].action_num = 104;
|
|
|
|
self.parts[0].anim_num = 5;
|
|
|
|
self.parts[0].vel_x = self.parts[0].direction.vector_x() * 0x200;
|
|
|
|
self.parts[0].vel_y = -2 * 0x200;
|
|
|
|
self.parts[0].display_bounds.top = 64 * 0x200;
|
|
|
|
self.parts[0].display_bounds.bottom = 24 * 0x200;
|
|
|
|
|
|
|
|
state.sound_manager.play_sfx(25);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
104 => {
|
|
|
|
if self.parts[0].direction == Direction::Left && self.parts[0].flags.hit_left_wall() {
|
|
|
|
self.parts[0].direction = Direction::Right;
|
|
|
|
self.parts[0].vel_x = 0x200;
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.parts[0].direction == Direction::Right && self.parts[0].flags.hit_right_wall() {
|
|
|
|
self.parts[0].direction = Direction::Left;
|
|
|
|
self.parts[0].vel_x = -0x200;
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.parts[0].flags.hit_bottom_wall() {
|
|
|
|
self.parts[0].action_num = 100;
|
|
|
|
self.parts[0].anim_num = 1;
|
|
|
|
self.parts[0].display_bounds.top = 48 * 0x200;
|
|
|
|
self.parts[0].display_bounds.bottom = 16 * 0x200;
|
|
|
|
|
|
|
|
if self.parts[0].direction == Direction::Left && self.parts[0].x < player.x {
|
|
|
|
self.parts[0].direction = Direction::Right;
|
|
|
|
self.parts[0].action_num = 110;
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.parts[0].direction == Direction::Right && self.parts[0].x > player.x {
|
|
|
|
self.parts[0].direction = Direction::Left;
|
|
|
|
self.parts[0].action_num = 110;
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut npc = NPCMap::create_npc(110, &state.npc_table);
|
|
|
|
npc.cond.set_alive(true);
|
|
|
|
npc.x = state.game_rng.range(4..16) as isize * 16 * 0x200;
|
|
|
|
npc.y = state.game_rng.range(0..4) as isize * 16 * 0x200;
|
2020-11-04 09:06:02 +00:00
|
|
|
npc.direction = Direction::FacingPlayer;
|
2020-11-02 14:01:30 +00:00
|
|
|
|
|
|
|
state.new_npcs.push(npc);
|
|
|
|
|
|
|
|
let mut npc = NPCMap::create_npc(4, &state.npc_table);
|
|
|
|
|
|
|
|
for _ in 0..4 {
|
|
|
|
npc.cond.set_alive(true);
|
|
|
|
npc.direction = Direction::Left;
|
|
|
|
npc.x = self.parts[0].x + state.game_rng.range(-12..12) as isize * 0x200;
|
|
|
|
npc.y = self.parts[0].y + state.game_rng.range(-12..12) as isize * 0x200;
|
|
|
|
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
|
|
|
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
|
|
|
|
|
|
|
state.new_npcs.push(npc);
|
|
|
|
}
|
|
|
|
|
|
|
|
state.quake_counter = 30;
|
|
|
|
state.sound_manager.play_sfx(26);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
110 | 111 => {
|
|
|
|
if self.parts[0].action_num == 110 {
|
|
|
|
self.parts[0].anim_num = 1;
|
|
|
|
self.parts[0].action_num = 111;
|
|
|
|
self.parts[0].action_counter = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.parts[0].action_counter += 1;
|
|
|
|
|
|
|
|
self.parts[0].vel_x = self.parts[0].vel_x * 8 / 9;
|
|
|
|
|
|
|
|
if self.parts[0].action_counter > 50 {
|
|
|
|
self.parts[0].anim_num = 2;
|
|
|
|
self.parts[0].anim_counter = 0;
|
|
|
|
self.parts[0].action_num = 112;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
112 => {
|
|
|
|
self.parts[0].anim_counter += 1;
|
|
|
|
|
|
|
|
if self.parts[0].anim_counter > 4 {
|
|
|
|
self.parts[0].action_num = 113;
|
|
|
|
self.parts[0].action_counter = 0;
|
2020-11-04 09:06:02 +00:00
|
|
|
self.parts[0].vel_x2 = 16;
|
2020-11-02 14:01:30 +00:00
|
|
|
self.parts[0].anim_num = 3;
|
|
|
|
self.parts[0].target_x = self.parts[0].life as isize;
|
|
|
|
self.parts[1].npc_flags.set_shootable(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
113 => {
|
|
|
|
if self.parts[0].shock != 0 {
|
|
|
|
if self.parts[0].action_counter2 / 2 % 2 != 0 {
|
|
|
|
self.parts[0].anim_num = 4;
|
|
|
|
} else {
|
|
|
|
self.parts[0].anim_num = 3;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
self.parts[0].action_counter2 = 0;
|
|
|
|
self.parts[0].anim_num = 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.parts[0].vel_x = self.parts[0].vel_x * 10 / 11;
|
|
|
|
|
|
|
|
self.parts[0].action_counter += 1;
|
|
|
|
if self.parts[0].action_counter > 16 {
|
|
|
|
self.parts[0].action_counter = 0;
|
2020-11-04 09:06:02 +00:00
|
|
|
self.parts[0].vel_x2 = self.parts[0].vel_x2.saturating_sub(1);
|
2020-11-02 14:01:30 +00:00
|
|
|
|
2020-11-04 09:06:02 +00:00
|
|
|
let px = self.parts[0].x + self.parts[0].direction.vector_x() * 2 * 16 * 0x200 - player.x;
|
2020-11-02 14:01:30 +00:00
|
|
|
let py = self.parts[0].y - 8 * 0x200 - player.y;
|
|
|
|
|
2020-11-04 09:06:02 +00:00
|
|
|
let deg = f64::atan2(py as f64, px as f64)
|
|
|
|
+ state.game_rng.range(-16..16) as f64 * CDEG_RAD;
|
2020-11-02 14:01:30 +00:00
|
|
|
// todo rand
|
|
|
|
|
|
|
|
let mut npc = NPCMap::create_npc(108, &state.npc_table);
|
|
|
|
npc.cond.set_alive(true);
|
2020-11-04 09:06:02 +00:00
|
|
|
npc.x = self.parts[0].x + self.parts[0].direction.vector_x() * 2 * 16 * 0x200;
|
|
|
|
npc.y = self.parts[0].y - 8 * 0x200;
|
|
|
|
npc.vel_x = (deg.cos() * -512.0) as isize;
|
|
|
|
npc.vel_y = (deg.sin() * -512.0) as isize;
|
|
|
|
|
|
|
|
state.new_npcs.push(npc);
|
2020-11-02 14:01:30 +00:00
|
|
|
|
|
|
|
state.sound_manager.play_sfx(39);
|
|
|
|
|
2020-11-04 09:06:02 +00:00
|
|
|
if self.parts[0].vel_x2 == 0 || (self.parts[0].life as isize) < self.parts[0].target_x - 90 {
|
2020-11-02 14:01:30 +00:00
|
|
|
self.parts[0].action_num = 114;
|
|
|
|
self.parts[0].action_counter = 0;
|
|
|
|
self.parts[0].anim_num = 2;
|
|
|
|
self.parts[0].anim_counter = 0;
|
|
|
|
self.parts[1].npc_flags.set_shootable(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
114 => {
|
|
|
|
self.parts[0].anim_counter += 1;
|
|
|
|
if self.parts[0].anim_counter > 10 {
|
|
|
|
self.parts[0].anim_num = 1;
|
|
|
|
self.parts[0].anim_counter = 0;
|
|
|
|
|
|
|
|
self.parts[1].action_counter2 += 1;
|
|
|
|
if self.parts[1].action_counter2 > 2 {
|
|
|
|
self.parts[1].action_counter2 = 0;
|
|
|
|
self.parts[0].action_num = 120;
|
|
|
|
} else {
|
|
|
|
self.parts[0].action_num = 100;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-11-04 09:06:02 +00:00
|
|
|
120 | 121 => {
|
|
|
|
if self.parts[0].action_num == 120 {
|
|
|
|
self.parts[0].action_num = 121;
|
|
|
|
self.parts[0].action_counter = 0;
|
|
|
|
self.parts[0].anim_num = 1;
|
|
|
|
self.parts[0].vel_x = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.parts[0].action_counter += 1;
|
|
|
|
if self.parts[0].action_counter > 50 {
|
|
|
|
self.parts[0].action_num = 122;
|
|
|
|
self.parts[0].anim_num = 2;
|
|
|
|
self.parts[0].anim_counter = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
122 => {
|
|
|
|
self.parts[0].anim_counter += 1;
|
|
|
|
if self.parts[0].anim_counter > 20 {
|
|
|
|
self.parts[0].action_num = 123;
|
|
|
|
self.parts[0].anim_num = 1;
|
|
|
|
self.parts[0].anim_counter = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
123 => {
|
|
|
|
self.parts[0].anim_counter += 1;
|
|
|
|
if self.parts[0].anim_counter > 4 {
|
|
|
|
self.parts[0].action_num = 124;
|
|
|
|
self.parts[0].anim_num = 5;
|
|
|
|
self.parts[0].vel_x = -5 * 0x200;
|
|
|
|
self.parts[0].display_bounds.top = 64 * 0x200;
|
|
|
|
self.parts[0].display_bounds.bottom = 24 * 0x200;
|
|
|
|
|
|
|
|
state.sound_manager.play_sfx(25);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
124 => {
|
|
|
|
if self.parts[0].flags.hit_bottom_wall() {
|
|
|
|
self.parts[0].action_num = 100;
|
|
|
|
self.parts[0].anim_num = 1;
|
|
|
|
self.parts[0].display_bounds.top = 48 * 0x200;
|
|
|
|
self.parts[0].display_bounds.bottom = 16 * 0x200;
|
|
|
|
|
|
|
|
let mut npc = NPCMap::create_npc(104, &state.npc_table);
|
|
|
|
for _ in 0..2 {
|
|
|
|
npc.cond.set_alive(true);
|
|
|
|
npc.x = state.game_rng.range(4..16) as isize * 16 * 0x200;
|
|
|
|
npc.y = state.game_rng.range(0..4) as isize * 16 * 0x200;
|
|
|
|
npc.direction = Direction::FacingPlayer;
|
|
|
|
|
|
|
|
state.new_npcs.push(npc);
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut npc = NPCMap::create_npc(110, &state.npc_table);
|
|
|
|
for _ in 0..6 {
|
|
|
|
npc.cond.set_alive(true);
|
|
|
|
npc.x = state.game_rng.range(4..16) as isize * 16 * 0x200;
|
|
|
|
npc.y = state.game_rng.range(0..4) as isize * 16 * 0x200;
|
|
|
|
npc.direction = Direction::FacingPlayer;
|
|
|
|
|
|
|
|
state.new_npcs.push(npc);
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut npc = NPCMap::create_npc(4, &state.npc_table);
|
|
|
|
for _ in 0..8 {
|
|
|
|
npc.cond.set_alive(true);
|
|
|
|
npc.x = self.parts[0].x + state.game_rng.range(-12..12) as isize * 0x200;
|
|
|
|
npc.y = self.parts[0].y + self.parts[0].hit_bounds.bottom as isize;
|
|
|
|
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
|
|
|
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
|
|
|
npc.direction = Direction::Left;
|
|
|
|
|
|
|
|
state.new_npcs.push(npc);
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.parts[0].direction == Direction::Left && self.parts[0].x < player.x {
|
|
|
|
self.parts[0].action_num = 110;
|
|
|
|
self.parts[0].direction = Direction::Right;
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.parts[0].direction == Direction::Right && self.parts[0].x > player.x {
|
|
|
|
self.parts[0].action_num = 110;
|
|
|
|
self.parts[0].direction = Direction::Right;
|
|
|
|
}
|
|
|
|
|
|
|
|
state.sound_manager.play_sfx(26);
|
|
|
|
state.quake_counter = 60;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
130 | 131 => {
|
|
|
|
if self.parts[0].action_num == 130 {
|
|
|
|
self.parts[0].action_num = 131;
|
|
|
|
self.parts[0].action_counter = 0;
|
|
|
|
self.parts[0].anim_num = 3;
|
|
|
|
self.parts[0].vel_x = 0;
|
|
|
|
|
|
|
|
self.parts[1].cond.set_alive(false);
|
|
|
|
self.parts[2].cond.set_alive(false);
|
|
|
|
|
|
|
|
state.sound_manager.play_sfx(72);
|
|
|
|
|
|
|
|
let mut npc = NPCMap::create_npc(4, &state.npc_table);
|
|
|
|
for _ in 0..8 {
|
|
|
|
npc.cond.set_alive(true);
|
|
|
|
npc.x = self.parts[0].x + state.game_rng.range(-12..12) as isize * 0x200;
|
|
|
|
npc.y = self.parts[0].y + state.game_rng.range(-12..12) as isize * 0x200;
|
|
|
|
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
|
|
|
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
|
|
|
npc.direction = Direction::Left;
|
|
|
|
state.new_npcs.push(npc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
self.parts[0].action_counter += 1;
|
|
|
|
if (self.parts[0].action_counter % 5) == 0 {
|
|
|
|
let mut npc = NPCMap::create_npc(4, &state.npc_table);
|
|
|
|
npc.cond.set_alive(true);
|
|
|
|
npc.x = self.parts[0].x + state.game_rng.range(-12..12) as isize * 0x200;
|
|
|
|
npc.y = self.parts[0].y + state.game_rng.range(-12..12) as isize * 0x200;
|
|
|
|
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
|
|
|
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
|
|
|
npc.direction = Direction::Left;
|
|
|
|
state.new_npcs.push(npc);
|
|
|
|
}
|
|
|
|
|
|
|
|
self.parts[0].x += if (self.parts[0].action_counter / 2 % 2) != 0 {
|
|
|
|
-0x200
|
|
|
|
} else {
|
|
|
|
0x200
|
|
|
|
};
|
|
|
|
|
|
|
|
if self.parts[0].action_counter > 100 {
|
|
|
|
self.parts[0].action_num = 132;
|
|
|
|
self.parts[0].action_counter = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
132 => {
|
|
|
|
self.parts[0].action_counter += 1;
|
|
|
|
if (self.parts[0].action_counter / 2 % 2) != 0 {
|
|
|
|
self.parts[0].anim_num = 6;
|
|
|
|
self.parts[0].display_bounds = Rect {
|
|
|
|
left: 20 * 0x200,
|
|
|
|
top: 12 * 0x200,
|
|
|
|
right: 20 * 0x200,
|
|
|
|
bottom: 12 * 0x200,
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
self.parts[0].anim_num = 3;
|
|
|
|
self.parts[0].display_bounds = Rect {
|
|
|
|
left: 48 * 0x200,
|
|
|
|
top: 48 * 0x200,
|
|
|
|
right: 32 * 0x200,
|
|
|
|
bottom: 16 * 0x200,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
if (self.parts[0].action_counter % 9) == 0 {
|
|
|
|
let mut npc = NPCMap::create_npc(4, &state.npc_table);
|
|
|
|
npc.cond.set_alive(true);
|
|
|
|
npc.x = self.parts[0].x + state.game_rng.range(-12..12) as isize * 0x200;
|
|
|
|
npc.y = self.parts[0].y + state.game_rng.range(-12..12) as isize * 0x200;
|
|
|
|
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
|
|
|
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
|
|
|
npc.direction = Direction::Left;
|
|
|
|
state.new_npcs.push(npc);
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.parts[0].action_counter > 150 {
|
|
|
|
self.parts[0].action_num = 140;
|
|
|
|
self.parts[0].hit_bounds.bottom = 12 * 0x200;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
140 | 141 => {
|
|
|
|
if self.parts[0].action_num == 140 {
|
|
|
|
self.parts[0].action_num = 141;
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.parts[0].flags.hit_bottom_wall() {
|
|
|
|
self.parts[0].action_num = 142;
|
|
|
|
self.parts[0].action_counter = 0;
|
|
|
|
self.parts[0].anim_num = 7;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
142 => {
|
|
|
|
self.parts[0].action_counter += 1;
|
|
|
|
if self.parts[0].action_counter > 30 {
|
|
|
|
self.parts[0].anim_num = 8;
|
|
|
|
self.parts[0].vel_y = -5 * 0x200;
|
|
|
|
self.parts[0].npc_flags.set_ignore_solidity(true);
|
|
|
|
self.parts[0].action_num = 143;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
143 => {
|
|
|
|
self.parts[0].vel_y = -5 * 0x200;
|
|
|
|
if self.parts[0].y < 0 {
|
|
|
|
self.parts[0].cond.set_alive(false);
|
|
|
|
|
|
|
|
state.sound_manager.play_sfx(26);
|
|
|
|
state.quake_counter = 30;
|
|
|
|
}
|
|
|
|
}
|
2020-11-02 02:20:16 +00:00
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
|
|
|
self.parts[0].vel_y += 0x40;
|
|
|
|
if self.parts[0].vel_y > 0x5ff {
|
|
|
|
self.parts[0].vel_y = 0x5ff;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.parts[0].x += self.parts[0].vel_x;
|
|
|
|
self.parts[0].y += self.parts[0].vel_y;
|
|
|
|
|
|
|
|
let dir_offset = if self.parts[0].direction == Direction::Left { 0 } else { 9 };
|
|
|
|
self.parts[0].anim_rect = state.constants.npc.b02_balfrog[self.parts[0].anim_num as usize + dir_offset];
|
2020-11-04 09:06:02 +00:00
|
|
|
|
|
|
|
match self.parts[0].anim_num {
|
|
|
|
0 => {
|
|
|
|
self.hurt_sound[1] = 52;
|
|
|
|
self.parts[1].size = 3;
|
|
|
|
self.parts[1].npc_flags.set_invulnerable(true);
|
|
|
|
self.parts[1].hit_bounds = Rect {
|
|
|
|
left: 16 * 0x200,
|
|
|
|
top: 16 * 0x200,
|
|
|
|
right: 16 * 0x200,
|
|
|
|
bottom: 16 * 0x200,
|
|
|
|
};
|
|
|
|
|
|
|
|
self.hurt_sound[2] = 52;
|
|
|
|
self.parts[2].size = 3;
|
|
|
|
self.parts[2].npc_flags.set_invulnerable(true);
|
|
|
|
self.parts[2].hit_bounds = Rect {
|
|
|
|
left: 24 * 0x200,
|
|
|
|
top: 16 * 0x200,
|
|
|
|
right: 24 * 0x200,
|
|
|
|
bottom: 16 * 0x200,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
1 => {
|
|
|
|
self.parts[1].x = self.parts[0].x + self.parts[0].direction.vector_x() * 24 * 0x200;
|
|
|
|
self.parts[1].y = self.parts[0].y - 24 * 0x200;
|
|
|
|
|
|
|
|
self.parts[2].x = self.parts[0].x;
|
|
|
|
self.parts[2].y = self.parts[0].y;
|
|
|
|
}
|
|
|
|
2 => {
|
|
|
|
self.parts[1].x = self.parts[0].x + self.parts[0].direction.vector_x() * 24 * 0x200;
|
|
|
|
self.parts[1].y = self.parts[0].y - 20 * 0x200;
|
|
|
|
|
|
|
|
self.parts[2].x = self.parts[0].x;
|
|
|
|
self.parts[2].y = self.parts[0].y;
|
|
|
|
}
|
|
|
|
3 | 4 => {
|
|
|
|
self.parts[1].x = self.parts[0].x + self.parts[0].direction.vector_x() * 24 * 0x200;
|
|
|
|
self.parts[1].y = self.parts[0].y - 16 * 0x200;
|
|
|
|
|
|
|
|
self.parts[2].x = self.parts[0].x;
|
|
|
|
self.parts[2].y = self.parts[0].y;
|
|
|
|
}
|
|
|
|
5 => {
|
|
|
|
self.parts[1].x = self.parts[0].x + self.parts[0].direction.vector_x() * 24 * 0x200;
|
|
|
|
self.parts[1].y = self.parts[0].y - 43 * 0x200;
|
|
|
|
|
|
|
|
self.parts[2].x = self.parts[0].x;
|
|
|
|
self.parts[2].y = self.parts[0].y;
|
|
|
|
}
|
|
|
|
_ => { }
|
|
|
|
}
|
2020-11-02 02:20:16 +00:00
|
|
|
}
|
|
|
|
}
|