From 7d41ff45aef41585301d841e4be77f738e555919 Mon Sep 17 00:00:00 2001 From: Alula Date: Thu, 10 Sep 2020 13:29:25 +0200 Subject: [PATCH] egg corridor npcs --- src/engine_constants.rs | 74 +++++++++++ src/npc/egg_corridor.rs | 267 ++++++++++++++++++++++++++++++++++++++++ src/npc/mod.rs | 5 +- 3 files changed, 345 insertions(+), 1 deletion(-) diff --git a/src/engine_constants.rs b/src/engine_constants.rs index c209683..27f44ab 100644 --- a/src/engine_constants.rs +++ b/src/engine_constants.rs @@ -86,6 +86,12 @@ pub struct WorldConsts { #[derive(Debug, Copy, Clone)] pub struct NPCConsts { + pub n002_behemoth: [Rect; 14], + pub n004_smoke: [Rect; 16], + pub n005_green_critter: [Rect; 6], + pub n006_green_beetle: [Rect; 10], + pub n007_basil: [Rect; 6], + pub n008_blue_beetle: [Rect; 4], pub n016_save_point: [Rect; 8], pub n017_health_refill: [Rect; 2], pub n018_door: [Rect; 2], @@ -316,6 +322,74 @@ impl EngineConstants { snack_rect: Rect { left: 256, top: 48, right: 272, bottom: 64 }, }, npc: NPCConsts { + n002_behemoth: [ + Rect { left: 32, top: 0, right: 64, bottom: 24 }, // left + Rect { left: 0, top: 0, right: 32, bottom: 24 }, + Rect { left: 32, top: 0, right: 64, bottom: 24 }, + Rect { left: 64, top: 0, right: 96, bottom: 24 }, + Rect { left: 96, top: 0, right: 128, bottom: 24 }, + Rect { left: 128, top: 0, right: 160, bottom: 24 }, + Rect { left: 160, top: 0, right: 192, bottom: 24 }, + Rect { left: 32, top: 24, right: 64, bottom: 48 }, // right + Rect { left: 0, top: 24, right: 32, bottom: 48 }, + Rect { left: 32, top: 24, right: 64, bottom: 48 }, + Rect { left: 64, top: 24, right: 96, bottom: 48 }, + Rect { left: 96, top: 24, right: 128, bottom: 48 }, + Rect { left: 128, top: 24, right: 160, bottom: 48 }, + Rect { left: 160, top: 24, right: 192, bottom: 48 }, + ], + n004_smoke: [ + Rect { left: 16, top: 0, right: 17, bottom: 1 }, // left + Rect { left: 16, top: 0, right: 32, bottom: 16 }, + Rect { left: 32, top: 0, right: 48, bottom: 16 }, + Rect { left: 48, top: 0, right: 64, bottom: 16 }, + Rect { left: 64, top: 0, right: 80, bottom: 16 }, + Rect { left: 80, top: 0, right: 96, bottom: 16 }, + Rect { left: 96, top: 0, right: 112, bottom: 16 }, + Rect { left: 112, top: 0, right: 128, bottom: 16 }, + Rect { left: 16, top: 0, right: 17, bottom: 1 }, // right + Rect { left: 80, top: 48, right: 96, bottom: 64 }, + Rect { left: 0, top: 128, right: 16, bottom: 144 }, + Rect { left: 16, top: 128, right: 32, bottom: 144 }, + Rect { left: 32, top: 128, right: 48, bottom: 144 }, + Rect { left: 48, top: 128, right: 64, bottom: 144 }, + Rect { left: 64, top: 128, right: 80, bottom: 144 }, + Rect { left: 80, top: 128, right: 96, bottom: 144 }, + ], + n005_green_critter: [ + Rect { left: 0, top: 48, right: 16, bottom: 64 }, // left + Rect { left: 16, top: 48, right: 32, bottom: 64 }, + Rect { left: 32, top: 48, right: 48, bottom: 64 }, + Rect { left: 0, top: 64, right: 16, bottom: 80 }, // right + Rect { left: 16, top: 64, right: 32, bottom: 80 }, + Rect { left: 32, top: 64, right: 48, bottom: 80 }, + ], + n006_green_beetle: [ + Rect { left: 0, top: 80, right: 16, bottom: 96 }, // left + Rect { left: 16, top: 80, right: 32, bottom: 96 }, + Rect { left: 32, top: 80, right: 48, bottom: 96 }, + Rect { left: 48, top: 80, right: 64, bottom: 96 }, + Rect { left: 64, top: 80, right: 80, bottom: 96 }, + Rect { left: 0, top: 96, right: 16, bottom: 112 }, // right + Rect { left: 16, top: 96, right: 32, bottom: 112 }, + Rect { left: 32, top: 96, right: 48, bottom: 112 }, + Rect { left: 48, top: 96, right: 64, bottom: 112 }, + Rect { left: 64, top: 96, right: 80, bottom: 112 }, + ], + n007_basil: [ + Rect { left: 256, top: 64, right: 288, bottom: 80 }, // left + Rect { left: 256, top: 80, right: 288, bottom: 96 }, + Rect { left: 256, top: 96, right: 288, bottom: 112 }, + Rect { left: 288, top: 64, right: 320, bottom: 80 }, // right + Rect { left: 288, top: 80, right: 320, bottom: 96 }, + Rect { left: 288, top: 96, right: 320, bottom: 112 }, + ], + n008_blue_beetle: [ + Rect { left: 80, top: 80, right: 96, bottom: 96 },// left + Rect { left: 96, top: 80, right: 112, bottom: 96 }, + Rect { left: 80, top: 96, right: 96, bottom: 112 }, // right + Rect { left: 96, top: 96, right: 112, bottom: 112 }, + ], n016_save_point: [ Rect { left: 96, top: 16, right: 112, bottom: 32 }, Rect { left: 112, top: 16, right: 128, bottom: 32 }, diff --git a/src/npc/egg_corridor.rs b/src/npc/egg_corridor.rs index e69de29..29cd475 100644 --- a/src/npc/egg_corridor.rs +++ b/src/npc/egg_corridor.rs @@ -0,0 +1,267 @@ +use nalgebra::clamp; + +use crate::common::Direction; +use crate::ggez::GameResult; +use crate::npc::NPC; +use crate::player::Player; +use crate::SharedGameState; + +impl NPC { + pub(crate) fn tick_n002_behemoth(&mut self, state: &mut SharedGameState) -> GameResult { + if self.flags.hit_left_wall() { + self.direction = Direction::Right; + } else if self.flags.hit_right_wall() { + self.direction = Direction::Left; + } + + match self.action_num { + 0 => { + self.vel_x = match self.direction { + Direction::Left => { -0x100 } + Direction::Right => { 0x100 } + _ => { 0 } + }; + + self.anim_counter += 1; + if self.anim_counter > 8 { + self.anim_counter = 0; + self.anim_num = (self.anim_num + 1) % 3; + self.anim_rect = state.constants.npc.n002_behemoth[self.anim_num as usize + if self.direction == Direction::Right { 7 } else { 0 }]; + } + + if self.shock > 0 { + self.action_counter = 0; + self.action_num = 1; + self.anim_num = 4; + self.anim_rect = state.constants.npc.n002_behemoth[self.anim_num as usize + if self.direction == Direction::Right { 7 } else { 0 }]; + } + } + 1 => { + self.vel_x = (self.vel_x * 7) / 8; + + self.action_counter += 1; + if self.action_counter > 40 { + if self.shock > 0 { + self.action_counter = 0; + self.action_num = 2; + self.anim_num = 6; + self.anim_counter = 0; + self.damage = 5; + self.anim_rect = state.constants.npc.n002_behemoth[self.anim_num as usize + if self.direction == Direction::Right { 7 } else { 0 }]; + } else { + self.action_num = 0; + self.anim_counter = 0; + } + } + } + 2 => { + self.vel_x = match self.direction { + Direction::Left => { -0x400 } + Direction::Right => { 0x400 } + _ => { 0 } + }; + + self.action_counter += 1; + if self.action_counter > 200 { + self.action_num = 0; + self.damage = 1; + } + + self.anim_counter += 1; + if self.anim_counter > 5 { + self.anim_counter = 0; + self.anim_num += 1; + if self.anim_num > 6 { + self.anim_num = 5; + // todo play sound 26 + state.quake_counter = 8; + } + + self.anim_rect = state.constants.npc.n002_behemoth[self.anim_num as usize + if self.direction == Direction::Right { 7 } else { 0 }]; + } + } + _ => {} + } + + self.vel_y += 0x40; + if self.vel_y > 0x5ff { + self.vel_y = 0x5ff; + } + + self.x += self.vel_x; + self.y += self.vel_y; + + Ok(()) + } + + pub(crate) fn tick_n005_green_critter(&mut self, state: &mut SharedGameState, player: &Player) -> GameResult { + match self.action_num { + 0 | 1 => { + if self.action_num == 0 { + self.y += 3 * 0x200; + self.action_num = 1; + self.anim_num = 0; + self.anim_rect = state.constants.npc.n005_green_critter[self.anim_num as usize + if self.direction == Direction::Right { 3 } else { 0 }]; + } + + if self.x > player.x { + self.direction = Direction::Left; + } else { + self.direction = Direction::Right; + } + + if self.target_x < 100 { + self.target_x += 1; + } + + if self.action_counter >= 8 + && self.x - (112 * 0x200) < player.x + && self.x + (112 * 0x200) > player.x + && self.y - (80 * 0x200) < player.y + && self.y + (80 * 0x200) > player.y { + if self.anim_num != 1 { + self.anim_num = 1; + self.anim_rect = state.constants.npc.n005_green_critter[self.anim_num as usize + if self.direction == Direction::Right { 3 } else { 0 }]; + } + } else { + if self.action_counter < 8 { + self.action_counter += 1; + } + + if self.anim_num != 0 { + self.anim_num = 0; + self.anim_rect = state.constants.npc.n005_green_critter[self.anim_num as usize + if self.direction == Direction::Right { 3 } else { 0 }]; + } + } + + if self.shock > 0 { + self.action_num = 2; + self.action_counter = 0; + + if self.anim_num != 0 { + self.anim_num = 0; + self.anim_rect = state.constants.npc.n005_green_critter[self.anim_num as usize + if self.direction == Direction::Right { 3 } else { 0 }]; + } + } + + if self.action_counter >= 8 + && self.target_x >= 100 + && self.x - (64 * 0x200) < player.x + && self.x + (64 * 0x200) > player.x + && self.y - (80 * 0x200) < player.y + && self.y + (80 * 0x200) > player.y { + self.action_num = 2; + self.action_counter = 0; + + if self.anim_num != 0 { + self.anim_num = 0; + self.anim_rect = state.constants.npc.n005_green_critter[self.anim_num as usize + if self.direction == Direction::Right { 3 } else { 0 }]; + } + } + } + 2 => { + self.action_counter += 1; + if self.action_counter > 8 { + self.action_num = 3; + + if self.anim_num != 2 { + self.anim_num = 2; + self.anim_rect = state.constants.npc.n005_green_critter[self.anim_num as usize + if self.direction == Direction::Right { 3 } else { 0 }]; + } + + self.vel_y = -0x5ff; + // todo play sound 30 + + if self.direction == Direction::Left { + self.vel_x = -0x100; + } else { + self.vel_x = 0x100; + } + } + } + 3 => { + if self.flags.hit_bottom_wall() { + self.vel_x = 0; + self.action_counter = 0; + self.action_num = 1; + + // tood play sound 23 + + if self.anim_num != 0 { + self.anim_num = 0; + self.anim_rect = state.constants.npc.n005_green_critter[self.anim_num as usize + if self.direction == Direction::Right { 3 } else { 0 }]; + } + } + } + _ => {} + } + + self.vel_y += 0x40; + if self.vel_y > 0x5ff { + self.vel_y = 0x5ff; + } + + self.x += self.vel_x; + self.y += self.vel_y; + + Ok(()) + } + + pub(crate) fn tick_n007_basil(&mut self, state: &mut SharedGameState, player: &Player) -> GameResult { + match self.action_num { + 0 => { + self.x = player.x; + + if self.direction == Direction::Left { + self.action_num = 1; + } else { + self.action_num = 2; + } + } + 1 => { + self.vel_x -= 0x40; + + if self.x < (player.x - 192 * 0x200) { + self.action_num = 2; + } + + if self.flags.hit_left_wall() { + self.vel_x = 0; + self.action_num = 2; + } + } + 2 => { + self.vel_x += 0x40; + + if self.x > (player.x + 192 * 0x200) { + self.action_num = 1; + } + + if self.flags.hit_right_wall() { + self.vel_x = 0; + self.action_num = 1; + } + } + _ => {} + } + + if self.vel_x < 0 { + self.direction = Direction::Left; + } else { + self.direction = Direction::Right; + } + + self.vel_x = clamp(self.vel_x, -0x5ff, 0x5ff); + + self.x += self.vel_x; + + self.anim_counter += 1; + if self.anim_counter > 1 { + self.anim_counter = 0; + self.anim_num = (self.anim_num + 1) % 2; + self.anim_rect = state.constants.npc.n007_basil[self.anim_num as usize + if self.direction == Direction::Right { 3 } else { 0 }]; + } + + Ok(()) + } +} diff --git a/src/npc/mod.rs b/src/npc/mod.rs index cf404eb..fb39936 100644 --- a/src/npc/mod.rs +++ b/src/npc/mod.rs @@ -16,9 +16,9 @@ use crate::map::NPCData; use crate::physics::PhysicalEntity; use crate::player::Player; use crate::str; -use crate::text_script::TextScriptExecutionState; pub mod characters; +pub mod egg_corridor; pub mod first_cave; pub mod mimiga_village; pub mod misc; @@ -79,6 +79,9 @@ impl GameEntity<&mut Player> for NPC { // maybe use macros? match self.npc_type { 0 => { self.tick_n000_null(state) } + 2 => { self.tick_n002_behemoth(state) } + 5 => { self.tick_n005_green_critter(state, player) } + 7 => { self.tick_n007_basil(state, player) } 16 => { self.tick_n016_save_point(state) } 17 => { self.tick_n017_health_refill(state) } 18 => { self.tick_n018_door(state) }