mirror of
https://github.com/doukutsu-rs/doukutsu-rs
synced 2025-02-14 13:23:05 +00:00
dep update
This commit is contained in:
parent
c67e90f4dd
commit
c7522f9bf1
30
Cargo.toml
30
Cargo.toml
|
@ -40,25 +40,27 @@ opt-level = 1
|
|||
opt-level = 1
|
||||
|
||||
[features]
|
||||
default = ["scripting", "backend-sdl"]
|
||||
default = ["scripting", "backend-sdl", "ogg-playback"]
|
||||
ogg-playback = ["lewton"]
|
||||
backend-sdl = ["sdl2"]
|
||||
backend-gfx = ["winit", "imgui-gfx-renderer", "imgui-winit-support"]
|
||||
scripting = ["lua-ffi"]
|
||||
editor = []
|
||||
|
||||
[dependencies]
|
||||
bitvec = "0.17.4"
|
||||
byteorder = "1.3"
|
||||
bitvec = "0.20"
|
||||
byteorder = "1.4"
|
||||
case_insensitive_hashmap = "1.0.0"
|
||||
chrono = "0.4"
|
||||
cpal = { git = "https://github.com/doukutsu-rs/cpal.git", branch = "android-support" }
|
||||
cpal = "0.13"
|
||||
directories = "3"
|
||||
imgui = "0.7.0"
|
||||
imgui-gfx-renderer = { version = "0.7.0", optional = true }
|
||||
imgui-winit-support = { version = "0.7.0", default-features = false, features = ["winit-23"], optional = true }
|
||||
image = { version = "0.22", default-features = false, features = ["png_codec", "pnm", "bmp"] }
|
||||
itertools = "0.9.0"
|
||||
imgui-winit-support = { version = "0.7.0", default-features = false, features = ["winit-24"], optional = true }
|
||||
image = { version = "0.23", default-features = false, features = ["png", "bmp"] }
|
||||
itertools = "0.10"
|
||||
lazy_static = "1.4.0"
|
||||
lewton = { version = "0.10.2", optional = true }
|
||||
log = "0.4"
|
||||
lua-ffi = { git = "https://github.com/doukutsu-rs/lua-ffi.git", rev = "1ef3caf772d72068297ddf75df06fd2ef8c1daab", optional = true }
|
||||
lru = "0.6.0"
|
||||
|
@ -70,17 +72,17 @@ sdl2 = { version = "0.34", optional = true, features = ["unsafe_textures", "bund
|
|||
serde = { version = "1", features = ["derive"] }
|
||||
serde_derive = "1"
|
||||
serde_yaml = "0.8"
|
||||
strum = "0.18.0"
|
||||
strum_macros = "0.18.0"
|
||||
strum = "0.20"
|
||||
strum_macros = "0.20"
|
||||
# remove and replace when drain_filter is in stable
|
||||
vec_mut_scan = "0.3.0"
|
||||
vec_mut_scan = "0.4"
|
||||
webbrowser = "0.5.5"
|
||||
winit = { version = "0.24.0", features = ["serde"], optional = true }
|
||||
winit = { version = "0.24", features = ["serde"], optional = true }
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
winapi = { version = "0.3", features = ["winuser"] }
|
||||
|
||||
[target.'cfg(target_os = "android")'.dependencies]
|
||||
ndk = "0.2"
|
||||
ndk-glue = "0.2"
|
||||
jni = "0.17"
|
||||
ndk = "0.3"
|
||||
ndk-glue = "0.3"
|
||||
jni = "0.19"
|
||||
|
|
137
src/lib.rs
137
src/lib.rs
|
@ -18,12 +18,10 @@ use log::*;
|
|||
use pretty_env_logger::env_logger::Env;
|
||||
|
||||
use crate::builtin_fs::BuiltinFS;
|
||||
use crate::framework::backend::init_backend;
|
||||
use crate::framework::context::Context;
|
||||
use crate::framework::error::{GameError, GameResult};
|
||||
use crate::framework::filesystem::{mount_user_vfs, mount_vfs};
|
||||
use crate::framework::graphics;
|
||||
use crate::framework::keyboard::ScanCode;
|
||||
use crate::framework::ui::UI;
|
||||
use crate::framework::vfs::PhysicalFS;
|
||||
use crate::scene::loading_scene::LoadingScene;
|
||||
|
@ -44,8 +42,8 @@ mod engine_constants;
|
|||
mod entity;
|
||||
mod frame;
|
||||
mod framework;
|
||||
mod inventory;
|
||||
mod input;
|
||||
mod inventory;
|
||||
mod live_debugger;
|
||||
mod macros;
|
||||
mod map;
|
||||
|
@ -62,8 +60,8 @@ mod settings;
|
|||
#[cfg(feature = "backend-gfx")]
|
||||
mod shaders;
|
||||
mod shared_game_state;
|
||||
mod stage;
|
||||
mod sound;
|
||||
mod stage;
|
||||
mod text_script;
|
||||
mod texture_set;
|
||||
mod weapon;
|
||||
|
@ -101,11 +99,14 @@ impl Game {
|
|||
TimingMode::_50Hz | TimingMode::_60Hz => {
|
||||
let last_tick = self.next_tick;
|
||||
|
||||
while self.start_time.elapsed().as_nanos() >= self.next_tick && self.loops < 10 {
|
||||
while self.start_time.elapsed().as_nanos() >= self.next_tick && self.loops < 10
|
||||
{
|
||||
if (state_ref.settings.speed - 1.0).abs() < 0.01 {
|
||||
self.next_tick += state_ref.timing_mode.get_delta() as u128;
|
||||
} else {
|
||||
self.next_tick += (state_ref.timing_mode.get_delta() as f64 / state_ref.settings.speed) as u128;
|
||||
self.next_tick += (state_ref.timing_mode.get_delta() as f64
|
||||
/ state_ref.settings.speed)
|
||||
as u128;
|
||||
}
|
||||
self.loops += 1;
|
||||
}
|
||||
|
@ -113,7 +114,9 @@ impl Game {
|
|||
if self.loops == 10 {
|
||||
log::warn!("Frame skip is way too high, a long system lag occurred?");
|
||||
self.last_tick = self.start_time.elapsed().as_nanos();
|
||||
self.next_tick = self.last_tick + (state_ref.timing_mode.get_delta() as f64 / state_ref.settings.speed) as u128;
|
||||
self.next_tick = self.last_tick
|
||||
+ (state_ref.timing_mode.get_delta() as f64 / state_ref.settings.speed)
|
||||
as u128;
|
||||
self.loops = 0;
|
||||
}
|
||||
|
||||
|
@ -140,34 +143,45 @@ impl Game {
|
|||
if state_ref.timing_mode != TimingMode::FrameSynchronized {
|
||||
let mut elapsed = self.start_time.elapsed().as_nanos();
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
// Even with the non-monotonic Instant mitigation at the start of the event loop, there's still a chance of it not working.
|
||||
// This check here should trigger if that happens and makes sure there's no panic from an underflow.
|
||||
if elapsed < self.last_tick {
|
||||
elapsed = self.last_tick;
|
||||
}
|
||||
{
|
||||
// Even with the non-monotonic Instant mitigation at the start of the event loop, there's still a chance of it not working.
|
||||
// This check here should trigger if that happens and makes sure there's no panic from an underflow.
|
||||
if elapsed < self.last_tick {
|
||||
elapsed = self.last_tick;
|
||||
}
|
||||
}
|
||||
let n1 = (elapsed - self.last_tick) as f64;
|
||||
let n2 = (self.next_tick - self.last_tick) as f64;
|
||||
state_ref.frame_time = if state_ref.settings.motion_interpolation {
|
||||
n1 / n2
|
||||
} else { 1.0 };
|
||||
} else {
|
||||
1.0
|
||||
};
|
||||
}
|
||||
unsafe {
|
||||
G_MAG = if state_ref.settings.subpixel_coords { state_ref.scale } else { 1.0 };
|
||||
G_MAG = if state_ref.settings.subpixel_coords {
|
||||
state_ref.scale
|
||||
} else {
|
||||
1.0
|
||||
};
|
||||
I_MAG = state_ref.scale;
|
||||
}
|
||||
self.loops = 0;
|
||||
|
||||
graphics::clear(ctx, [0.0, 0.0, 0.0, 1.0].into());
|
||||
/*graphics::set_projection(ctx, DrawParam::new()
|
||||
.scale(Vec2::new(state_ref.scale, state_ref.scale))
|
||||
.to_matrix());*/
|
||||
.scale(Vec2::new(state_ref.scale, state_ref.scale))
|
||||
.to_matrix());*/
|
||||
|
||||
if let Some(scene) = self.scene.as_mut() {
|
||||
scene.draw(state_ref, ctx)?;
|
||||
if state_ref.settings.touch_controls {
|
||||
state_ref.touch_controls.draw(state_ref.canvas_size, &state_ref.constants, &mut state_ref.texture_set, ctx)?;
|
||||
state_ref.touch_controls.draw(
|
||||
state_ref.canvas_size,
|
||||
&state_ref.constants,
|
||||
&mut state_ref.texture_set,
|
||||
ctx,
|
||||
)?;
|
||||
}
|
||||
|
||||
//graphics::set_projection(ctx, self.def_matrix);
|
||||
|
@ -181,44 +195,76 @@ impl Game {
|
|||
|
||||
#[cfg(target_os = "android")]
|
||||
fn request_perms() -> GameResult {
|
||||
use jni::objects::JValue;
|
||||
use jni::objects::JObject;
|
||||
use jni::objects::JValue;
|
||||
|
||||
let native_activity = ndk_glue::native_activity();
|
||||
let vm_ptr = native_activity.vm();
|
||||
let vm = unsafe { jni::JavaVM::from_raw(vm_ptr) }?;
|
||||
let vm_env = vm.attach_current_thread()?;
|
||||
|
||||
fn perm_name<'a, 'b, 'c>(vm_env: &'b jni::AttachGuard<'a>, name: &'c str) -> GameResult<jni::objects::JValue<'a>> {
|
||||
fn perm_name<'a, 'b, 'c>(
|
||||
vm_env: &'b jni::AttachGuard<'a>,
|
||||
name: &'c str,
|
||||
) -> GameResult<jni::objects::JValue<'a>> {
|
||||
let class = vm_env.find_class("android/Manifest$permission")?;
|
||||
Ok(vm_env.get_static_field(class, name.to_owned(), "Ljava/lang/String;")?)
|
||||
}
|
||||
|
||||
fn has_permission(vm_env: &jni::AttachGuard, activity: &jni::sys::jobject, name: &str) -> GameResult<bool> {
|
||||
fn has_permission(
|
||||
vm_env: &jni::AttachGuard,
|
||||
activity: &jni::sys::jobject,
|
||||
name: &str,
|
||||
) -> GameResult<bool> {
|
||||
let perm_granted = {
|
||||
let class = vm_env.find_class("android/content/pm/PackageManager")?;
|
||||
vm_env.get_static_field(class, "PERMISSION_GRANTED", "I")?.i()?
|
||||
vm_env
|
||||
.get_static_field(class, "PERMISSION_GRANTED", "I")?
|
||||
.i()?
|
||||
};
|
||||
|
||||
let perm = perm_name(vm_env, name)?;
|
||||
let activity_obj = JObject::from(*activity);
|
||||
let result = vm_env.call_method(activity_obj, "checkSelfPermission", "(Ljava/lang/String;)I", &[perm])?.i()?;
|
||||
let result = vm_env
|
||||
.call_method(
|
||||
activity_obj,
|
||||
"checkSelfPermission",
|
||||
"(Ljava/lang/String;)I",
|
||||
&[perm],
|
||||
)?
|
||||
.i()?;
|
||||
Ok(result == perm_granted)
|
||||
}
|
||||
|
||||
let str_class = vm_env.find_class("java/lang/String")?;
|
||||
let array = vm_env.new_object_array(2, str_class, JObject::null())?;
|
||||
vm_env.set_object_array_element(array, 0, perm_name(&vm_env, "READ_EXTERNAL_STORAGE")?.l()?)?;
|
||||
vm_env.set_object_array_element(array, 1, perm_name(&vm_env, "WRITE_EXTERNAL_STORAGE")?.l()?)?;
|
||||
vm_env.set_object_array_element(
|
||||
array,
|
||||
1,
|
||||
perm_name(&vm_env, "WRITE_EXTERNAL_STORAGE")?.l()?,
|
||||
)?;
|
||||
let activity_obj = JObject::from(native_activity.activity());
|
||||
|
||||
loop {
|
||||
if has_permission(&vm_env, &native_activity.activity(), "READ_EXTERNAL_STORAGE")?
|
||||
&& has_permission(&vm_env, &native_activity.activity(), "WRITE_EXTERNAL_STORAGE")? {
|
||||
if has_permission(
|
||||
&vm_env,
|
||||
&native_activity.activity(),
|
||||
"READ_EXTERNAL_STORAGE",
|
||||
)? && has_permission(
|
||||
&vm_env,
|
||||
&native_activity.activity(),
|
||||
"WRITE_EXTERNAL_STORAGE",
|
||||
)? {
|
||||
break;
|
||||
}
|
||||
|
||||
vm_env.call_method(activity_obj, "requestPermissions", "([Ljava/lang/String;I)V", &[JValue::from(array), JValue::from(0)])?;
|
||||
vm_env.call_method(
|
||||
activity_obj,
|
||||
"requestPermissions",
|
||||
"([Ljava/lang/String;I)V",
|
||||
&[JValue::from(array), JValue::from(0)],
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -240,8 +286,7 @@ pub fn android_main() {
|
|||
}
|
||||
|
||||
pub fn init() -> GameResult {
|
||||
pretty_env_logger::env_logger::from_env(Env::default().default_filter_or("info"))
|
||||
.init();
|
||||
pretty_env_logger::env_logger::from_env(Env::default().default_filter_or("info")).init();
|
||||
|
||||
let resource_dir = if let Ok(data_dir) = env::var("CAVESTORY_DATA_DIR") {
|
||||
PathBuf::from(data_dir)
|
||||
|
@ -261,9 +306,8 @@ pub fn init() -> GameResult {
|
|||
mount_vfs(&mut context, Box::new(BuiltinFS::new()));
|
||||
mount_vfs(&mut context, Box::new(PhysicalFS::new(&resource_dir, true)));
|
||||
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
let project_dirs = match ProjectDirs::from("", "", "doukutsu-rs") {
|
||||
let project_dirs = match ProjectDirs::from("", "", "doukutsu-rs") {
|
||||
Some(dirs) => dirs,
|
||||
None => {
|
||||
return Err(GameError::FilesystemError(String::from(
|
||||
|
@ -271,29 +315,34 @@ pub fn init() -> GameResult {
|
|||
)));
|
||||
}
|
||||
};
|
||||
mount_user_vfs(&mut context, Box::new(PhysicalFS::new(project_dirs.data_local_dir(), false)));
|
||||
mount_user_vfs(
|
||||
&mut context,
|
||||
Box::new(PhysicalFS::new(project_dirs.data_local_dir(), false)),
|
||||
);
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
{
|
||||
loop {
|
||||
match ndk_glue::native_window().as_ref() {
|
||||
Some(_) => {
|
||||
println!("NativeScreen Found:{:?}", ndk_glue::native_window());
|
||||
break;
|
||||
}
|
||||
None => ()
|
||||
{
|
||||
loop {
|
||||
match ndk_glue::native_window().as_ref() {
|
||||
Some(_) => {
|
||||
println!("NativeScreen Found:{:?}", ndk_glue::native_window());
|
||||
break;
|
||||
}
|
||||
None => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut game = Game::new(&mut context)?;
|
||||
let state_ref = unsafe { &mut *game.state.get() };
|
||||
#[cfg(feature = "scripting")]
|
||||
{
|
||||
unsafe {
|
||||
state_ref.lua.update_refs(game.state.get(), &mut context as *mut Context);
|
||||
}
|
||||
{
|
||||
unsafe {
|
||||
state_ref
|
||||
.lua
|
||||
.update_refs(game.state.get(), &mut context as *mut Context);
|
||||
}
|
||||
}
|
||||
|
||||
state_ref.next_scene = Some(Box::new(LoadingScene::new()));
|
||||
context.run(&mut game)?;
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
use crate::framework::context::Context;
|
||||
use crate::framework::error::GameResult;
|
||||
|
||||
use crate::common::Direction;
|
||||
use crate::framework::error::GameResult;
|
||||
use crate::npc::NPC;
|
||||
use crate::player::Player;
|
||||
use crate::shared_game_state::SharedGameState;
|
||||
|
||||
impl NPC {
|
||||
pub(crate) fn tick_n241_critter_red(&mut self, state: &mut SharedGameState, players: [&mut Player; 2]) -> GameResult {
|
||||
pub(crate) fn tick_n241_critter_red(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
players: [&mut Player; 2],
|
||||
) -> GameResult {
|
||||
match self.action_num {
|
||||
0 | 1 => {
|
||||
if self.action_num == 0 {
|
||||
|
@ -31,7 +33,8 @@ impl NPC {
|
|||
&& self.x - (144 * 0x200) < player.x
|
||||
&& self.x + (144 * 0x200) > player.x
|
||||
&& self.y - (96 * 0x200) < player.y
|
||||
&& self.y + (96 * 0x200) > player.y {
|
||||
&& self.y + (96 * 0x200) > player.y
|
||||
{
|
||||
self.anim_num = 1;
|
||||
} else {
|
||||
if self.action_counter < 8 {
|
||||
|
@ -53,7 +56,8 @@ impl NPC {
|
|||
&& self.x - (96 * 0x200) < player.x
|
||||
&& self.x + (96 * 0x200) > player.x
|
||||
&& self.y - (80 * 0x200) < player.y
|
||||
&& self.y + (80 * 0x200) > player.y {
|
||||
&& self.y + (80 * 0x200) > player.y
|
||||
{
|
||||
self.action_num = 2;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 0;
|
||||
|
@ -96,8 +100,11 @@ impl NPC {
|
|||
self.x += self.vel_x;
|
||||
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.n241_critter_red[self.anim_num as usize + dir_offset];
|
||||
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
use crate::framework::context::Context;
|
||||
use crate::framework::error::GameResult;
|
||||
use num_traits::clamp;
|
||||
|
||||
use crate::caret::CaretType;
|
||||
use crate::common::Direction;
|
||||
use crate::npc::list::NPCList;
|
||||
use crate::framework::error::GameResult;
|
||||
use crate::npc::NPC;
|
||||
use crate::player::Player;
|
||||
use crate::rng::RNG;
|
||||
|
@ -54,7 +50,11 @@ impl NPC {
|
|||
self.x += self.vel_x;
|
||||
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.n154_gaudi_dead[self.anim_num as usize + dir_offset];
|
||||
|
||||
Ok(())
|
||||
|
@ -63,7 +63,12 @@ impl NPC {
|
|||
pub(crate) fn tick_n156_gaudi_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);
|
||||
state.create_caret(
|
||||
self.x,
|
||||
self.y,
|
||||
CaretType::ProjectileDissipation,
|
||||
Direction::Left,
|
||||
);
|
||||
}
|
||||
|
||||
self.x += self.vel_x;
|
||||
|
@ -101,13 +106,16 @@ impl NPC {
|
|||
_ => {}
|
||||
}
|
||||
|
||||
|
||||
self.anim_rect = state.constants.npc.n166_chaba[self.anim_num as usize];
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n173_gaudi_armored(&mut self, state: &mut SharedGameState, players: [&mut Player; 2]) -> GameResult {
|
||||
pub(crate) fn tick_n173_gaudi_armored(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
players: [&mut Player; 2],
|
||||
) -> GameResult {
|
||||
let player = self.get_closest_player_mut(players);
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -3,7 +3,6 @@ use std::cmp::Ordering;
|
|||
use num_traits::{abs, clamp};
|
||||
|
||||
use crate::common::Direction;
|
||||
use crate::framework::context::Context;
|
||||
use crate::framework::error::GameResult;
|
||||
use crate::npc::NPC;
|
||||
use crate::player::Player;
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
use crate::framework::context::Context;
|
||||
use crate::framework::error::GameResult;
|
||||
use num_traits::{abs, clamp};
|
||||
|
||||
use crate::caret::CaretType;
|
||||
use crate::common::{Direction, Rect};
|
||||
use crate::framework::error::GameResult;
|
||||
use crate::npc::list::NPCList;
|
||||
use crate::npc::NPC;
|
||||
use crate::player::Player;
|
||||
|
@ -134,7 +133,11 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n015_chest_closed(&mut self, state: &mut SharedGameState, npc_list: &NPCList) -> GameResult {
|
||||
pub(crate) fn tick_n015_chest_closed(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
npc_list: &NPCList,
|
||||
) -> GameResult {
|
||||
match self.action_num {
|
||||
0 | 1 => {
|
||||
if self.action_num == 0 {
|
||||
|
@ -292,15 +295,17 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n018_door(&mut self, state: &mut SharedGameState, npc_list: &NPCList) -> GameResult {
|
||||
pub(crate) fn tick_n018_door(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
npc_list: &NPCList,
|
||||
) -> GameResult {
|
||||
match self.action_num {
|
||||
0 => {
|
||||
match self.direction {
|
||||
Direction::Left => { self.anim_rect = state.constants.npc.n018_door[0] }
|
||||
Direction::Right => { self.anim_rect = state.constants.npc.n018_door[1] }
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
0 => match self.direction {
|
||||
Direction::Left => self.anim_rect = state.constants.npc.n018_door[0],
|
||||
Direction::Right => self.anim_rect = state.constants.npc.n018_door[1],
|
||||
_ => {}
|
||||
},
|
||||
1 => {
|
||||
let mut npc = NPC::create(4, &state.npc_table);
|
||||
|
||||
|
@ -370,7 +375,10 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n023_teleporter_lights(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
pub(crate) fn tick_n023_teleporter_lights(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
) -> GameResult {
|
||||
self.anim_counter += 1;
|
||||
if self.anim_counter > 1 {
|
||||
self.anim_counter = 0;
|
||||
|
@ -437,7 +445,6 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
@ -451,8 +458,8 @@ impl NPC {
|
|||
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] }
|
||||
Direction::Left => self.anim_rect = state.constants.npc.n034_bed[0],
|
||||
Direction::Right => self.anim_rect = state.constants.npc.n034_bed[1],
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -494,8 +501,8 @@ impl NPC {
|
|||
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] }
|
||||
Direction::Left => self.anim_rect = state.constants.npc.n039_save_sign[0],
|
||||
Direction::Right => self.anim_rect = state.constants.npc.n039_save_sign[1],
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -519,8 +526,8 @@ impl NPC {
|
|||
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] }
|
||||
Direction::Left => self.anim_rect = state.constants.npc.n043_chalkboard[0],
|
||||
Direction::Right => self.anim_rect = state.constants.npc.n043_chalkboard[1],
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -556,8 +563,12 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
pub(crate) fn tick_n072_sprinkler(&mut self, state: &mut SharedGameState, players: [&mut Player; 2], npc_list: &NPCList) -> GameResult {
|
||||
pub(crate) fn tick_n072_sprinkler(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
players: [&mut Player; 2],
|
||||
npc_list: &NPCList,
|
||||
) -> GameResult {
|
||||
if self.direction == Direction::Left {
|
||||
self.anim_counter = (self.anim_counter + 1) % 4;
|
||||
self.anim_num = self.anim_counter / 2;
|
||||
|
@ -587,7 +598,11 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n073_water_droplet(&mut self, state: &mut SharedGameState, stage: &Stage) -> GameResult {
|
||||
pub(crate) fn tick_n073_water_droplet(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
stage: &Stage,
|
||||
) -> GameResult {
|
||||
self.vel_y += 0x20;
|
||||
|
||||
self.anim_rect = state.constants.npc.n073_water_droplet[self.rng.range(0..4) as usize];
|
||||
|
@ -605,8 +620,12 @@ impl NPC {
|
|||
}
|
||||
|
||||
self.action_counter += 1;
|
||||
if self.action_counter > 10 && (self.flags.hit_left_wall() || self.flags.hit_right_wall()
|
||||
|| self.flags.hit_bottom_wall() || self.flags.in_water()) {
|
||||
if self.action_counter > 10
|
||||
&& (self.flags.hit_left_wall()
|
||||
|| self.flags.hit_right_wall()
|
||||
|| self.flags.hit_bottom_wall()
|
||||
|| self.flags.in_water())
|
||||
{
|
||||
// hit something
|
||||
self.cond.set_alive(false);
|
||||
}
|
||||
|
@ -637,8 +656,8 @@ impl NPC {
|
|||
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] }
|
||||
Direction::Left => self.anim_rect = state.constants.npc.n078_pot[0],
|
||||
Direction::Right => self.anim_rect = state.constants.npc.n078_pot[1],
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -646,13 +665,20 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n085_terminal(&mut self, state: &mut SharedGameState, players: [&mut Player; 2]) -> GameResult {
|
||||
pub(crate) fn tick_n085_terminal(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
players: [&mut Player; 2],
|
||||
) -> GameResult {
|
||||
match self.action_num {
|
||||
0 => {
|
||||
self.anim_num = 0;
|
||||
let player = self.get_closest_player_mut(players);
|
||||
|
||||
if abs(player.x - self.x) < 8 * 0x200 && player.y < self.y + 8 * 0x200 && player.y > self.y - 16 * 0x200 {
|
||||
if abs(player.x - self.x) < 8 * 0x200
|
||||
&& player.y < self.y + 8 * 0x200
|
||||
&& player.y > self.y - 16 * 0x200
|
||||
{
|
||||
state.sound_manager.play_sfx(43);
|
||||
self.action_num = 1;
|
||||
}
|
||||
|
@ -666,7 +692,11 @@ impl NPC {
|
|||
_ => {}
|
||||
}
|
||||
|
||||
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.n085_terminal[self.anim_num as usize + dir_offset];
|
||||
|
||||
Ok(())
|
||||
|
@ -681,7 +711,12 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n096_fan_left(&mut self, state: &mut SharedGameState, mut players: [&mut Player; 2], npc_list: &NPCList) -> GameResult {
|
||||
pub(crate) fn tick_n096_fan_left(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
mut players: [&mut Player; 2],
|
||||
npc_list: &NPCList,
|
||||
) -> GameResult {
|
||||
match self.action_num {
|
||||
0 | 1 => {
|
||||
if self.action_num == 0 && self.direction == Direction::Right {
|
||||
|
@ -702,8 +737,10 @@ impl NPC {
|
|||
|
||||
{
|
||||
let i = self.get_closest_player_idx_mut(&players);
|
||||
if abs(players[i].x - self.x) < 480 * 0x200 && abs(players[i].y - self.y) < 240 * 0x200
|
||||
&& self.rng.range(0..5) == 1 {
|
||||
if abs(players[i].x - self.x) < 480 * 0x200
|
||||
&& abs(players[i].y - self.y) < 240 * 0x200
|
||||
&& self.rng.range(0..5) == 1
|
||||
{
|
||||
let mut particle = NPC::create(199, &state.npc_table);
|
||||
particle.cond.set_alive(true);
|
||||
particle.direction = Direction::Left;
|
||||
|
@ -718,7 +755,10 @@ impl NPC {
|
|||
continue;
|
||||
}
|
||||
|
||||
if abs(player.y - self.y) < 8 * 0x200 && player.x < self.x && player.x > self.x - 96 * 0x200 {
|
||||
if abs(player.y - self.y) < 8 * 0x200
|
||||
&& player.x < self.x
|
||||
&& player.x > self.x - 96 * 0x200
|
||||
{
|
||||
player.vel_x -= 0x88;
|
||||
player.cond.set_increase_acceleration(true);
|
||||
}
|
||||
|
@ -734,7 +774,12 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n097_fan_up(&mut self, state: &mut SharedGameState, mut players: [&mut Player; 2], npc_list: &NPCList) -> GameResult {
|
||||
pub(crate) fn tick_n097_fan_up(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
mut players: [&mut Player; 2],
|
||||
npc_list: &NPCList,
|
||||
) -> GameResult {
|
||||
match self.action_num {
|
||||
0 | 1 => {
|
||||
if self.action_num == 0 && self.direction == Direction::Right {
|
||||
|
@ -755,8 +800,10 @@ impl NPC {
|
|||
|
||||
{
|
||||
let i = self.get_closest_player_idx_mut(&players);
|
||||
if abs(players[i].x - self.x) < 480 * 0x200 && abs(players[i].y - self.y) < 240 * 0x200
|
||||
&& self.rng.range(0..5) == 1 {
|
||||
if abs(players[i].x - self.x) < 480 * 0x200
|
||||
&& abs(players[i].y - self.y) < 240 * 0x200
|
||||
&& self.rng.range(0..5) == 1
|
||||
{
|
||||
let mut particle = NPC::create(199, &state.npc_table);
|
||||
particle.cond.set_alive(true);
|
||||
particle.direction = Direction::Up;
|
||||
|
@ -771,7 +818,10 @@ impl NPC {
|
|||
continue;
|
||||
}
|
||||
|
||||
if abs(player.x - self.x) < 8 * 0x200 && player.y < self.y && player.y > self.y - 96 * 0x200 {
|
||||
if abs(player.x - self.x) < 8 * 0x200
|
||||
&& player.y < self.y
|
||||
&& player.y > self.y - 96 * 0x200
|
||||
{
|
||||
player.vel_y -= 0x88;
|
||||
}
|
||||
}
|
||||
|
@ -786,7 +836,12 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n098_fan_right(&mut self, state: &mut SharedGameState, mut players: [&mut Player; 2], npc_list: &NPCList) -> GameResult {
|
||||
pub(crate) fn tick_n098_fan_right(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
mut players: [&mut Player; 2],
|
||||
npc_list: &NPCList,
|
||||
) -> GameResult {
|
||||
match self.action_num {
|
||||
0 | 1 => {
|
||||
if self.action_num == 0 && self.direction == Direction::Right {
|
||||
|
@ -807,8 +862,10 @@ impl NPC {
|
|||
|
||||
{
|
||||
let i = self.get_closest_player_idx_mut(&players);
|
||||
if abs(players[i].x - self.x) < 480 * 0x200 && abs(players[i].y - self.y) < 240 * 0x200
|
||||
&& self.rng.range(0..5) == 1 {
|
||||
if abs(players[i].x - self.x) < 480 * 0x200
|
||||
&& abs(players[i].y - self.y) < 240 * 0x200
|
||||
&& self.rng.range(0..5) == 1
|
||||
{
|
||||
let mut particle = NPC::create(199, &state.npc_table);
|
||||
particle.cond.set_alive(true);
|
||||
particle.direction = Direction::Right;
|
||||
|
@ -819,7 +876,10 @@ impl NPC {
|
|||
}
|
||||
|
||||
for player in players.iter_mut() {
|
||||
if abs(player.y - self.y) < 8 * 0x200 && player.x > self.x && player.x < self.x + 96 * 0x200 {
|
||||
if abs(player.y - self.y) < 8 * 0x200
|
||||
&& player.x > self.x
|
||||
&& player.x < self.x + 96 * 0x200
|
||||
{
|
||||
player.vel_x += 0x88;
|
||||
player.cond.set_increase_acceleration(true);
|
||||
}
|
||||
|
@ -835,7 +895,12 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n099_fan_down(&mut self, state: &mut SharedGameState, mut players: [&mut Player; 2], npc_list: &NPCList) -> GameResult {
|
||||
pub(crate) fn tick_n099_fan_down(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
mut players: [&mut Player; 2],
|
||||
npc_list: &NPCList,
|
||||
) -> GameResult {
|
||||
match self.action_num {
|
||||
0 | 1 => {
|
||||
if self.action_num == 0 && self.direction == Direction::Right {
|
||||
|
@ -856,8 +921,10 @@ impl NPC {
|
|||
|
||||
{
|
||||
let i = self.get_closest_player_idx_mut(&players);
|
||||
if abs(players[i].x - self.x) < 480 * 0x200 && abs(players[i].y - self.y) < 240 * 0x200
|
||||
&& self.rng.range(0..5) == 1 {
|
||||
if abs(players[i].x - self.x) < 480 * 0x200
|
||||
&& abs(players[i].y - self.y) < 240 * 0x200
|
||||
&& self.rng.range(0..5) == 1
|
||||
{
|
||||
let mut particle = NPC::create(199, &state.npc_table);
|
||||
particle.cond.set_alive(true);
|
||||
particle.direction = Direction::Bottom;
|
||||
|
@ -868,7 +935,10 @@ impl NPC {
|
|||
}
|
||||
|
||||
for player in players.iter_mut() {
|
||||
if abs(player.x - self.x) < 8 * 0x200 && player.y > self.y && player.y < self.y + 96 * 0x200 {
|
||||
if abs(player.x - self.x) < 8 * 0x200
|
||||
&& player.y > self.y
|
||||
&& player.y < self.y + 96 * 0x200
|
||||
{
|
||||
player.vel_y -= 0x88;
|
||||
}
|
||||
}
|
||||
|
@ -897,7 +967,11 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n106_hey_bubble_high(&mut self, state: &mut SharedGameState, npc_list: &NPCList) -> GameResult {
|
||||
pub(crate) fn tick_n106_hey_bubble_high(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
npc_list: &NPCList,
|
||||
) -> GameResult {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
|
||||
|
@ -912,7 +986,12 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n114_press(&mut self, state: &mut SharedGameState, players: [&mut Player; 2], npc_list: &NPCList) -> GameResult {
|
||||
pub(crate) fn tick_n114_press(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
players: [&mut Player; 2],
|
||||
npc_list: &NPCList,
|
||||
) -> GameResult {
|
||||
match self.action_num {
|
||||
0 | 1 => {
|
||||
if self.action_num == 0 {
|
||||
|
@ -1004,9 +1083,20 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n125_hidden_item(&mut self, state: &mut SharedGameState, npc_list: &NPCList) -> GameResult {
|
||||
pub(crate) fn tick_n125_hidden_item(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
npc_list: &NPCList,
|
||||
) -> GameResult {
|
||||
if self.life < 990 {
|
||||
npc_list.create_death_smoke(self.x, self.y, self.display_bounds.right, 8, state, &self.rng);
|
||||
npc_list.create_death_smoke(
|
||||
self.x,
|
||||
self.y,
|
||||
self.display_bounds.right,
|
||||
8,
|
||||
state,
|
||||
&self.rng,
|
||||
);
|
||||
self.cond.set_alive(false);
|
||||
state.sound_manager.play_sfx(70);
|
||||
|
||||
|
@ -1051,7 +1141,12 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n149_horizontal_moving_block(&mut self, state: &mut SharedGameState, players: [&mut Player; 2], npc_list: &NPCList) -> GameResult {
|
||||
pub(crate) fn tick_n149_horizontal_moving_block(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
players: [&mut Player; 2],
|
||||
npc_list: &NPCList,
|
||||
) -> GameResult {
|
||||
match self.action_num {
|
||||
0 => {
|
||||
self.x += 8 * 0x200;
|
||||
|
@ -1059,14 +1154,21 @@ impl NPC {
|
|||
self.npc_flags.set_solid_hard(true);
|
||||
self.vel_x = 0;
|
||||
self.vel_y = 0;
|
||||
self.action_num = if self.direction == Direction::Right { 20 } else { 10 };
|
||||
self.action_num = if self.direction == Direction::Right {
|
||||
20
|
||||
} else {
|
||||
10
|
||||
};
|
||||
}
|
||||
10 => {
|
||||
self.npc_flags.set_rear_and_top_not_hurt(false);
|
||||
self.damage = 0;
|
||||
let player = self.get_closest_player_mut(players);
|
||||
if (player.x < self.x + 25 * 0x200) && (player.x > self.x - 25 * 16 * 0x200)
|
||||
&& (player.y < self.y + 25 * 0x200) && (player.y > self.y - 25 * 0x200) {
|
||||
if (player.x < self.x + 25 * 0x200)
|
||||
&& (player.x > self.x - 25 * 16 * 0x200)
|
||||
&& (player.y < self.y + 25 * 0x200)
|
||||
&& (player.y > self.y - 25 * 0x200)
|
||||
{
|
||||
self.action_num = 11;
|
||||
self.action_counter = 0;
|
||||
}
|
||||
|
@ -1113,8 +1215,11 @@ impl NPC {
|
|||
self.damage = 0;
|
||||
|
||||
let player = self.get_closest_player_mut(players);
|
||||
if (player.x > self.x - 25 * 0x200) && (player.x < self.x + 25 * 16 * 0x200)
|
||||
&& (player.y < self.y + 25 * 0x200) && (player.y > self.y - 25 * 0x200) {
|
||||
if (player.x > self.x - 25 * 0x200)
|
||||
&& (player.x < self.x + 25 * 16 * 0x200)
|
||||
&& (player.y < self.y + 25 * 0x200)
|
||||
&& (player.y > self.y - 25 * 0x200)
|
||||
{
|
||||
self.action_num = 21;
|
||||
self.action_counter = 0;
|
||||
}
|
||||
|
@ -1178,13 +1283,23 @@ impl NPC {
|
|||
self.y += 0x2000;
|
||||
}
|
||||
|
||||
self.anim_rect = Rect { left: 0, top: 0, right: 0, bottom: 0 };
|
||||
self.anim_rect = Rect {
|
||||
left: 0,
|
||||
top: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
};
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n157_vertical_moving_block(&mut self, state: &mut SharedGameState, players: [&mut Player; 2], npc_list: &NPCList) -> GameResult {
|
||||
pub(crate) fn tick_n157_vertical_moving_block(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
players: [&mut Player; 2],
|
||||
npc_list: &NPCList,
|
||||
) -> GameResult {
|
||||
match self.action_num {
|
||||
0 => {
|
||||
self.x += 8 * 0x200;
|
||||
|
@ -1192,14 +1307,21 @@ impl NPC {
|
|||
self.npc_flags.set_solid_hard(true);
|
||||
self.vel_x = 0;
|
||||
self.vel_y = 0;
|
||||
self.action_num = if self.direction == Direction::Right { 20 } else { 10 };
|
||||
self.action_num = if self.direction == Direction::Right {
|
||||
20
|
||||
} else {
|
||||
10
|
||||
};
|
||||
}
|
||||
10 => {
|
||||
self.npc_flags.set_rear_and_top_not_hurt(false);
|
||||
self.damage = 0;
|
||||
let player = self.get_closest_player_mut(players);
|
||||
if (player.y < self.y + 25 * 0x200) && (player.y > self.y - 25 * 16 * 0x200)
|
||||
&& (player.x < self.x + 25 * 0x200) && (player.x > self.x - 25 * 0x200) {
|
||||
if (player.y < self.y + 25 * 0x200)
|
||||
&& (player.y > self.y - 25 * 16 * 0x200)
|
||||
&& (player.x < self.x + 25 * 0x200)
|
||||
&& (player.x > self.x - 25 * 0x200)
|
||||
{
|
||||
self.action_num = 11;
|
||||
self.action_counter = 0;
|
||||
}
|
||||
|
@ -1246,8 +1368,11 @@ impl NPC {
|
|||
self.damage = 0;
|
||||
|
||||
let player = self.get_closest_player_mut(players);
|
||||
if (player.y > self.y - 25 * 0x200) && (player.y < self.y + 25 * 16 * 0x200)
|
||||
&& (player.x < self.x + 25 * 0x200) && (player.x > self.x - 25 * 0x200) {
|
||||
if (player.y > self.y - 25 * 0x200)
|
||||
&& (player.y < self.y + 25 * 16 * 0x200)
|
||||
&& (player.x < self.x + 25 * 0x200)
|
||||
&& (player.x > self.x - 25 * 0x200)
|
||||
{
|
||||
self.action_num = 21;
|
||||
self.action_counter = 0;
|
||||
}
|
||||
|
@ -1303,7 +1428,10 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n194_broken_blue_robot(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
pub(crate) fn tick_n194_broken_blue_robot(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
) -> GameResult {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
self.y += 4 * 0x200;
|
||||
|
@ -1389,12 +1517,19 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n229_red_flowers_sprouts(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
pub(crate) fn tick_n229_red_flowers_sprouts(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
) -> GameResult {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
self.y -= 0x2000;
|
||||
|
||||
let anim = if self.direction == Direction::Left { 0 } else { 1 };
|
||||
let anim = if self.direction == Direction::Left {
|
||||
0
|
||||
} else {
|
||||
1
|
||||
};
|
||||
|
||||
self.anim_rect = state.constants.npc.n229_red_flowers_sprouts[anim];
|
||||
}
|
||||
|
@ -1402,13 +1537,20 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n230_red_flowers_blooming(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
pub(crate) fn tick_n230_red_flowers_blooming(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
) -> GameResult {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
self.x -= 0x2000;
|
||||
self.y -= 0x2000;
|
||||
|
||||
let anim = if self.direction == Direction::Left { 0 } else { 1 };
|
||||
let anim = if self.direction == Direction::Left {
|
||||
0
|
||||
} else {
|
||||
1
|
||||
};
|
||||
|
||||
self.anim_rect = state.constants.npc.n230_red_flowers_blooming[anim];
|
||||
}
|
||||
|
@ -1416,7 +1558,10 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n234_red_flowers_picked(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
pub(crate) fn tick_n234_red_flowers_picked(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
) -> GameResult {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
self.y += 16 * 0x200;
|
||||
|
@ -1444,7 +1589,11 @@ impl NPC {
|
|||
}
|
||||
}
|
||||
|
||||
let anim = if self.direction == Direction::Left { 0 } else { 1 };
|
||||
let anim = if self.direction == Direction::Left {
|
||||
0
|
||||
} else {
|
||||
1
|
||||
};
|
||||
|
||||
self.anim_rect = state.constants.npc.n239_cage_bars[anim];
|
||||
|
||||
|
@ -1466,7 +1615,11 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n297_sue_dragon_mouth(&mut self, state: &mut SharedGameState, npc_list: &NPCList) -> GameResult {
|
||||
pub(crate) fn tick_n297_sue_dragon_mouth(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
npc_list: &NPCList,
|
||||
) -> GameResult {
|
||||
if let Some(npc) = self.get_parent_ref_mut(npc_list) {
|
||||
self.x = npc.x + 0x2000;
|
||||
self.y = npc.y + 0x1000;
|
||||
|
@ -1477,7 +1630,12 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n302_camera_focus_marker(&mut self, state: &mut SharedGameState, players: [&mut Player; 2], npc_list: &NPCList) -> GameResult {
|
||||
pub(crate) fn tick_n302_camera_focus_marker(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
players: [&mut Player; 2],
|
||||
npc_list: &NPCList,
|
||||
) -> GameResult {
|
||||
let player = &players[state.textscript_vm.executor_player.index()];
|
||||
|
||||
match self.action_num {
|
||||
|
@ -1485,15 +1643,13 @@ impl NPC {
|
|||
self.x = player.x;
|
||||
self.y = player.y - 0x4000;
|
||||
}
|
||||
20 => {
|
||||
match self.direction {
|
||||
Direction::Left => self.x -= 0x400,
|
||||
Direction::Up => self.y -= 0x400,
|
||||
Direction::Right => self.x += 0x400,
|
||||
Direction::Bottom => self.y += 0x400,
|
||||
_=>{}
|
||||
}
|
||||
}
|
||||
20 => match self.direction {
|
||||
Direction::Left => self.x -= 0x400,
|
||||
Direction::Up => self.y -= 0x400,
|
||||
Direction::Right => self.x += 0x400,
|
||||
Direction::Bottom => self.y += 0x400,
|
||||
_ => {}
|
||||
},
|
||||
30 => {
|
||||
self.x = player.x;
|
||||
self.y = player.y + 0xa000;
|
||||
|
@ -1529,7 +1685,10 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n328_human_transform_machine(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
pub(crate) fn tick_n328_human_transform_machine(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
) -> GameResult {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
self.anim_rect = state.constants.npc.n328_human_transform_machine;
|
||||
|
@ -1540,7 +1699,8 @@ impl NPC {
|
|||
|
||||
pub(crate) fn tick_n329_laboratory_fan(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
self.anim_counter = self.anim_counter.wrapping_add(1);
|
||||
self.anim_rect = state.constants.npc.n329_laboratory_fan[(self.anim_counter as usize / 2) & 1];
|
||||
self.anim_rect =
|
||||
state.constants.npc.n329_laboratory_fan[(self.anim_counter as usize / 2) & 1];
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1561,8 +1721,11 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
pub(crate) fn tick_n351_statue_shootable(&mut self, state: &mut SharedGameState, npc_list: &NPCList) -> GameResult {
|
||||
pub(crate) fn tick_n351_statue_shootable(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
npc_list: &NPCList,
|
||||
) -> GameResult {
|
||||
match self.action_num {
|
||||
0 => {
|
||||
self.action_num = 1;
|
||||
|
@ -1572,7 +1735,7 @@ impl NPC {
|
|||
}
|
||||
10 | 11 => {
|
||||
if self.action_num == 10 {
|
||||
if let Some(true) = state.game_flags.get(self.flag_num as usize) {
|
||||
if state.get_flag(self.flag_num as usize) {
|
||||
self.action_num = 20;
|
||||
} else {
|
||||
self.action_num = 11;
|
||||
|
@ -1603,7 +1766,11 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n352_ending_characters(&mut self, state: &mut SharedGameState, npc_list: &NPCList) -> GameResult {
|
||||
pub(crate) fn tick_n352_ending_characters(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
npc_list: &NPCList,
|
||||
) -> GameResult {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
self.anim_num = 0;
|
||||
|
@ -1647,12 +1814,17 @@ impl NPC {
|
|||
|
||||
self.y += self.vel_y;
|
||||
|
||||
self.anim_rect = state.constants.npc.n352_ending_characters[(2 * self.action_counter2 as usize + self.anim_num as usize) % 28];
|
||||
self.anim_rect = state.constants.npc.n352_ending_characters
|
||||
[(2 * self.action_counter2 as usize + self.anim_num as usize) % 28];
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n355_quote_and_curly_on_balrog(&mut self, state: &mut SharedGameState, npc_list: &NPCList) -> GameResult {
|
||||
pub(crate) fn tick_n355_quote_and_curly_on_balrog(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
npc_list: &NPCList,
|
||||
) -> GameResult {
|
||||
if self.action_num == 0 {
|
||||
match self.direction {
|
||||
Direction::Left => {
|
||||
|
@ -1712,12 +1884,18 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n359_water_droplet_generator(&mut self, state: &mut SharedGameState, players: [&mut Player; 2], npc_list: &NPCList) -> GameResult {
|
||||
pub(crate) fn tick_n359_water_droplet_generator(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
players: [&mut Player; 2],
|
||||
npc_list: &NPCList,
|
||||
) -> GameResult {
|
||||
let player = self.get_closest_player_mut(players);
|
||||
if abs(player.x - self.x) < 320 * 0x200
|
||||
&& player.y < self.y + 320 * 0x200
|
||||
&& player.y > self.y - 160 * 0x200
|
||||
&& self.rng.range(0..100) == 2 {
|
||||
&& self.rng.range(0..100) == 2
|
||||
{
|
||||
let mut npc = NPC::create(73, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
npc.x = self.x + self.rng.range(-6..6) * 0x200;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use num_traits::clamp;
|
||||
|
||||
use crate::common::Direction;
|
||||
use crate::framework::context::Context;
|
||||
use crate::framework::error::GameResult;
|
||||
use crate::npc::list::NPCList;
|
||||
use crate::npc::NPC;
|
||||
|
|
|
@ -157,7 +157,7 @@ impl Player {
|
|||
self.air_counter = 60;
|
||||
if self.air > 0 {
|
||||
self.air -= 1;
|
||||
} else if let Some(true) = state.game_flags.get(4000) {
|
||||
} else if state.get_flag(4000) {
|
||||
state.textscript_vm.start_script(1100);
|
||||
} else {
|
||||
self.cond.set_hidden(true);
|
||||
|
@ -692,20 +692,6 @@ impl GameEntity<&NPCList> for Player {
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
{
|
||||
let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "MyChar")?;
|
||||
batch.add_rect(
|
||||
interpolate_fix9_scale(self.prev_x - self.display_bounds.left as i32 - frame.prev_x,
|
||||
self.x - self.display_bounds.left as i32 - frame.x,
|
||||
state.frame_time),
|
||||
interpolate_fix9_scale(self.prev_y - self.display_bounds.left as i32 - frame.prev_y,
|
||||
self.y - self.display_bounds.left as i32 - frame.y,
|
||||
state.frame_time),
|
||||
&self.anim_rect,
|
||||
);
|
||||
batch.draw(ctx)?;
|
||||
}
|
||||
|
||||
if self.current_weapon != 0 {
|
||||
let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "Arms")?;
|
||||
match self.direction {
|
||||
|
@ -737,6 +723,20 @@ impl GameEntity<&NPCList> for Player {
|
|||
batch.draw(ctx)?;
|
||||
}
|
||||
|
||||
{
|
||||
let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "MyChar")?;
|
||||
batch.add_rect(
|
||||
interpolate_fix9_scale(self.prev_x - self.display_bounds.left as i32 - frame.prev_x,
|
||||
self.x - self.display_bounds.left as i32 - frame.x,
|
||||
state.frame_time),
|
||||
interpolate_fix9_scale(self.prev_y - self.display_bounds.left as i32 - frame.prev_y,
|
||||
self.y - self.display_bounds.left as i32 - frame.y,
|
||||
state.frame_time),
|
||||
&self.anim_rect,
|
||||
);
|
||||
batch.draw(ctx)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -174,7 +174,7 @@ impl GameProfile {
|
|||
|
||||
let mut bidx = 0;
|
||||
let mut flags = [0u8; 1000];
|
||||
for bits in state.game_flags.as_slice() {
|
||||
for bits in state.game_flags.as_raw_slice() {
|
||||
let bytes = bits.to_le_bytes();
|
||||
for b in bytes.iter() {
|
||||
if let Some(out) = flags.get_mut(bidx) {
|
||||
|
|
|
@ -1085,11 +1085,11 @@ impl Scene for GameScene {
|
|||
|
||||
let mut npc = NPC::create_from_data(npc_data, &state.npc_table);
|
||||
if npc.npc_flags.appear_when_flag_set() {
|
||||
if let Some(true) = state.game_flags.get(npc_data.flag_num as usize) {
|
||||
if state.get_flag(npc_data.flag_num as usize) {
|
||||
npc.cond.set_alive(true);
|
||||
}
|
||||
} else if npc.npc_flags.hide_unless_flag_set() {
|
||||
if let Some(false) = state.game_flags.get(npc_data.flag_num as usize) {
|
||||
if !state.get_flag(npc_data.flag_num as usize) {
|
||||
npc.cond.set_alive(true);
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -36,11 +36,11 @@ impl Doukutsu {
|
|||
0
|
||||
}
|
||||
|
||||
unsafe fn lua_flag(&self, state: &mut State) -> c_int {
|
||||
unsafe fn lua_get_flag(&self, state: &mut State) -> c_int {
|
||||
if let Some(index) = state.to_int(2) {
|
||||
let game_state = &mut (*(*self.ptr).state_ptr);
|
||||
|
||||
state.push(*game_state.game_flags.get(index.max(0) as usize).unwrap_or(&false));
|
||||
state.push(game_state.get_flag(index.max(0) as usize));
|
||||
} else {
|
||||
state.push_nil();
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ impl LuaObject for Doukutsu {
|
|||
vec![
|
||||
lua_method!("play_sfx", Doukutsu, Doukutsu::lua_play_sfx),
|
||||
lua_method!("play_song", Doukutsu, Doukutsu::lua_play_song),
|
||||
lua_method!("get_flag", Doukutsu, Doukutsu::lua_get_flag),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,9 +9,13 @@ use crate::bmfont_renderer::BMFontRenderer;
|
|||
use crate::caret::{Caret, CaretType};
|
||||
use crate::common::{ControlFlags, Direction, FadeState};
|
||||
use crate::engine_constants::EngineConstants;
|
||||
use crate::framework::backend::BackendTexture;
|
||||
use crate::framework::context::Context;
|
||||
use crate::framework::error::GameResult;
|
||||
use crate::framework::graphics::{create_texture_mutable, set_render_target};
|
||||
use crate::framework::keyboard::ScanCode;
|
||||
use crate::framework::vfs::OpenOptions;
|
||||
use crate::framework::{filesystem, graphics};
|
||||
use crate::input::touch_controls::TouchControls;
|
||||
use crate::npc::NPCTable;
|
||||
use crate::profile::GameProfile;
|
||||
|
@ -26,10 +30,6 @@ use crate::stage::StageData;
|
|||
use crate::str;
|
||||
use crate::text_script::{ScriptMode, TextScriptExecutionState, TextScriptVM};
|
||||
use crate::texture_set::TextureSet;
|
||||
use crate::framework::{filesystem, graphics};
|
||||
use crate::framework::backend::BackendTexture;
|
||||
use crate::framework::graphics::{set_render_target, create_texture_mutable};
|
||||
use crate::framework::keyboard::ScanCode;
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone)]
|
||||
pub enum TimingMode {
|
||||
|
@ -41,30 +41,29 @@ pub enum TimingMode {
|
|||
impl TimingMode {
|
||||
pub fn get_delta(self) -> usize {
|
||||
match self {
|
||||
TimingMode::_50Hz => { 1000000000 / 50 }
|
||||
TimingMode::_60Hz => { 1000000000 / 60 }
|
||||
TimingMode::FrameSynchronized => { 0 }
|
||||
TimingMode::_50Hz => 1000000000 / 50,
|
||||
TimingMode::_60Hz => 1000000000 / 60,
|
||||
TimingMode::FrameSynchronized => 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_delta_millis(self) -> f64 {
|
||||
match self {
|
||||
TimingMode::_50Hz => { 1000.0 / 50.0 }
|
||||
TimingMode::_60Hz => { 1000.0 / 60.0 }
|
||||
TimingMode::FrameSynchronized => { 0.0 }
|
||||
TimingMode::_50Hz => 1000.0 / 50.0,
|
||||
TimingMode::_60Hz => 1000.0 / 60.0,
|
||||
TimingMode::FrameSynchronized => 0.0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_tps(self) -> usize {
|
||||
match self {
|
||||
TimingMode::_50Hz => { 50 }
|
||||
TimingMode::_60Hz => { 60 }
|
||||
TimingMode::FrameSynchronized => { 0 }
|
||||
TimingMode::_50Hz => 50,
|
||||
TimingMode::_60Hz => 60,
|
||||
TimingMode::FrameSynchronized => 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone)]
|
||||
pub enum Season {
|
||||
None,
|
||||
|
@ -119,7 +118,7 @@ pub struct SharedGameState {
|
|||
pub lua: LuaScriptingState,
|
||||
pub sound_manager: SoundManager,
|
||||
pub settings: Settings,
|
||||
pub shutdown: bool
|
||||
pub shutdown: bool,
|
||||
}
|
||||
|
||||
impl SharedGameState {
|
||||
|
@ -191,11 +190,13 @@ impl SharedGameState {
|
|||
|
||||
pub fn process_debug_keys(&mut self, key_code: ScanCode) {
|
||||
match key_code {
|
||||
ScanCode::F3 => { self.settings.god_mode = !self.settings.god_mode }
|
||||
ScanCode::F4 => { self.settings.infinite_booster = !self.settings.infinite_booster }
|
||||
ScanCode::F5 => { self.settings.subpixel_coords = !self.settings.subpixel_coords }
|
||||
ScanCode::F6 => { self.settings.motion_interpolation = !self.settings.motion_interpolation }
|
||||
ScanCode::F7 => { self.set_speed(1.0) }
|
||||
ScanCode::F3 => self.settings.god_mode = !self.settings.god_mode,
|
||||
ScanCode::F4 => self.settings.infinite_booster = !self.settings.infinite_booster,
|
||||
ScanCode::F5 => self.settings.subpixel_coords = !self.settings.subpixel_coords,
|
||||
ScanCode::F6 => {
|
||||
self.settings.motion_interpolation = !self.settings.motion_interpolation
|
||||
}
|
||||
ScanCode::F7 => self.set_speed(1.0),
|
||||
ScanCode::F8 => {
|
||||
if self.settings.speed > 0.2 {
|
||||
self.set_speed(self.settings.speed - 0.1);
|
||||
|
@ -206,7 +207,7 @@ impl SharedGameState {
|
|||
self.set_speed(self.settings.speed + 0.1);
|
||||
}
|
||||
}
|
||||
ScanCode::F10 => { self.settings.debug_outlines = !self.settings.debug_outlines }
|
||||
ScanCode::F10 => self.settings.debug_outlines = !self.settings.debug_outlines,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -230,7 +231,7 @@ impl SharedGameState {
|
|||
self.textscript_vm.state = TextScriptExecutionState::Running(200, 0);
|
||||
|
||||
#[cfg(feature = "scripting")]
|
||||
self.lua.reload_scripts(ctx)?;
|
||||
self.lua.reload_scripts(ctx)?;
|
||||
|
||||
self.next_scene = Some(Box::new(next_scene));
|
||||
|
||||
|
@ -247,7 +248,7 @@ impl SharedGameState {
|
|||
self.textscript_vm.state = TextScriptExecutionState::Running(100, 0);
|
||||
|
||||
#[cfg(feature = "scripting")]
|
||||
self.lua.reload_scripts(ctx)?;
|
||||
self.lua.reload_scripts(ctx)?;
|
||||
|
||||
self.next_scene = Some(Box::new(next_scene));
|
||||
|
||||
|
@ -255,7 +256,11 @@ impl SharedGameState {
|
|||
}
|
||||
|
||||
pub fn save_game(&mut self, game_scene: &mut GameScene, ctx: &mut Context) -> GameResult {
|
||||
if let Ok(data) = filesystem::open_options(ctx, "/Profile.dat", OpenOptions::new().write(true).create(true)) {
|
||||
if let Ok(data) = filesystem::open_options(
|
||||
ctx,
|
||||
"/Profile.dat",
|
||||
OpenOptions::new().write(true).create(true),
|
||||
) {
|
||||
let profile = GameProfile::dump(self, game_scene);
|
||||
profile.write_save(data)?;
|
||||
} else {
|
||||
|
@ -275,7 +280,7 @@ impl SharedGameState {
|
|||
profile.apply(self, &mut next_scene, ctx);
|
||||
|
||||
#[cfg(feature = "scripting")]
|
||||
self.lua.reload_scripts(ctx)?;
|
||||
self.lua.reload_scripts(ctx)?;
|
||||
|
||||
self.next_scene = Some(Box::new(next_scene));
|
||||
return Ok(());
|
||||
|
@ -306,7 +311,10 @@ impl SharedGameState {
|
|||
pub fn handle_resize(&mut self, ctx: &mut Context) -> GameResult {
|
||||
self.screen_size = graphics::screen_size(ctx);
|
||||
self.scale = self.screen_size.1.div(230.0).floor().max(1.0);
|
||||
self.canvas_size = (self.screen_size.0 / self.scale, self.screen_size.1 / self.scale);
|
||||
self.canvas_size = (
|
||||
self.screen_size.0 / self.scale,
|
||||
self.screen_size.1 / self.scale,
|
||||
);
|
||||
|
||||
let (width, height) = (self.screen_size.0 as u16, self.screen_size.1 as u16);
|
||||
|
||||
|
@ -326,7 +334,8 @@ impl SharedGameState {
|
|||
}
|
||||
|
||||
pub fn create_caret(&mut self, x: i32, y: i32, ctype: CaretType, direct: Direction) {
|
||||
self.carets.push(Caret::new(x, y, ctype, direct, &self.constants));
|
||||
self.carets
|
||||
.push(Caret::new(x, y, ctype, direct, &self.constants));
|
||||
}
|
||||
|
||||
pub fn set_speed(&mut self, value: f64) {
|
||||
|
@ -341,4 +350,20 @@ impl SharedGameState {
|
|||
pub fn shutdown(&mut self) {
|
||||
self.shutdown = true;
|
||||
}
|
||||
|
||||
pub fn set_flag(&mut self, id: usize, value: bool) {
|
||||
if id < self.game_flags.len() {
|
||||
self.game_flags.set(id, value);
|
||||
} else {
|
||||
log::warn!("Attempted to set an out-of-bounds flag {}:", id);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_flag(&self, id: usize) -> bool {
|
||||
if let Some(flag) = self.game_flags.get(id) {
|
||||
*flag
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -854,7 +854,7 @@ impl TextScriptVM {
|
|||
OpCode::FLJ => {
|
||||
let flag_num = read_cur_varint(&mut cursor)? as usize;
|
||||
let event_num = read_cur_varint(&mut cursor)? as u16;
|
||||
if let Some(true) = state.game_flags.get(flag_num) {
|
||||
if state.get_flag(flag_num) {
|
||||
exec_state = TextScriptExecutionState::Running(event_num, 0);
|
||||
} else {
|
||||
exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32);
|
||||
|
|
|
@ -187,7 +187,7 @@ impl SizedBatch {
|
|||
self.draw_filtered(FilterMode::Nearest, ctx)
|
||||
}
|
||||
|
||||
pub fn draw_filtered(&mut self, filter: FilterMode, ctx: &mut Context) -> GameResult {
|
||||
pub fn draw_filtered(&mut self, _filter: FilterMode, _ctx: &mut Context) -> GameResult {
|
||||
//self.batch.set_filter(filter);
|
||||
self.batch.draw()?;
|
||||
self.batch.clear();
|
||||
|
@ -236,7 +236,7 @@ impl TextureSet {
|
|||
reader.seek(SeekFrom::Start(0))?;
|
||||
|
||||
let image = image::load(BufReader::new(reader), image::guess_format(&buf)?)?;
|
||||
let mut rgba = image.to_rgba();
|
||||
let mut rgba = image.to_rgba8();
|
||||
if image.color().channel_count() != 4 {
|
||||
TextureSet::make_transparent(&mut rgba);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue