2020-09-06 00:37:42 +00:00
|
|
|
use crate::caret::CaretType;
|
2020-09-04 23:08:33 +00:00
|
|
|
use crate::common::Direction;
|
|
|
|
use crate::ggez::GameResult;
|
|
|
|
use crate::npc::NPC;
|
2020-09-06 00:37:42 +00:00
|
|
|
use crate::player::Player;
|
2020-09-04 23:08:33 +00:00
|
|
|
use crate::SharedGameState;
|
|
|
|
|
|
|
|
impl NPC {
|
|
|
|
pub(crate) fn tick_n000_null(&mut self, state: &mut SharedGameState) -> GameResult {
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn tick_n016_save_point(&mut self, state: &mut SharedGameState) -> GameResult {
|
2020-09-05 02:09:52 +00:00
|
|
|
if self.action_num == 0 {
|
|
|
|
self.action_num = 1;
|
|
|
|
|
|
|
|
if self.direction == Direction::Right {
|
|
|
|
self.npc_flags.set_interactable(false);
|
|
|
|
self.vel_y = -0x200;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.flags.hit_bottom_wall() {
|
|
|
|
self.npc_flags.set_interactable(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
self.anim_counter = (self.anim_counter + 1) % 24;
|
|
|
|
self.anim_num = self.anim_counter / 3;
|
|
|
|
self.anim_rect = state.constants.npc.n016_save_point[self.anim_num as usize];
|
|
|
|
|
2020-09-04 23:08:33 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn tick_n017_health_refill(&mut self, state: &mut SharedGameState) -> GameResult {
|
|
|
|
if self.action_num == 0 {
|
|
|
|
self.action_num = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
match self.action_num {
|
|
|
|
1 => {
|
|
|
|
let rand = state.game_rng.range(0..30);
|
|
|
|
|
|
|
|
if rand < 10 {
|
|
|
|
self.action_num = 2;
|
|
|
|
} else if rand < 25 {
|
|
|
|
self.action_num = 3;
|
|
|
|
} else {
|
|
|
|
self.action_num = 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.action_counter = state.game_rng.range(0x10..0x40) as u16;
|
|
|
|
self.anim_counter = 0;
|
|
|
|
}
|
|
|
|
2 => {
|
|
|
|
self.anim_rect = state.constants.npc.n017_health_refill[0];
|
|
|
|
|
|
|
|
if self.action_counter > 0 {
|
|
|
|
self.action_counter -= 1;
|
|
|
|
} else {
|
|
|
|
self.action_num = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
3 => {
|
|
|
|
self.anim_counter += 1;
|
|
|
|
|
|
|
|
if self.anim_counter % 2 == 0 {
|
|
|
|
self.anim_rect = state.constants.npc.n017_health_refill[1];
|
|
|
|
} else {
|
|
|
|
self.anim_rect = state.constants.npc.n017_health_refill[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.action_counter > 0 {
|
|
|
|
self.action_counter -= 1;
|
|
|
|
} else {
|
|
|
|
self.action_num = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
4 => {
|
|
|
|
self.anim_rect = state.constants.npc.n017_health_refill[1];
|
|
|
|
|
|
|
|
if self.action_counter > 0 {
|
|
|
|
self.action_counter -= 1;
|
|
|
|
} else {
|
|
|
|
self.action_num = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn tick_n018_door(&mut self, state: &mut SharedGameState) -> GameResult {
|
|
|
|
match self.action_num {
|
|
|
|
0 => {
|
|
|
|
match self.direction {
|
2020-09-05 02:09:52 +00:00
|
|
|
Direction::Left => { self.anim_rect = state.constants.npc.n018_door[0] }
|
|
|
|
Direction::Right => { self.anim_rect = state.constants.npc.n018_door[1] }
|
2020-09-04 23:08:33 +00:00
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
1 => {
|
|
|
|
// todo smoke
|
|
|
|
self.action_num = 0;
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2020-09-05 02:09:52 +00:00
|
|
|
|
|
|
|
pub(crate) fn tick_n020_computer(&mut self, state: &mut SharedGameState) -> GameResult {
|
2020-09-06 00:37:42 +00:00
|
|
|
match self.direction {
|
|
|
|
Direction::Left if self.anim_num == 0 => {
|
|
|
|
self.anim_num = 1;
|
|
|
|
self.anim_rect = state.constants.npc.n020_computer[0];
|
|
|
|
}
|
|
|
|
Direction::Right => {
|
|
|
|
self.anim_counter = (self.anim_counter + 1) % 12;
|
|
|
|
self.anim_num = self.anim_counter / 4;
|
|
|
|
self.anim_rect = state.constants.npc.n020_computer[1 + self.anim_num as usize];
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn tick_n021_chest_open(&mut self, state: &mut SharedGameState) -> GameResult {
|
|
|
|
if self.action_num == 0 {
|
|
|
|
self.action_num = 1;
|
|
|
|
|
|
|
|
if self.direction == Direction::Right {
|
|
|
|
self.y += 16 * 0x200;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.anim_rect = state.constants.npc.n021_chest_open;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn tick_n022_teleporter(&mut self, state: &mut SharedGameState) -> GameResult {
|
|
|
|
match self.action_num {
|
|
|
|
0 if self.anim_counter == 0 => {
|
|
|
|
self.anim_counter = 1;
|
|
|
|
self.anim_rect = state.constants.npc.n022_teleporter[0];
|
|
|
|
}
|
|
|
|
1 => {
|
|
|
|
self.anim_num = (self.anim_num + 1) & 1;
|
|
|
|
self.anim_rect = state.constants.npc.n022_teleporter[self.anim_num as usize];
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
2020-09-05 02:09:52 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn tick_n027_death_trap(&mut self, state: &mut SharedGameState) -> GameResult {
|
|
|
|
if self.action_num == 0 {
|
|
|
|
self.action_num = 1;
|
|
|
|
self.anim_rect = state.constants.npc.n027_death_trap;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2020-09-06 00:37:42 +00:00
|
|
|
pub(crate) fn tick_n030_gunsmith(&mut self, state: &mut SharedGameState) -> GameResult {
|
|
|
|
if self.direction == Direction::Left {
|
|
|
|
match self.action_num {
|
|
|
|
0 => {
|
|
|
|
self.action_num = 1;
|
|
|
|
self.anim_counter = 0;
|
|
|
|
self.anim_rect = state.constants.npc.n030_hermit_gunsmith[0];
|
|
|
|
}
|
|
|
|
1 => {
|
|
|
|
self.action_num = 1;
|
|
|
|
self.anim_counter = 0;
|
|
|
|
|
|
|
|
if state.game_rng.range(0..120) == 10 {
|
|
|
|
self.action_num = 2;
|
|
|
|
self.action_counter = 8;
|
|
|
|
self.anim_rect = state.constants.npc.n030_hermit_gunsmith[1];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
2 => {
|
|
|
|
if self.action_counter > 0 {
|
|
|
|
self.action_counter -= 1;
|
|
|
|
self.anim_rect = state.constants.npc.n030_hermit_gunsmith[0];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if self.action_num == 0 {
|
|
|
|
self.action_num = 1;
|
|
|
|
self.anim_rect = state.constants.npc.n030_hermit_gunsmith[2];
|
|
|
|
self.y += 16 * 0x200;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.action_counter += 1;
|
|
|
|
if self.action_counter > 100 {
|
|
|
|
self.action_counter = 0;
|
|
|
|
state.create_caret(self.x, self.y - 0x400, CaretType::Zzz, Direction::Left);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-09-05 02:09:52 +00:00
|
|
|
pub(crate) fn tick_n032_life_capsule(&mut self, state: &mut SharedGameState) -> GameResult {
|
|
|
|
self.anim_counter = (self.anim_counter + 1) % 4;
|
|
|
|
self.anim_num = self.anim_counter / 2;
|
|
|
|
self.anim_rect = state.constants.npc.n032_life_capsule[self.anim_num as usize];
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn tick_n034_bed(&mut self, state: &mut SharedGameState) -> GameResult {
|
2020-09-06 00:37:42 +00:00
|
|
|
if self.action_num == 0 {
|
|
|
|
self.action_num = 1;
|
|
|
|
|
|
|
|
match self.direction {
|
|
|
|
Direction::Left => { self.anim_rect = state.constants.npc.n034_bed[0] }
|
|
|
|
Direction::Right => { self.anim_rect = state.constants.npc.n034_bed[1] }
|
|
|
|
_ => {}
|
|
|
|
}
|
2020-09-05 02:09:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn tick_n037_sign(&mut self, state: &mut SharedGameState) -> GameResult {
|
|
|
|
self.anim_counter = (self.anim_counter + 1) % 4;
|
|
|
|
self.anim_num = self.anim_counter / 2;
|
|
|
|
self.anim_rect = state.constants.npc.n037_sign[self.anim_num as usize];
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn tick_n038_fireplace(&mut self, state: &mut SharedGameState) -> GameResult {
|
|
|
|
match self.action_num {
|
|
|
|
0 => {
|
|
|
|
self.anim_counter = (self.anim_counter + 1) % 16;
|
|
|
|
self.anim_num = self.anim_counter / 4;
|
|
|
|
self.anim_rect = state.constants.npc.n038_fireplace[self.anim_num as usize];
|
|
|
|
}
|
|
|
|
10 => {}
|
|
|
|
11 => {}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn tick_n039_save_sign(&mut self, state: &mut SharedGameState) -> GameResult {
|
2020-09-06 00:37:42 +00:00
|
|
|
if self.action_num == 0 {
|
|
|
|
self.action_num = 1;
|
|
|
|
|
|
|
|
match self.direction {
|
|
|
|
Direction::Left => { self.anim_rect = state.constants.npc.n039_save_sign[0] }
|
|
|
|
Direction::Right => { self.anim_rect = state.constants.npc.n039_save_sign[1] }
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn tick_n041_busted_door(&mut self, state: &mut SharedGameState) -> GameResult {
|
|
|
|
if self.action_num == 0 {
|
|
|
|
self.action_num = 1;
|
|
|
|
self.anim_rect = state.constants.npc.n041_busted_door;
|
|
|
|
self.y -= 16 * 0x200;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn tick_n043_chalkboard(&mut self, state: &mut SharedGameState) -> GameResult {
|
|
|
|
if self.action_num == 0 {
|
|
|
|
self.action_num = 1;
|
|
|
|
self.y -= 16 * 0x200;
|
|
|
|
|
|
|
|
match self.direction {
|
|
|
|
Direction::Left => { self.anim_rect = state.constants.npc.n043_chalkboard[0] }
|
|
|
|
Direction::Right => { self.anim_rect = state.constants.npc.n043_chalkboard[1] }
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn tick_n046_hv_trigger(&mut self, state: &mut SharedGameState, player: &Player) -> GameResult {
|
|
|
|
self.npc_flags.set_event_when_touched(true);
|
|
|
|
|
|
|
|
if self.direction == Direction::Left {
|
|
|
|
if self.x < player.x {
|
|
|
|
self.x += 0x5ff;
|
|
|
|
} else {
|
|
|
|
self.x -= 0x5ff;
|
|
|
|
}
|
|
|
|
} else if self.y < player.y {
|
|
|
|
self.y += 0x5ff;
|
|
|
|
} else {
|
|
|
|
self.y -= 0x5ff;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn tick_n070_sparkle(&mut self, state: &mut SharedGameState) -> GameResult {
|
|
|
|
self.anim_counter = (self.anim_counter + 1) % 16;
|
|
|
|
self.anim_num = self.anim_counter / 4;
|
|
|
|
self.anim_rect = state.constants.npc.n070_sparkle[self.anim_num as usize];
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn tick_n072_sprinkler(&mut self, state: &mut SharedGameState) -> GameResult {
|
|
|
|
if self.direction == Direction::Left {
|
|
|
|
self.anim_counter = (self.anim_counter + 1) % 4;
|
|
|
|
self.anim_num = self.anim_counter / 2;
|
|
|
|
self.anim_rect = state.constants.npc.n072_sprinkler[self.anim_num as usize];
|
|
|
|
|
|
|
|
// todo: spawn water droplets
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn tick_n078_pot(&mut self, state: &mut SharedGameState) -> GameResult {
|
|
|
|
if self.action_num == 0 {
|
|
|
|
self.action_num = 1;
|
|
|
|
|
|
|
|
match self.direction {
|
|
|
|
Direction::Left => { self.anim_rect = state.constants.npc.n078_pot[0] }
|
|
|
|
Direction::Right => { self.anim_rect = state.constants.npc.n078_pot[1] }
|
|
|
|
_ => {}
|
|
|
|
}
|
2020-09-05 02:09:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2020-09-04 23:08:33 +00:00
|
|
|
}
|