mirror of
https://github.com/doukutsu-rs/doukutsu-rs
synced 2024-09-27 20:48:54 +00:00
full implementation of grasstown npcs
This commit is contained in:
parent
e7d421f384
commit
5f2968fa0b
|
@ -311,8 +311,8 @@ pub struct NPCConsts {
|
||||||
#[serde(default = "default_n102_malco_computer_wave")]
|
#[serde(default = "default_n102_malco_computer_wave")]
|
||||||
pub n102_malco_computer_wave: [Rect<u16>; 4],
|
pub n102_malco_computer_wave: [Rect<u16>; 4],
|
||||||
|
|
||||||
#[serde(default = "default_n103_manaan_projectile")]
|
#[serde(default = "default_n103_mannan_projectile")]
|
||||||
pub n103_manaan_projectile: [Rect<u16>; 6],
|
pub n103_mannan_projectile: [Rect<u16>; 6],
|
||||||
|
|
||||||
#[serde(default = "default_n104_frog")]
|
#[serde(default = "default_n104_frog")]
|
||||||
pub n104_frog: [Rect<u16>; 6],
|
pub n104_frog: [Rect<u16>; 6],
|
||||||
|
@ -322,14 +322,14 @@ pub struct NPCConsts {
|
||||||
|
|
||||||
// pub n106_hey_bubble_high: () // Defined in code
|
// pub n106_hey_bubble_high: () // Defined in code
|
||||||
|
|
||||||
#[serde(default = "default_n107_malco_powered_on")]
|
#[serde(default = "default_n107_malco_broken")]
|
||||||
pub n107_malco_powered_on: [Rect<u16>; 10],
|
pub n107_malco_broken: [Rect<u16>; 10],
|
||||||
|
|
||||||
#[serde(default = "default_n108_balfrog_projectile")]
|
#[serde(default = "default_n108_balfrog_projectile")]
|
||||||
pub n108_balfrog_projectile: [Rect<u16>; 3],
|
pub n108_balfrog_projectile: [Rect<u16>; 3],
|
||||||
|
|
||||||
#[serde(default = "default_n109_malco_broken")]
|
#[serde(default = "default_n109_malco_powered_on")]
|
||||||
pub n109_malco_broken: [Rect<u16>; 4],
|
pub n109_malco_powered_on: [Rect<u16>; 4],
|
||||||
|
|
||||||
#[serde(default = "default_n110_puchi")]
|
#[serde(default = "default_n110_puchi")]
|
||||||
pub n110_puchi: [Rect<u16>; 6],
|
pub n110_puchi: [Rect<u16>; 6],
|
||||||
|
@ -2243,7 +2243,7 @@ fn default_n102_malco_computer_wave() -> [Rect<u16>; 4] {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_n103_manaan_projectile() -> [Rect<u16>; 6] {
|
fn default_n103_mannan_projectile() -> [Rect<u16>; 6] {
|
||||||
[
|
[
|
||||||
Rect { left: 192, top: 96, right: 208, bottom: 120 },
|
Rect { left: 192, top: 96, right: 208, bottom: 120 },
|
||||||
Rect { left: 208, top: 96, right: 224, bottom: 120 },
|
Rect { left: 208, top: 96, right: 224, bottom: 120 },
|
||||||
|
@ -2272,7 +2272,7 @@ fn default_n105_hey_bubble_low() -> [Rect<u16>; 2] {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_n107_malco_powered_on() -> [Rect<u16>; 10] {
|
fn default_n107_malco_broken() -> [Rect<u16>; 10] {
|
||||||
[
|
[
|
||||||
Rect { left: 144, top: 0, right: 160, bottom: 24 },
|
Rect { left: 144, top: 0, right: 160, bottom: 24 },
|
||||||
Rect { left: 160, top: 0, right: 176, bottom: 24 },
|
Rect { left: 160, top: 0, right: 176, bottom: 24 },
|
||||||
|
@ -2295,7 +2295,7 @@ fn default_n108_balfrog_projectile() -> [Rect<u16>; 3] {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_n109_malco_broken() -> [Rect<u16>; 4] {
|
fn default_n109_malco_powered_on() -> [Rect<u16>; 4] {
|
||||||
[
|
[
|
||||||
Rect { left: 240, top: 0, right: 256, bottom: 24 },
|
Rect { left: 240, top: 0, right: 256, bottom: 24 },
|
||||||
Rect { left: 256, top: 0, right: 272, bottom: 24 },
|
Rect { left: 256, top: 0, right: 272, bottom: 24 },
|
||||||
|
|
|
@ -5,7 +5,7 @@ use ggez::GameResult;
|
||||||
use num_traits::clamp;
|
use num_traits::clamp;
|
||||||
|
|
||||||
use crate::caret::CaretType;
|
use crate::caret::CaretType;
|
||||||
use crate::common::Direction;
|
use crate::common::{CDEG_RAD, Direction};
|
||||||
use crate::npc::{NPC, NPCMap};
|
use crate::npc::{NPC, NPCMap};
|
||||||
use crate::player::Player;
|
use crate::player::Player;
|
||||||
use crate::shared_game_state::SharedGameState;
|
use crate::shared_game_state::SharedGameState;
|
||||||
|
@ -611,6 +611,194 @@ impl NPC {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn tick_n033_balrog_bouncing_projectile(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||||
|
if self.flags.hit_left_wall() || self.flags.hit_right_wall() {
|
||||||
|
self.cond.set_alive(false);
|
||||||
|
state.create_caret(self.x, self.y, CaretType::ProjectileDissipation, Direction::Left);
|
||||||
|
} else if self.flags.hit_bottom_wall() {
|
||||||
|
self.vel_y = -2 * 0x200;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.vel_y += 0x2a;
|
||||||
|
|
||||||
|
self.x += self.vel_x;
|
||||||
|
self.y += self.vel_y;
|
||||||
|
|
||||||
|
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.anim_rect = state.constants.npc.n033_balrog_bouncing_projectile[self.anim_num as usize];
|
||||||
|
|
||||||
|
self.action_counter += 1;
|
||||||
|
if self.action_counter > 250 {
|
||||||
|
self.cond.set_alive(false);
|
||||||
|
state.create_caret(self.x, self.y, CaretType::ProjectileDissipation, Direction::Left);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn tick_n036_balrog_hover(&mut self, state: &mut SharedGameState, player: &Player) -> GameResult {
|
||||||
|
match self.action_num {
|
||||||
|
0 | 1 => {
|
||||||
|
if self.action_num == 0 {
|
||||||
|
self.action_num = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.action_counter += 1;
|
||||||
|
if self.action_counter > 12 {
|
||||||
|
self.action_num = 2;
|
||||||
|
self.action_counter = 0;
|
||||||
|
self.anim_num = 1;
|
||||||
|
self.vel_x2 = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2 => {
|
||||||
|
self.action_counter += 1;
|
||||||
|
if self.action_counter > 16 {
|
||||||
|
self.vel_x2 -= 1;
|
||||||
|
self.action_counter = 0;
|
||||||
|
|
||||||
|
let angle = f64::atan2((self.y - player.y) as f64, (self.x - player.x) as f64)
|
||||||
|
+ state.game_rng.range(-16..16) as f64 * CDEG_RAD;
|
||||||
|
|
||||||
|
let mut npc = NPCMap::create_npc(11, &state.npc_table);
|
||||||
|
npc.cond.set_alive(true);
|
||||||
|
npc.vel_x = (angle.cos() * -512.0) as isize;
|
||||||
|
npc.vel_y = (angle.sin() * -512.0) as isize;
|
||||||
|
npc.x = self.x;
|
||||||
|
npc.y = self.y + 4 * 0x200;
|
||||||
|
|
||||||
|
state.new_npcs.push(npc);
|
||||||
|
state.sound_manager.play_sfx(39);
|
||||||
|
|
||||||
|
if self.vel_x2 == 0 {
|
||||||
|
self.action_num = 3;
|
||||||
|
self.action_counter = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
3 => {
|
||||||
|
self.action_counter += 1;
|
||||||
|
if self.action_counter > 3 {
|
||||||
|
self.action_num = 4;
|
||||||
|
self.action_counter = 0;
|
||||||
|
self.anim_num = 3;
|
||||||
|
|
||||||
|
self.vel_x = (player.x - self.x) / 100;
|
||||||
|
self.vel_y = -3 * 0x200;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
4 => {
|
||||||
|
if self.vel_y > -0x200 {
|
||||||
|
if self.life > 60 {
|
||||||
|
self.action_num = 5;
|
||||||
|
self.action_counter = 0;
|
||||||
|
self.anim_num = 4;
|
||||||
|
self.anim_counter = 0;
|
||||||
|
self.target_y = self.y;
|
||||||
|
} else {
|
||||||
|
self.action_num = 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
5 => {
|
||||||
|
self.anim_counter += 1;
|
||||||
|
if self.anim_counter > 1 {
|
||||||
|
self.anim_counter = 0;
|
||||||
|
self.anim_num += 1;
|
||||||
|
if self.anim_num > 5 {
|
||||||
|
self.anim_num = 4;
|
||||||
|
state.sound_manager.play_sfx(47);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.action_counter += 1;
|
||||||
|
if self.action_counter > 100 {
|
||||||
|
self.action_num = 6;
|
||||||
|
self.anim_num = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.vel_y += ((self.target_y - self.y).signum() | 1) * 0x40;
|
||||||
|
self.vel_y = clamp(self.vel_y, -0x200, 0x200);
|
||||||
|
}
|
||||||
|
6 => {
|
||||||
|
if self.y + 16 * 0x200 < player.y {
|
||||||
|
self.damage = 10;
|
||||||
|
} else {
|
||||||
|
self.damage = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.flags.hit_bottom_wall() {
|
||||||
|
self.action_num = 7;
|
||||||
|
self.action_counter = 0;
|
||||||
|
self.anim_num = 2;
|
||||||
|
self.damage = 0;
|
||||||
|
|
||||||
|
state.sound_manager.play_sfx(25);
|
||||||
|
state.sound_manager.play_sfx(26);
|
||||||
|
state.quake_counter = 30;
|
||||||
|
|
||||||
|
let mut npc_smoke = NPCMap::create_npc(4, &state.npc_table);
|
||||||
|
let mut npc_proj = NPCMap::create_npc(33, &state.npc_table);
|
||||||
|
for _ in 0..8 {
|
||||||
|
npc_smoke.cond.set_alive(true);
|
||||||
|
npc_smoke.direction = Direction::Left;
|
||||||
|
npc_smoke.x = self.x + state.game_rng.range(-12..12) as isize * 0x200;
|
||||||
|
npc_smoke.y = self.y + state.game_rng.range(-12..12) as isize * 0x200;
|
||||||
|
npc_smoke.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||||
|
npc_smoke.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||||
|
|
||||||
|
npc_proj.cond.set_alive(true);
|
||||||
|
npc_proj.direction = Direction::Left;
|
||||||
|
npc_proj.x = self.x + state.game_rng.range(-12..12) as isize * 0x200;
|
||||||
|
npc_proj.y = self.y + state.game_rng.range(-12..12) as isize * 0x200;
|
||||||
|
npc_proj.vel_x = state.game_rng.range(-0x400..0x400) as isize;
|
||||||
|
npc_proj.vel_y = state.game_rng.range(-0x400..0) as isize;
|
||||||
|
|
||||||
|
state.new_npcs.push(npc_smoke);
|
||||||
|
state.new_npcs.push(npc_proj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
7 => {
|
||||||
|
self.vel_x = 0;
|
||||||
|
|
||||||
|
self.action_counter += 1;
|
||||||
|
if self.action_counter > 3 {
|
||||||
|
self.action_num = 1;
|
||||||
|
self.action_counter = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.action_num != 5 {
|
||||||
|
self.vel_y += 0x33;
|
||||||
|
self.direction = if self.x < player.x { Direction::Right } else { Direction::Left };
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.vel_y > 0x5ff {
|
||||||
|
self.vel_y = 0x5ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.x += self.vel_x;
|
||||||
|
self.y += self.vel_y;
|
||||||
|
|
||||||
|
let dir_offset = if self.direction == Direction::Left { 0 } else { 6 };
|
||||||
|
|
||||||
|
self.anim_rect = state.constants.npc.n036_balrog_hover[self.anim_num as usize + dir_offset];
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn tick_n068_balrog_running(&mut self, state: &mut SharedGameState, player: &mut Player) -> GameResult {
|
pub(crate) fn tick_n068_balrog_running(&mut self, state: &mut SharedGameState, player: &mut Player) -> GameResult {
|
||||||
match self.action_num {
|
match self.action_num {
|
||||||
0 | 1 => {
|
0 | 1 => {
|
||||||
|
|
|
@ -607,7 +607,7 @@ impl NPC {
|
||||||
} else {
|
} else {
|
||||||
self.action_counter2 += 1;
|
self.action_counter2 += 1;
|
||||||
if (self.action_counter2 % 8) == 0 && abs(self.x - player.x) < 160 * 0x200 {
|
if (self.action_counter2 % 8) == 0 && abs(self.x - player.x) < 160 * 0x200 {
|
||||||
let angle = ((player.y - self.y) as f64 / (player.x - self.x) as f64).atan()
|
let angle = ((self.y - player.y) as f64 / (self.x - player.x) as f64).atan()
|
||||||
+ (state.game_rng.range(-6..6) as u8) as f64 * CDEG_RAD;
|
+ (state.game_rng.range(-6..6) as u8) as f64 * CDEG_RAD;
|
||||||
|
|
||||||
let mut npc = NPCMap::create_npc(84, &state.npc_table);
|
let mut npc = NPCMap::create_npc(84, &state.npc_table);
|
||||||
|
@ -618,6 +618,7 @@ impl NPC {
|
||||||
npc.vel_y = (angle.sin() * 1024.0) as isize;
|
npc.vel_y = (angle.sin() * 1024.0) as isize;
|
||||||
|
|
||||||
state.new_npcs.push(npc);
|
state.new_npcs.push(npc);
|
||||||
|
state.sound_manager.play_sfx(39);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.action_counter2 > 8 {
|
if self.action_counter2 > 8 {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
|
use ggez::GameResult;
|
||||||
use num_traits::abs;
|
use num_traits::abs;
|
||||||
use num_traits::clamp;
|
use num_traits::clamp;
|
||||||
|
|
||||||
use crate::common::Direction;
|
use crate::common::Direction;
|
||||||
use ggez::GameResult;
|
|
||||||
use crate::npc::{NPC, NPCMap};
|
use crate::npc::{NPC, NPCMap};
|
||||||
use crate::player::Player;
|
use crate::player::Player;
|
||||||
use crate::shared_game_state::SharedGameState;
|
use crate::shared_game_state::SharedGameState;
|
||||||
|
@ -17,8 +17,8 @@ impl NPC {
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.action_counter >= 8
|
if self.action_counter >= 8
|
||||||
&& abs(self.x - player.x) < (112 * 0x200)
|
&& abs(self.x - player.x) < (128 * 0x200)
|
||||||
&& abs(self.y - player.y) < (80 * 0x200) {
|
&& self.y - 128 * 0x200 < player.y && self.y + 48 * 0x200 > player.y {
|
||||||
if self.x > player.x {
|
if self.x > player.x {
|
||||||
self.direction = Direction::Left;
|
self.direction = Direction::Left;
|
||||||
} else {
|
} else {
|
||||||
|
@ -74,7 +74,7 @@ impl NPC {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
4 => {
|
4 => {
|
||||||
if self.x > player.x {
|
if self.x >= player.x {
|
||||||
self.direction = Direction::Left;
|
self.direction = Direction::Left;
|
||||||
} else {
|
} else {
|
||||||
self.direction = Direction::Right;
|
self.direction = Direction::Right;
|
||||||
|
@ -89,18 +89,18 @@ impl NPC {
|
||||||
self.anim_num = 2;
|
self.anim_num = 2;
|
||||||
self.vel_x /= 2;
|
self.vel_x /= 2;
|
||||||
self.damage = 12;
|
self.damage = 12;
|
||||||
}
|
} else {
|
||||||
|
if self.action_counter % 4 == 1 {
|
||||||
|
state.sound_manager.play_sfx(110);
|
||||||
|
}
|
||||||
|
|
||||||
if self.action_counter % 4 == 1 {
|
self.anim_counter += 1;
|
||||||
state.sound_manager.play_sfx(110);
|
if self.anim_counter > 0 {
|
||||||
}
|
self.anim_counter = 0;
|
||||||
|
self.anim_num += 1;
|
||||||
self.anim_counter += 1;
|
if self.anim_num > 5 {
|
||||||
if self.anim_counter > 0 {
|
self.anim_num = 3;
|
||||||
self.anim_counter = 0;
|
}
|
||||||
self.anim_num += 1;
|
|
||||||
if self.anim_num > 5 {
|
|
||||||
self.anim_num = 3;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -347,8 +347,102 @@ impl NPC {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn tick_n031_bat_hanging(&mut self, state: &mut SharedGameState, player: &Player) -> GameResult {
|
||||||
|
match self.action_num {
|
||||||
|
0 | 1 => {
|
||||||
|
if self.action_num == 0 {
|
||||||
|
self.action_num = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if state.game_rng.range(0..120) == 10 {
|
||||||
|
self.action_num = 2;
|
||||||
|
self.action_counter = 0;
|
||||||
|
self.anim_num = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if abs(self.x - player.x) < 8 * 0x200
|
||||||
|
&& self.y - 8 * 0x200 < player.y
|
||||||
|
&& self.y + 96 * 0x200 > player.y {
|
||||||
|
self.action_num = 3;
|
||||||
|
self.anim_num = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2 => {
|
||||||
|
self.action_counter += 1;
|
||||||
|
if self.action_counter > 8 {
|
||||||
|
self.action_num = 1;
|
||||||
|
self.anim_num = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
3 => {
|
||||||
|
self.anim_num = 0;
|
||||||
|
|
||||||
|
if self.shock > 0 || abs(self.x - player.x) > 20 * 0x200 {
|
||||||
|
self.action_num = 4;
|
||||||
|
self.action_counter = 0;
|
||||||
|
self.anim_num = 1;
|
||||||
|
self.anim_counter = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
4 => {
|
||||||
|
self.vel_y += 0x20;
|
||||||
|
if self.vel_y > 0x5ff {
|
||||||
|
self.vel_y = 0x5ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.action_counter += 1;
|
||||||
|
if self.action_counter >= 20 && (self.flags.hit_bottom_wall() || self.y > player.y - 16 * 0x200) {
|
||||||
|
self.action_num = 5;
|
||||||
|
self.anim_num = 2;
|
||||||
|
self.anim_counter = 0;
|
||||||
|
self.target_y = self.y;
|
||||||
|
|
||||||
|
if self.flags.hit_bottom_wall() {
|
||||||
|
self.vel_y = -0x200;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
5 => {
|
||||||
|
self.anim_counter += 1;
|
||||||
|
if self.anim_counter > 1 {
|
||||||
|
self.anim_counter = 0;
|
||||||
|
self.anim_num += 1;
|
||||||
|
if self.anim_num > 4 {
|
||||||
|
self.anim_num = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.direction = if player.x < self.x { Direction::Left} else {Direction::Right};
|
||||||
|
|
||||||
|
self.vel_x += (player.x - self.x).signum() * 0x10;
|
||||||
|
self.vel_y += (self.target_y - self.y).signum() * 0x10;
|
||||||
|
|
||||||
|
self.vel_x = clamp(self.vel_x, -0x200, 0x200);
|
||||||
|
self.vel_y = clamp(self.vel_y, -0x200, 0x200);
|
||||||
|
|
||||||
|
if self.flags.hit_bottom_wall() {
|
||||||
|
self.vel_y = -0x200;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.flags.hit_top_wall() {
|
||||||
|
self.vel_y = 0x200;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.x += self.vel_x;
|
||||||
|
self.y += self.vel_y;
|
||||||
|
|
||||||
|
let dir_offset = if self.direction == Direction::Left { 0 } else { 5 };
|
||||||
|
|
||||||
|
self.anim_rect = state.constants.npc.n031_bat_hanging[self.anim_num as usize + dir_offset];
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn tick_n035_mannan(&mut self, state: &mut SharedGameState) -> GameResult {
|
pub(crate) fn tick_n035_mannan(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||||
if self.action_num <= 2 && self.life <= 89 {
|
if self.action_num <= 2 && self.life < 90 {
|
||||||
self.action_num = 3;
|
self.action_num = 3;
|
||||||
self.action_counter = 0;
|
self.action_counter = 0;
|
||||||
self.anim_num = 2;
|
self.anim_num = 2;
|
||||||
|
@ -380,20 +474,21 @@ impl NPC {
|
||||||
self.action_num = 4;
|
self.action_num = 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if self.action_num >= 0 && self.shock > 0 {
|
} else if self.shock > 0 {
|
||||||
self.action_num = 2;
|
self.action_num = 2;
|
||||||
self.action_counter = 0;
|
self.action_counter = 0;
|
||||||
self.anim_num = 1;
|
self.anim_num = 1;
|
||||||
|
|
||||||
let mut npc = NPCMap::create_npc(103, &state.npc_table);
|
let mut npc = NPCMap::create_npc(103, &state.npc_table);
|
||||||
npc.cond.set_alive(true);
|
npc.cond.set_alive(true);
|
||||||
npc.x = self.x + self.direction.vector_x() * 32 * 0x200;
|
npc.x = self.x + self.direction.vector_x() * 8 * 0x200;
|
||||||
npc.y = self.y + 32 * 0x200;
|
npc.y = self.y + 8 * 0x200;
|
||||||
npc.direction = self.direction;
|
npc.direction = self.direction;
|
||||||
state.new_npcs.push(npc);
|
state.new_npcs.push(npc);
|
||||||
}
|
}
|
||||||
|
|
||||||
let dir_offset = if self.direction == Direction::Left { 0 } else { 4 };
|
let dir_offset = if self.direction == Direction::Left { 0 } else { 4 };
|
||||||
|
|
||||||
self.anim_rect = state.constants.npc.n035_mannan[self.anim_num as usize + dir_offset];
|
self.anim_rect = state.constants.npc.n035_mannan[self.anim_num as usize + dir_offset];
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -542,13 +637,14 @@ impl NPC {
|
||||||
if self.anim_counter > 5 {
|
if self.anim_counter > 5 {
|
||||||
self.anim_counter = 0;
|
self.anim_counter = 0;
|
||||||
self.anim_num += 1;
|
self.anim_num += 1;
|
||||||
if self.anim_num == 2 {
|
}
|
||||||
self.vel_x += self.direction.vector_x() * 0x100;
|
|
||||||
self.vel_y -= 0x200;
|
if self.anim_num == 2 {
|
||||||
} else if self.anim_num > 2 {
|
self.vel_x += self.direction.vector_x() * 0x100;
|
||||||
self.action_num = 12;
|
self.vel_y -= 0x200;
|
||||||
self.anim_num = 3;
|
} else if self.anim_num > 2 {
|
||||||
}
|
self.action_num = 12;
|
||||||
|
self.anim_num = 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
12 => {
|
12 => {
|
||||||
|
@ -590,10 +686,94 @@ impl NPC {
|
||||||
self.y += self.vel_y;
|
self.y += self.vel_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.anim_counter == 1 {
|
let dir_offset = if self.direction == Direction::Left { 0 } else { 4 };
|
||||||
let dir_offset = if self.direction == Direction::Left { 0 } else { 4 };
|
|
||||||
self.anim_rect = state.constants.npc.n095_jelly[self.anim_num as usize + dir_offset];
|
self.anim_rect = state.constants.npc.n095_jelly[self.anim_num as usize + dir_offset];
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn tick_n100_grate(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||||
|
if self.action_num == 0 {
|
||||||
|
self.y += 16 * 0x200;
|
||||||
|
self.action_num = 1;
|
||||||
|
|
||||||
|
self.anim_rect = if self.direction == Direction::Left {
|
||||||
|
state.constants.npc.n100_grate[0]
|
||||||
|
} else {
|
||||||
|
state.constants.npc.n100_grate[1]
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn tick_n101_malco_screen(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||||
|
self.anim_counter += 1;
|
||||||
|
if self.anim_counter > 3 {
|
||||||
|
self.anim_counter = 0;
|
||||||
|
self.anim_num += 1;
|
||||||
|
if self.anim_num > 2 {
|
||||||
|
self.anim_num = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.anim_rect = state.constants.npc.n101_malco_screen[self.anim_num as usize];
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn tick_n102_malco_computer_wave(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||||
|
if self.action_num == 0 {
|
||||||
|
self.action_num = 1;
|
||||||
|
self.y += 8 * 0x200;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.anim_counter += 1;
|
||||||
|
if self.anim_counter > 0 {
|
||||||
|
self.anim_counter = 0;
|
||||||
|
self.anim_num += 1;
|
||||||
|
if self.anim_num > 3 {
|
||||||
|
self.anim_num = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.anim_rect = state.constants.npc.n102_malco_computer_wave[self.anim_num as usize];
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn tick_n103_mannan_projectile(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||||
|
if self.action_num == 0 {
|
||||||
|
self.action_num == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.vel_x += self.direction.vector_x() * 0x20;
|
||||||
|
|
||||||
|
self.anim_counter += 1;
|
||||||
|
if self.anim_counter > 0 {
|
||||||
|
self.anim_counter = 0;
|
||||||
|
self.anim_num += 1;
|
||||||
|
if self.anim_num > 2 {
|
||||||
|
self.anim_num = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.x += self.vel_x;
|
||||||
|
|
||||||
|
self.action_counter2 += 1;
|
||||||
|
if self.action_counter2 > 100 {
|
||||||
|
self.cond.set_alive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.action_counter2 % 4 == 1 {
|
||||||
|
state.sound_manager.play_sfx(46);
|
||||||
|
}
|
||||||
|
|
||||||
|
let dir_offset = if self.direction == Direction::Left { 0 } else { 3 };
|
||||||
|
|
||||||
|
self.anim_rect = state.constants.npc.n103_mannan_projectile[self.anim_num as usize + dir_offset];
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -717,6 +897,241 @@ impl NPC {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn tick_n107_malco_broken(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||||
|
match self.action_num {
|
||||||
|
0 => {
|
||||||
|
self.action_num = 1;
|
||||||
|
|
||||||
|
if self.direction == Direction::Right {
|
||||||
|
self.anim_num = 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
10 | 11 => {
|
||||||
|
if self.action_num == 10 {
|
||||||
|
self.action_num = 11;
|
||||||
|
self.action_counter = 0;
|
||||||
|
self.anim_counter = 0;
|
||||||
|
|
||||||
|
let mut npc = NPCMap::create_npc(4, &state.npc_table);
|
||||||
|
for _ in 0..4 {
|
||||||
|
npc.cond.set_alive(true);
|
||||||
|
npc.x = self.x;
|
||||||
|
npc.y = self.y;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.anim_counter += 1;
|
||||||
|
if self.anim_counter > 1 {
|
||||||
|
state.sound_manager.play_sfx(43);
|
||||||
|
|
||||||
|
self.anim_counter = 0;
|
||||||
|
self.anim_num += 1;
|
||||||
|
if self.anim_num > 1 {
|
||||||
|
self.anim_num = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.action_counter += 1;
|
||||||
|
if self.action_counter > 100 {
|
||||||
|
self.action_num = 12;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
12 | 13 => {
|
||||||
|
if self.action_num == 12 {
|
||||||
|
self.action_num = 13;
|
||||||
|
self.action_counter = 0;
|
||||||
|
self.anim_num = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.action_counter += 1;
|
||||||
|
if self.action_counter > 50 {
|
||||||
|
self.action_num = 14;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
14 | 15 => {
|
||||||
|
if self.action_num == 14 {
|
||||||
|
self.action_num = 15;
|
||||||
|
self.action_counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.action_counter / 2 % 2 != 0 {
|
||||||
|
self.x += 0x200;
|
||||||
|
state.sound_manager.play_sfx(11);
|
||||||
|
} else {
|
||||||
|
self.x -= 0x200;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.action_counter += 1;
|
||||||
|
if self.action_counter > 50 {
|
||||||
|
self.action_num = 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
16 | 17 => {
|
||||||
|
if self.action_num == 16 {
|
||||||
|
self.action_num = 17;
|
||||||
|
self.action_counter = 0;
|
||||||
|
self.anim_num = 2;
|
||||||
|
state.sound_manager.play_sfx(12);
|
||||||
|
|
||||||
|
let mut npc = NPCMap::create_npc(4, &state.npc_table);
|
||||||
|
for _ in 0..8 {
|
||||||
|
npc.cond.set_alive(true);
|
||||||
|
npc.x = self.x;
|
||||||
|
npc.y = self.y;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.action_counter += 1;
|
||||||
|
if self.action_counter > 150 {
|
||||||
|
self.action_num = 18;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
18 | 19 => {
|
||||||
|
if self.action_num == 18 {
|
||||||
|
self.action_num = 19;
|
||||||
|
self.action_counter = 0;
|
||||||
|
self.anim_num = 3;
|
||||||
|
self.anim_counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.anim_counter += 1;
|
||||||
|
if self.anim_counter > 3 {
|
||||||
|
self.anim_counter = 0;
|
||||||
|
self.anim_num += 1;
|
||||||
|
if self.anim_num > 4 {
|
||||||
|
self.anim_num = 3;
|
||||||
|
state.sound_manager.play_sfx(11);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.action_counter += 1;
|
||||||
|
if self.action_counter > 100 {
|
||||||
|
self.action_num = 20;
|
||||||
|
state.sound_manager.play_sfx(12);
|
||||||
|
|
||||||
|
let mut npc = NPCMap::create_npc(4, &state.npc_table);
|
||||||
|
for _ in 0..4 {
|
||||||
|
npc.cond.set_alive(true);
|
||||||
|
npc.x = self.x;
|
||||||
|
npc.y = self.y;
|
||||||
|
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 => {
|
||||||
|
self.anim_num = 4;
|
||||||
|
}
|
||||||
|
21 => {
|
||||||
|
self.action_num = 22;
|
||||||
|
self.anim_num = 5;
|
||||||
|
|
||||||
|
state.sound_manager.play_sfx(51);
|
||||||
|
}
|
||||||
|
100 | 101 => {
|
||||||
|
if self.action_num == 100 {
|
||||||
|
self.action_num = 101;
|
||||||
|
self.anim_num = 6;
|
||||||
|
self.anim_counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.anim_counter += 1;
|
||||||
|
if self.anim_counter > 4 {
|
||||||
|
self.anim_counter = 0;
|
||||||
|
self.anim_num += 1;
|
||||||
|
if self.anim_num > 9 {
|
||||||
|
self.anim_num = 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
110 => {
|
||||||
|
self.cond.set_drs_destroyed(true);
|
||||||
|
self.cond.set_alive(false);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.anim_rect = state.constants.npc.n107_malco_broken[self.anim_num as usize];
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn tick_n109_malco_powered_on(&mut self, state: &mut SharedGameState, player: &Player) -> GameResult {
|
||||||
|
match self.action_num {
|
||||||
|
0 | 1 => {
|
||||||
|
if self.action_num == 0 {
|
||||||
|
if self.action_counter > 0 {
|
||||||
|
self.action_counter -= 1;
|
||||||
|
} else {
|
||||||
|
self.action_num = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.anim_num = 0;
|
||||||
|
self.action_counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if state.game_rng.range(0..120) == 10 {
|
||||||
|
self.action_num = 2;
|
||||||
|
self.action_counter = 0;
|
||||||
|
self.anim_num = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if abs(self.x - player.x) < 32 * 0x200
|
||||||
|
&& self.y - 32 * 0x200 < player.y
|
||||||
|
&& self.y + 16 * 0x200 > player.y {
|
||||||
|
self.direction = if self.x > player.x { Direction::Left } else { Direction::Right };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2 => {
|
||||||
|
self.action_counter += 1;
|
||||||
|
if self.action_counter > 8 {
|
||||||
|
self.action_num = 1;
|
||||||
|
self.anim_num = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
10 => {
|
||||||
|
self.action_num = 0;
|
||||||
|
state.sound_manager.play_sfx(12);
|
||||||
|
|
||||||
|
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.x;
|
||||||
|
npc.y = self.y;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.vel_y += 0x40;
|
||||||
|
if self.vel_y > 0x5ff {
|
||||||
|
self.vel_y = 0x5ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.y += self.vel_y;
|
||||||
|
|
||||||
|
let dir_offset = if self.direction == Direction::Left { 0 } else { 2 };
|
||||||
|
|
||||||
|
self.anim_rect = state.constants.npc.n109_malco_powered_on[self.anim_num as usize + dir_offset];
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn tick_n110_puchi(&mut self, state: &mut SharedGameState, player: &Player) -> GameResult {
|
pub(crate) fn tick_n110_puchi(&mut self, state: &mut SharedGameState, player: &Player) -> GameResult {
|
||||||
match self.action_num {
|
match self.action_num {
|
||||||
0 => {
|
0 => {
|
||||||
|
@ -832,6 +1247,7 @@ impl NPC {
|
||||||
self.y += self.vel_y;
|
self.y += self.vel_y;
|
||||||
|
|
||||||
let dir_offset = if self.direction == Direction::Left { 0 } else { 3 };
|
let dir_offset = if self.direction == Direction::Left { 0 } else { 3 };
|
||||||
|
|
||||||
self.anim_rect = state.constants.npc.n110_puchi[self.anim_num as usize + dir_offset];
|
self.anim_rect = state.constants.npc.n110_puchi[self.anim_num as usize + dir_offset];
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
100
src/npc/misc.rs
100
src/npc/misc.rs
|
@ -841,6 +841,106 @@ impl NPC {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn tick_n105_hey_bubble_low(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||||
|
self.action_counter += 1;
|
||||||
|
|
||||||
|
if self.action_counter < 5 {
|
||||||
|
self.y -= 0x200
|
||||||
|
} else if self.action_counter > 30 {
|
||||||
|
self.cond.set_alive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.anim_rect = state.constants.npc.n105_hey_bubble_low[self.anim_num as usize];
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn tick_n106_hey_bubble_high(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||||
|
if self.action_num == 0 {
|
||||||
|
self.action_num = 1;
|
||||||
|
|
||||||
|
let mut npc = NPCMap::create_npc(105, &state.npc_table);
|
||||||
|
npc.cond.set_alive(true);
|
||||||
|
npc.x = self.x;
|
||||||
|
npc.y = self.y - 8 * 0x200;
|
||||||
|
|
||||||
|
state.new_npcs.push(npc);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn tick_n114_press(&mut self, state: &mut SharedGameState, player: &Player) -> GameResult {
|
||||||
|
match self.action_num {
|
||||||
|
0 | 1 => {
|
||||||
|
if self.action_num == 0 {
|
||||||
|
self.action_num = 1;
|
||||||
|
self.y -= 4 * 0x200;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.flags.hit_bottom_wall() {
|
||||||
|
self.action_num = 10;
|
||||||
|
self.anim_num = 1;
|
||||||
|
self.anim_counter = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
10 => {
|
||||||
|
self.anim_counter += 1;
|
||||||
|
if self.anim_counter > 2{
|
||||||
|
self.anim_counter = 0;
|
||||||
|
self.anim_num += 1;
|
||||||
|
if self.anim_num > 2 {
|
||||||
|
self.anim_num = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if player.y > self.y {
|
||||||
|
self.npc_flags.set_solid_hard(false);
|
||||||
|
self.damage = 127;
|
||||||
|
} else {
|
||||||
|
self.npc_flags.set_solid_hard(true);
|
||||||
|
self.damage = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.flags.hit_bottom_wall() {
|
||||||
|
if self.anim_num > 1 {
|
||||||
|
let mut npc = NPCMap::create_npc(4, &state.npc_table);
|
||||||
|
for _ in 0..4 {
|
||||||
|
npc.cond.set_alive(true);
|
||||||
|
npc.x = self.x;
|
||||||
|
npc.y = self.y;
|
||||||
|
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 = 10;
|
||||||
|
state.sound_manager.play_sfx(26);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.action_num = 1;
|
||||||
|
self.anim_num = 0;
|
||||||
|
self.damage = 0;
|
||||||
|
self.npc_flags.set_solid_hard(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.vel_y += 0x20;
|
||||||
|
|
||||||
|
if self.vel_y > 0x5ff {
|
||||||
|
self.vel_y = 0x5ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.y += self.vel_y;
|
||||||
|
|
||||||
|
self.anim_rect = state.constants.npc.n114_press[self.anim_num as usize];
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn tick_n149_horizontal_moving_block(&mut self, state: &mut SharedGameState, player: &Player) -> GameResult {
|
pub(crate) fn tick_n149_horizontal_moving_block(&mut self, state: &mut SharedGameState, player: &Player) -> GameResult {
|
||||||
match self.action_num {
|
match self.action_num {
|
||||||
0 => {
|
0 => {
|
||||||
|
|
|
@ -197,12 +197,16 @@ impl GameEntity<(&mut Player, &BTreeMap<u16, RefCell<NPC>>, &mut Stage)> for NPC
|
||||||
28 => self.tick_n028_flying_critter(state, player),
|
28 => self.tick_n028_flying_critter(state, player),
|
||||||
29 => self.tick_n029_cthulhu(state, player),
|
29 => self.tick_n029_cthulhu(state, player),
|
||||||
30 => self.tick_n030_gunsmith(state),
|
30 => self.tick_n030_gunsmith(state),
|
||||||
|
31 => self.tick_n031_bat_hanging(state, player),
|
||||||
32 => self.tick_n032_life_capsule(state),
|
32 => self.tick_n032_life_capsule(state),
|
||||||
|
33 => self.tick_n033_balrog_bouncing_projectile(state),
|
||||||
34 => self.tick_n034_bed(state),
|
34 => self.tick_n034_bed(state),
|
||||||
35 => self.tick_n035_mannan(state),
|
35 => self.tick_n035_mannan(state),
|
||||||
|
36 => self.tick_n036_balrog_hover(state, player),
|
||||||
37 => self.tick_n037_sign(state),
|
37 => self.tick_n037_sign(state),
|
||||||
38 => self.tick_n038_fireplace(state),
|
38 => self.tick_n038_fireplace(state),
|
||||||
39 => self.tick_n039_save_sign(state),
|
39 => self.tick_n039_save_sign(state),
|
||||||
|
40 => self.tick_n040_santa(state, player),
|
||||||
41 => self.tick_n041_busted_door(state),
|
41 => self.tick_n041_busted_door(state),
|
||||||
42 => self.tick_n042_sue(state, player, map),
|
42 => self.tick_n042_sue(state, player, map),
|
||||||
43 => self.tick_n043_chalkboard(state),
|
43 => self.tick_n043_chalkboard(state),
|
||||||
|
@ -250,11 +254,20 @@ impl GameEntity<(&mut Player, &BTreeMap<u16, RefCell<NPC>>, &mut Stage)> for NPC
|
||||||
97 => self.tick_n097_fan_up(state, player),
|
97 => self.tick_n097_fan_up(state, player),
|
||||||
98 => self.tick_n098_fan_right(state, player),
|
98 => self.tick_n098_fan_right(state, player),
|
||||||
99 => self.tick_n099_fan_down(state, player),
|
99 => self.tick_n099_fan_down(state, player),
|
||||||
|
100 => self.tick_n100_grate(state),
|
||||||
|
101 => self.tick_n101_malco_screen(state),
|
||||||
|
102 => self.tick_n102_malco_computer_wave(state),
|
||||||
|
103 => self.tick_n103_mannan_projectile(state),
|
||||||
104 => self.tick_n104_frog(state, player),
|
104 => self.tick_n104_frog(state, player),
|
||||||
|
105 => self.tick_n105_hey_bubble_low(state),
|
||||||
|
106 => self.tick_n106_hey_bubble_high(state),
|
||||||
|
107 => self.tick_n107_malco_broken(state),
|
||||||
108 => self.tick_n108_balfrog_projectile(state),
|
108 => self.tick_n108_balfrog_projectile(state),
|
||||||
|
109 => self.tick_n109_malco_powered_on(state, player),
|
||||||
110 => self.tick_n110_puchi(state, player),
|
110 => self.tick_n110_puchi(state, player),
|
||||||
111 => self.tick_n111_quote_teleport_out(state, player),
|
111 => self.tick_n111_quote_teleport_out(state, player),
|
||||||
112 => self.tick_n112_quote_teleport_in(state, player),
|
112 => self.tick_n112_quote_teleport_in(state, player),
|
||||||
|
114 => self.tick_n114_press(state, player),
|
||||||
129 => self.tick_n129_fireball_snake_trail(state),
|
129 => self.tick_n129_fireball_snake_trail(state),
|
||||||
149 => self.tick_n149_horizontal_moving_block(state, player),
|
149 => self.tick_n149_horizontal_moving_block(state, player),
|
||||||
150 => self.tick_n150_quote(state, player),
|
150 => self.tick_n150_quote(state, player),
|
||||||
|
|
|
@ -1,5 +1,72 @@
|
||||||
|
use ggez::GameResult;
|
||||||
|
|
||||||
use crate::npc::NPC;
|
use crate::npc::NPC;
|
||||||
|
use crate::shared_game_state::SharedGameState;
|
||||||
|
use crate::player::Player;
|
||||||
|
use num_traits::abs;
|
||||||
|
use crate::common::Direction;
|
||||||
|
|
||||||
impl NPC {
|
impl NPC {
|
||||||
|
pub(crate) fn tick_n040_santa(&mut self, state: &mut SharedGameState, player: &Player) -> GameResult {
|
||||||
|
match self.action_num {
|
||||||
|
0 | 1 =>{
|
||||||
|
if self.action_num == 0 {
|
||||||
|
self.action_num = 1;
|
||||||
|
self.anim_num = 0;
|
||||||
|
self.anim_counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if state.game_rng.range(0..120) == 0 {
|
||||||
|
self.action_num = 2;
|
||||||
|
self.action_counter = 0;
|
||||||
|
self.anim_num = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if abs(self.x - player.x) < 32 * 0x200
|
||||||
|
&& self.y - 32 * 0x200 < player.y && self.y + 16 * 0x200 > player.y {
|
||||||
|
self.direction = if self.x > player.x {
|
||||||
|
Direction::Left
|
||||||
|
} else {
|
||||||
|
Direction::Right
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2 => {
|
||||||
|
self.action_counter += 1;
|
||||||
|
if self.action_counter > 8 {
|
||||||
|
self.action_num = 1;
|
||||||
|
self.anim_num = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
3 | 4 => {
|
||||||
|
if self.action_num == 3 {
|
||||||
|
self.action_num = 4;
|
||||||
|
self.anim_num =2;
|
||||||
|
self.anim_counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.anim_counter += 1;
|
||||||
|
if self.anim_counter > 4 {
|
||||||
|
self.anim_counter = 0;
|
||||||
|
self.anim_num += 1;
|
||||||
|
|
||||||
|
if self.anim_num > 5 {
|
||||||
|
self.anim_num = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.x += self.direction.vector_x() * 0x200;
|
||||||
|
}
|
||||||
|
5 => {
|
||||||
|
self.anim_num = 6;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
let dir_offset = if self.direction == Direction::Left { 0 } else { 7 };
|
||||||
|
|
||||||
|
self.anim_rect = state.constants.npc.n040_santa[self.anim_num as usize + dir_offset];
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1398,45 +1398,6 @@ impl Scene for GameScene {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_tick(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
|
||||||
self.frame.prev_x = self.frame.x;
|
|
||||||
self.frame.prev_y = self.frame.y;
|
|
||||||
self.player.prev_x = self.player.x;
|
|
||||||
self.player.prev_y = self.player.y;
|
|
||||||
|
|
||||||
for npc_cell in self.npc_map.npcs.values() {
|
|
||||||
let mut npc = npc_cell.borrow_mut();
|
|
||||||
|
|
||||||
if npc.cond.alive() {
|
|
||||||
npc.prev_x = npc.x;
|
|
||||||
npc.prev_y = npc.y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for npc in self.npc_map.boss_map.parts.iter_mut() {
|
|
||||||
if npc.cond.alive() {
|
|
||||||
npc.prev_x = npc.x;
|
|
||||||
npc.prev_y = npc.y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for bullet in self.bullet_manager.bullets.iter_mut() {
|
|
||||||
if bullet.cond.alive() {
|
|
||||||
bullet.prev_x = bullet.x;
|
|
||||||
bullet.prev_y = bullet.y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for caret in state.carets.iter_mut() {
|
|
||||||
if caret.cond.alive() {
|
|
||||||
caret.prev_x = caret.x;
|
|
||||||
caret.prev_y = caret.y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn tick(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
fn tick(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
||||||
state.update_key_trigger();
|
state.update_key_trigger();
|
||||||
|
|
||||||
|
@ -1481,6 +1442,45 @@ impl Scene for GameScene {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn draw_tick(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
||||||
|
self.frame.prev_x = self.frame.x;
|
||||||
|
self.frame.prev_y = self.frame.y;
|
||||||
|
self.player.prev_x = self.player.x;
|
||||||
|
self.player.prev_y = self.player.y;
|
||||||
|
|
||||||
|
for npc_cell in self.npc_map.npcs.values() {
|
||||||
|
let mut npc = npc_cell.borrow_mut();
|
||||||
|
|
||||||
|
if npc.cond.alive() {
|
||||||
|
npc.prev_x = npc.x;
|
||||||
|
npc.prev_y = npc.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for npc in self.npc_map.boss_map.parts.iter_mut() {
|
||||||
|
if npc.cond.alive() {
|
||||||
|
npc.prev_x = npc.x;
|
||||||
|
npc.prev_y = npc.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for bullet in self.bullet_manager.bullets.iter_mut() {
|
||||||
|
if bullet.cond.alive() {
|
||||||
|
bullet.prev_x = bullet.x;
|
||||||
|
bullet.prev_y = bullet.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for caret in state.carets.iter_mut() {
|
||||||
|
if caret.cond.alive() {
|
||||||
|
caret.prev_x = caret.x;
|
||||||
|
caret.prev_y = caret.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn draw(&self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
fn draw(&self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
||||||
graphics::set_canvas(ctx, Some(&state.game_canvas));
|
graphics::set_canvas(ctx, Some(&state.game_canvas));
|
||||||
self.draw_background(state, ctx)?;
|
self.draw_background(state, ctx)?;
|
||||||
|
|
Loading…
Reference in a new issue