277 lines
8.2 KiB
Rust
277 lines
8.2 KiB
Rust
use crate::common::Direction;
|
|
use crate::framework::error::GameResult;
|
|
use crate::game::npc::NPC;
|
|
use crate::game::shared_game_state::SharedGameState;
|
|
use crate::game::stage::{BackgroundType, Stage};
|
|
use crate::util::rng::RNG;
|
|
|
|
impl NPC {
|
|
pub(crate) fn tick_n001_experience(&mut self, state: &mut SharedGameState, stage: &mut Stage) -> GameResult {
|
|
if stage.data.background_type == BackgroundType::Scrolling || stage.data.background_type == BackgroundType::OutsideWind {
|
|
if self.action_num == 0 {
|
|
self.action_num = 1;
|
|
|
|
self.vel_x = self.rng.range(-0x80..0x80) as i32;
|
|
self.vel_y = self.rng.range(-0x7f..0x100) as i32;
|
|
}
|
|
|
|
self.vel_x -= 0x8;
|
|
|
|
if self.x < 0xa000 {
|
|
self.cond.set_alive(false);
|
|
return Ok(());
|
|
}
|
|
|
|
if self.vel_x < -0x600 {
|
|
self.vel_x = -0x600;
|
|
}
|
|
|
|
if self.flags.hit_left_wall() {
|
|
self.vel_x = 0x100;
|
|
}
|
|
|
|
if self.flags.hit_top_wall() {
|
|
self.vel_y = 0x40;
|
|
}
|
|
|
|
if self.flags.hit_bottom_wall() {
|
|
self.vel_y = -0x40;
|
|
}
|
|
} else {
|
|
if self.action_num == 0 {
|
|
self.action_num = 1;
|
|
self.anim_num = self.rng.range(0..4) as u16;
|
|
|
|
self.vel_x = self.rng.range(-0x200..0x200) as i32;
|
|
self.vel_y = self.rng.range(-0x400..0) as i32;
|
|
|
|
self.direction = if self.rng.range(0..1) != 0 { Direction::Left } else { Direction::Right };
|
|
}
|
|
|
|
self.vel_y += if self.flags.in_water() { 0x15 } else { 0x2a };
|
|
|
|
if self.flags.hit_left_wall() && self.vel_x < 0 {
|
|
self.vel_x = -self.vel_x;
|
|
}
|
|
|
|
if self.flags.hit_right_wall() && self.vel_x > 0 {
|
|
self.vel_x = -self.vel_x;
|
|
}
|
|
|
|
if self.flags.hit_top_wall() && self.vel_y < 0 {
|
|
self.vel_y = -self.vel_y;
|
|
}
|
|
|
|
if self.flags.hit_bottom_wall() {
|
|
state.sound_manager.play_sfx(45);
|
|
|
|
self.vel_y = -0x280;
|
|
self.vel_x = 2 * self.vel_x / 3;
|
|
}
|
|
|
|
if self.flags.hit_left_wall() || self.flags.hit_right_wall() || self.flags.hit_bottom_wall() {
|
|
state.sound_manager.play_sfx(45);
|
|
self.action_counter2 += 1;
|
|
|
|
if self.action_counter2 > 2 {
|
|
self.vel_y -= 0x200;
|
|
}
|
|
} else {
|
|
self.action_counter2 = 0;
|
|
}
|
|
|
|
self.vel_x = self.vel_x.clamp(-0x5ff, 0x5ff);
|
|
self.vel_y = self.vel_y.clamp(-0x5ff, 0x5ff);
|
|
}
|
|
|
|
self.x += self.vel_x;
|
|
self.y += self.vel_y;
|
|
|
|
self.anim_counter += 1;
|
|
|
|
if self.direction == Direction::Left {
|
|
if self.anim_counter > 2 {
|
|
self.anim_counter = 0;
|
|
|
|
self.anim_num += 1;
|
|
if self.anim_num > 5 {
|
|
self.anim_num = 0;
|
|
}
|
|
}
|
|
} else if self.anim_counter > 2 {
|
|
self.anim_counter = 0;
|
|
|
|
if self.anim_num > 0 {
|
|
self.anim_num -= 1;
|
|
} else {
|
|
self.anim_num = 5;
|
|
}
|
|
}
|
|
|
|
self.anim_rect = state.constants.npc.n001_experience[self.anim_num as usize];
|
|
|
|
if self.action_num != 0 {
|
|
if self.exp >= 20 {
|
|
self.anim_rect.top += 32;
|
|
self.anim_rect.bottom += 32;
|
|
} else if self.exp >= 5 {
|
|
self.anim_rect.top += 16;
|
|
self.anim_rect.bottom += 16;
|
|
}
|
|
|
|
self.action_num = 1;
|
|
}
|
|
|
|
self.action_counter += 1;
|
|
if self.action_counter > 500 && self.anim_num == 5 && self.anim_counter == 2 {
|
|
self.cond.set_alive(false);
|
|
return Ok(());
|
|
}
|
|
|
|
if self.action_counter > 400 && (self.action_counter & 0x02) != 0 {
|
|
self.anim_rect.left = 0;
|
|
self.anim_rect.top = 0;
|
|
self.anim_rect.right = 0;
|
|
self.anim_rect.bottom = 0;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub(crate) fn tick_n086_missile_pickup(&mut self, state: &mut SharedGameState, stage: &mut Stage) -> GameResult {
|
|
if self.direction == Direction::Left {
|
|
self.anim_counter += 1;
|
|
if self.anim_counter > 2 {
|
|
self.anim_counter = 0;
|
|
self.anim_num += 1;
|
|
if self.anim_num > 1 {
|
|
self.anim_num = 0;
|
|
}
|
|
}
|
|
|
|
self.action_counter2 += 1;
|
|
}
|
|
|
|
if stage.data.background_type == BackgroundType::Scrolling || stage.data.background_type == BackgroundType::OutsideWind {
|
|
if self.action_num == 0 {
|
|
self.action_num = 1;
|
|
self.vel_x = self.rng.range(0x7f..0x100) as i32;
|
|
self.vel_y = self.rng.range(-0x20..0x20) as i32;
|
|
}
|
|
|
|
self.vel_x -= 0x08;
|
|
if self.x < 0xa000 {
|
|
self.cond.set_alive(false)
|
|
}
|
|
|
|
if self.flags.hit_left_wall() {
|
|
self.vel_x = 0x100;
|
|
}
|
|
|
|
if self.flags.hit_top_wall() {
|
|
self.vel_y = 0x40;
|
|
}
|
|
|
|
if self.flags.hit_bottom_wall() {
|
|
self.vel_y = -0x40;
|
|
}
|
|
|
|
self.x += self.vel_x;
|
|
self.y += self.vel_y;
|
|
}
|
|
|
|
match self.exp {
|
|
1 => {
|
|
self.anim_rect = state.constants.npc.n086_missile_pickup[self.anim_num as usize];
|
|
}
|
|
3 => {
|
|
self.anim_rect = state.constants.npc.n086_missile_pickup[2 + self.anim_num as usize];
|
|
}
|
|
_ => (),
|
|
}
|
|
|
|
if self.action_counter2 > 550 {
|
|
self.cond.set_alive(false);
|
|
}
|
|
|
|
if self.action_counter2 > 500 && self.action_counter2 & 0x02 != 0 {
|
|
self.anim_rect.right = self.anim_rect.left;
|
|
self.anim_rect.bottom = self.anim_rect.top;
|
|
}
|
|
|
|
if self.action_counter2 > 547 {
|
|
self.anim_rect = state.constants.npc.n086_missile_pickup[4];
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub(crate) fn tick_n087_heart_pickup(&mut self, state: &mut SharedGameState, stage: &mut Stage) -> GameResult {
|
|
if self.direction == Direction::Left {
|
|
self.anim_counter += 1;
|
|
if self.anim_counter > 2 {
|
|
self.anim_counter = 0;
|
|
self.anim_num += 1;
|
|
if self.anim_num > 1 {
|
|
self.anim_num = 0;
|
|
}
|
|
}
|
|
|
|
self.action_counter2 += 1;
|
|
}
|
|
|
|
if stage.data.background_type == BackgroundType::Scrolling || stage.data.background_type == BackgroundType::OutsideWind {
|
|
if self.action_num == 0 {
|
|
self.action_num = 1;
|
|
self.vel_x = self.rng.range(0x7f..0x100) as i32;
|
|
self.vel_y = self.rng.range(-0x20..0x20) as i32;
|
|
}
|
|
|
|
self.vel_x -= 0x08;
|
|
if self.x < 0xa000 {
|
|
self.cond.set_alive(false)
|
|
}
|
|
|
|
if self.flags.hit_left_wall() {
|
|
self.vel_x = 0x100;
|
|
}
|
|
|
|
if self.flags.hit_top_wall() {
|
|
self.vel_y = 0x40;
|
|
}
|
|
|
|
if self.flags.hit_bottom_wall() {
|
|
self.vel_y = -0x40;
|
|
}
|
|
|
|
self.x += self.vel_x;
|
|
self.y += self.vel_y;
|
|
}
|
|
|
|
match self.exp {
|
|
2 => {
|
|
self.anim_rect = state.constants.npc.n087_heart_pickup[self.anim_num as usize];
|
|
}
|
|
6 => {
|
|
self.anim_rect = state.constants.npc.n087_heart_pickup[2 + self.anim_num as usize];
|
|
}
|
|
_ => (),
|
|
}
|
|
|
|
if self.action_counter2 > 550 {
|
|
self.cond.set_alive(false);
|
|
}
|
|
|
|
if self.action_counter2 > 500 && self.action_counter2 & 0x02 != 0 {
|
|
self.anim_rect.right = self.anim_rect.left;
|
|
self.anim_rect.bottom = self.anim_rect.top;
|
|
}
|
|
|
|
if self.action_counter2 > 547 {
|
|
self.anim_rect = state.constants.npc.n087_heart_pickup[4];
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|