Lua time
This commit is contained in:
parent
81a422502c
commit
e092a9e2ea
|
@ -40,11 +40,17 @@ opt-level = 1
|
|||
[profile.release.build-override]
|
||||
opt-level = 1
|
||||
|
||||
[features]
|
||||
default = ["scripting"]
|
||||
scripting = ["lua-ffi"]
|
||||
editor = []
|
||||
|
||||
[dependencies]
|
||||
#cpal = {path = "./3rdparty/cpal"}
|
||||
#gfx_device_gl = {path = "./3rdparty/gfx/src/backend/gl"}
|
||||
#ggez = {path = "./3rdparty/ggez"}
|
||||
#glutin = {path = "./3rdparty/glutin/glutin"}
|
||||
#lua-ffi = {path = "./3rdparty/luajit-rs", optional = true}
|
||||
|
||||
bitvec = "0.17.4"
|
||||
byteorder = "1.3"
|
||||
|
@ -64,6 +70,7 @@ image = {version = "0.22", default-features = false, features = ["png_codec", "p
|
|||
itertools = "0.9.0"
|
||||
lazy_static = "1.4.0"
|
||||
log = "0.4"
|
||||
lua-ffi = {git = "https://github.com/doukutsu-rs/lua-ffi.git", rev = "a1e7a62d7f583836b4703cfb8e54a68b79ceee11", optional = true}
|
||||
lru = "0.6.0"
|
||||
num-derive = "0.3.2"
|
||||
num-traits = "0.2.12"
|
||||
|
|
38
README.md
38
README.md
|
@ -14,9 +14,9 @@ A re-implementation of Cave Story (Doukutsu Monogatari) engine written in [Rust]
|
|||
|
||||
This repository does not contain any copyrighted files.
|
||||
|
||||
For better user experience, pre-built binaries are distributed with slightly modified freeware game files.
|
||||
For better user experience, pre-built binaries are distributed with slightly modified freeware game files.
|
||||
|
||||
*doukutsu-rs* should work fine with [CSE2-Enhanced](https://github.com/Clownacy/CSE2) or [NXEngine(-evo)](https://github.com/nxengine/nxengine-evo) freeware data files and [Cave Story+](https://www.nicalis.com/games/cavestory+) data files.
|
||||
*doukutsu-rs* should work fine with pre-extracted and tweaked data files from [this repository](https://github.com/doukutsu-rs/game-data), [NXEngine(-evo)](https://github.com/nxengine/nxengine-evo) extracted freeware data files and [Cave Story+](https://www.nicalis.com/games/cavestory+) data files.
|
||||
|
||||
Vanilla Cave Story does not work yet because some important data files have been embedded inside the executable. and we don't have a loader/extractor implemented yet.
|
||||
|
||||
|
@ -25,30 +25,20 @@ Vanilla Cave Story does not work yet because some important data files have been
|
|||
**Freeware**
|
||||
|
||||
- https://github.com/doukutsu-rs/game-data - Freeware game data distributed with CI builds, based on those two below.
|
||||
- https://github.com/Clownacy/CSE2/archive/enhanced.zip - copy `game_english/data` from archive to the runtime directory (place you run the executable from, usually project root)
|
||||
- ~~https://github.com/Clownacy/CSE2/archive/enhanced.zip - copy `game_english/data` from archive to the runtime directory (place you run the executable from, usually project root)~~
|
||||
- https://github.com/nxengine/nxengine-evo/releases/download/v2.6.4/NXEngine-v2.6.4-Win32.zip - copy `NXEngine-evo-2.6.4-xxx/data` from the archive to runtime directory
|
||||
|
||||
**Cave Story+**
|
||||
|
||||
- PC release - (Tested only with Steam version, both Windows and Linux builds) Copy `data` folder from installation directory ([guide for Steam](https://steamcommunity.com/sharedfiles/filedetails/?id=760447682)) to the runtime directory.
|
||||
- Switch release - **Not supported or actively tested.** Some of release-specific opcodes have been implemented (no code
|
||||
decompilation was involved, just pure data file analysis), so you should be able to play it without any major issues.
|
||||
Because methods used to extract game data from cartridge vary, you have to find that out on your own.
|
||||
- PC release (Steam) - (Tested only with Steam version, both Windows and Linux builds) Copy `data` folder from installation directory ([guide for Steam](https://steamcommunity.com/sharedfiles/filedetails/?id=760447682)) to the runtime directory.
|
||||
- PC release (EGS) - (Untested, but the game is essentially the same as Steam release) Same thing as with Steam version.
|
||||
- Switch release - (Tested once, no guarantee to work) You need a hacked Switch and physical release. Google should help you.
|
||||
|
||||
#### Gameplay support roadmap
|
||||
|
||||
- [x] Checkmarked things = fully implemented
|
||||
- [ ] Unmarked things = partially or not implemented yet.
|
||||
|
||||
- [x] Rendering
|
||||
- [x] Backdrops
|
||||
- [x] Tilemap
|
||||
- [x] Player and it's animations
|
||||
- [x] Carets
|
||||
- [x] Bullets
|
||||
- [x] NPCs
|
||||
- [x] Text
|
||||
- [x] HUD
|
||||
- [ ] Text scripts (TSC)
|
||||
- [x] Initial implementation
|
||||
- [x] Full implementation of gameplay opcodes
|
||||
|
@ -79,9 +69,6 @@ Because methods used to extract game data from cartridge vary, you have to find
|
|||
- [ ] Last Cave
|
||||
- [ ] Balcony
|
||||
- [ ] Hell
|
||||
- [ ] Cave Story+ specific NPCs
|
||||
- [x] Dashing Gaudis (361)
|
||||
- [ ] ??? (362)
|
||||
- [ ] Weapons
|
||||
- [x] Leveling / XP system
|
||||
- [x] Initial implementation
|
||||
|
@ -99,15 +86,14 @@ Because methods used to extract game data from cartridge vary, you have to find
|
|||
- [ ] Support for different game editions
|
||||
- [ ] Vanilla
|
||||
- [x] Modified vanilla
|
||||
- [ ] Cave Story+
|
||||
- [ ] Cave Story+ (PC/Switch)
|
||||
- [x] Base mod
|
||||
- [ ] Mod loading
|
||||
- [x] Curly Story
|
||||
- [ ] Wind Fortress (~40%)
|
||||
- [ ] Wind Fortress
|
||||
- [ ] Boss Run
|
||||
- [x] Seasonal graphics
|
||||
- [x] Co-op gameplay
|
||||
- [ ] Remastered soundtrack
|
||||
|
||||
*(tbd)*
|
||||
|
||||
|
@ -121,14 +107,6 @@ Because methods used to extract game data from cartridge vary, you have to find
|
|||
|
||||
![CS+ with enhanced graphics](https://i.imgur.com/YaPAs70.png)
|
||||
|
||||
#### Legal note
|
||||
|
||||
This project includes reverse engineered implementations of NPC and game physics algorithms, derived from freeware Cave Story and PC Cave Story+ executables.
|
||||
|
||||
Since the game's (non-existent, even for CS+) EULA does not prohibit reverse engineering,
|
||||
[according to Secion 103(f)](https://www.law.cornell.edu/uscode/text/17/1201) we could legally revese engineer those parts
|
||||
to achieve interoperability.
|
||||
|
||||
#### Credits
|
||||
|
||||
- Studio Pixel/Nicalis for Cave Story
|
||||
|
|
106
src/bullet.rs
106
src/bullet.rs
|
@ -23,7 +23,7 @@ impl BulletManager {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn create_bullet(&mut self, x: isize, y: isize, btype: u16, owner: TargetPlayer, direction: Direction, constants: &EngineConstants) {
|
||||
pub fn create_bullet(&mut self, x: i32, y: i32, btype: u16, owner: TargetPlayer, direction: Direction, constants: &EngineConstants) {
|
||||
self.bullets.push(Bullet::new(x, y, btype, owner, direction, constants));
|
||||
}
|
||||
|
||||
|
@ -56,14 +56,14 @@ impl BulletManager {
|
|||
|
||||
pub struct Bullet {
|
||||
pub btype: u16,
|
||||
pub x: isize,
|
||||
pub y: isize,
|
||||
pub vel_x: isize,
|
||||
pub vel_y: isize,
|
||||
pub target_x: isize,
|
||||
pub target_y: isize,
|
||||
pub prev_x: isize,
|
||||
pub prev_y: isize,
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
pub vel_x: i32,
|
||||
pub vel_y: i32,
|
||||
pub target_x: i32,
|
||||
pub target_y: i32,
|
||||
pub prev_x: i32,
|
||||
pub prev_y: i32,
|
||||
pub life: u16,
|
||||
pub lifetime: u16,
|
||||
pub damage: u16,
|
||||
|
@ -84,7 +84,7 @@ pub struct Bullet {
|
|||
}
|
||||
|
||||
impl Bullet {
|
||||
pub fn new(x: isize, y: isize, btype: u16, owner: TargetPlayer, direction: Direction, constants: &EngineConstants) -> Bullet {
|
||||
pub fn new(x: i32, y: i32, btype: u16, owner: TargetPlayer, direction: Direction, constants: &EngineConstants) -> Bullet {
|
||||
let bullet = constants.weapon.bullet_table
|
||||
.get(btype as usize)
|
||||
.unwrap_or_else(|| &BulletData {
|
||||
|
@ -398,7 +398,7 @@ impl Bullet {
|
|||
state.create_caret(self.x, self.y, CaretType::ProjectileDissipation, Direction::Right);
|
||||
}
|
||||
|
||||
fn judge_hit_block_destroy(&mut self, x: isize, y: isize, hit_attribs: &[u8; 4], state: &mut SharedGameState) {
|
||||
fn judge_hit_block_destroy(&mut self, x: i32, y: i32, hit_attribs: &[u8; 4], state: &mut SharedGameState) {
|
||||
let mut hits = [false; 4];
|
||||
let block_x = (x * 16 + 8) * 0x200;
|
||||
let block_y = (y * 16 + 8) * 0x200;
|
||||
|
@ -413,77 +413,77 @@ impl Bullet {
|
|||
|
||||
// left wall
|
||||
if hits[0] && hits[2] {
|
||||
if (self.x - self.hit_bounds.left as isize) < block_x {
|
||||
if (self.x - self.hit_bounds.left as i32) < block_x {
|
||||
self.flags.set_hit_left_wall(true);
|
||||
}
|
||||
} else if hits[0] && !hits[2] {
|
||||
if (self.x - self.hit_bounds.left as isize) < block_x
|
||||
&& (self.y - self.hit_bounds.top as isize) < block_y - (3 * 0x200) {
|
||||
if (self.x - self.hit_bounds.left as i32) < block_x
|
||||
&& (self.y - self.hit_bounds.top as i32) < block_y - (3 * 0x200) {
|
||||
self.flags.set_hit_left_wall(true);
|
||||
}
|
||||
} else if !hits[0] && hits[2]
|
||||
&& (self.x - self.hit_bounds.left as isize) < block_x
|
||||
&& (self.y + self.hit_bounds.top as isize) > block_y + (3 * 0x200) {
|
||||
&& (self.x - self.hit_bounds.left as i32) < block_x
|
||||
&& (self.y + self.hit_bounds.top as i32) > block_y + (3 * 0x200) {
|
||||
self.flags.set_hit_left_wall(true);
|
||||
}
|
||||
|
||||
// right wall
|
||||
if hits[1] && hits[3] {
|
||||
if (self.x + self.hit_bounds.right as isize) > block_x {
|
||||
if (self.x + self.hit_bounds.right as i32) > block_x {
|
||||
self.flags.set_hit_right_wall(true);
|
||||
}
|
||||
} else if hits[1] && !hits[3] {
|
||||
if (self.x + self.hit_bounds.right as isize) > block_x
|
||||
&& (self.y - self.hit_bounds.top as isize) < block_y - (3 * 0x200) {
|
||||
if (self.x + self.hit_bounds.right as i32) > block_x
|
||||
&& (self.y - self.hit_bounds.top as i32) < block_y - (3 * 0x200) {
|
||||
self.flags.set_hit_right_wall(true);
|
||||
}
|
||||
} else if !hits[1] && hits[3]
|
||||
&& (self.x + self.hit_bounds.right as isize) > block_x
|
||||
&& (self.y + self.hit_bounds.top as isize) > block_y + (3 * 0x200) {
|
||||
&& (self.x + self.hit_bounds.right as i32) > block_x
|
||||
&& (self.y + self.hit_bounds.top as i32) > block_y + (3 * 0x200) {
|
||||
self.flags.set_hit_right_wall(true);
|
||||
}
|
||||
|
||||
// ceiling
|
||||
if hits[0] && hits[1] {
|
||||
if (self.y - self.hit_bounds.top as isize) < block_y {
|
||||
if (self.y - self.hit_bounds.top as i32) < block_y {
|
||||
self.flags.set_hit_top_wall(true);
|
||||
}
|
||||
} else if hits[0] && !hits[1] {
|
||||
if (self.x - self.hit_bounds.left as isize) < block_x - (3 * 0x200)
|
||||
&& (self.y - self.hit_bounds.top as isize) < block_y {
|
||||
if (self.x - self.hit_bounds.left as i32) < block_x - (3 * 0x200)
|
||||
&& (self.y - self.hit_bounds.top as i32) < block_y {
|
||||
self.flags.set_hit_top_wall(true);
|
||||
}
|
||||
} else if !hits[0] && hits[1]
|
||||
&& (self.x + self.hit_bounds.right as isize) > block_x + (3 * 0x200)
|
||||
&& (self.y - self.hit_bounds.top as isize) < block_y {
|
||||
&& (self.x + self.hit_bounds.right as i32) > block_x + (3 * 0x200)
|
||||
&& (self.y - self.hit_bounds.top as i32) < block_y {
|
||||
self.flags.set_hit_top_wall(true);
|
||||
}
|
||||
|
||||
// ground
|
||||
if hits[2] && hits[3] {
|
||||
if (self.y + self.hit_bounds.bottom as isize) > block_y {
|
||||
if (self.y + self.hit_bounds.bottom as i32) > block_y {
|
||||
self.flags.set_hit_bottom_wall(true);
|
||||
}
|
||||
} else if hits[2] && !hits[3] {
|
||||
if (self.x - self.hit_bounds.left as isize) < block_x - (3 * 0x200)
|
||||
&& (self.y + self.hit_bounds.bottom as isize) > block_y {
|
||||
if (self.x - self.hit_bounds.left as i32) < block_x - (3 * 0x200)
|
||||
&& (self.y + self.hit_bounds.bottom as i32) > block_y {
|
||||
self.flags.set_hit_bottom_wall(true);
|
||||
}
|
||||
} else if !hits[2] && hits[3]
|
||||
&& (self.x + self.hit_bounds.right as isize) > block_x + (3 * 0x200)
|
||||
&& (self.y + self.hit_bounds.bottom as isize) > block_y {
|
||||
&& (self.x + self.hit_bounds.right as i32) > block_x + (3 * 0x200)
|
||||
&& (self.y + self.hit_bounds.bottom as i32) > block_y {
|
||||
self.flags.set_hit_bottom_wall(true);
|
||||
}
|
||||
|
||||
if self.weapon_flags.flag_x08() {
|
||||
if self.flags.hit_left_wall() {
|
||||
self.x = block_x + self.hit_bounds.right as isize;
|
||||
self.x = block_x + self.hit_bounds.right as i32;
|
||||
} else if self.flags.hit_right_wall() {
|
||||
self.x = block_x - self.hit_bounds.left as isize;
|
||||
self.x = block_x - self.hit_bounds.left as i32;
|
||||
} else if self.flags.hit_top_wall() {
|
||||
self.y = block_y + self.hit_bounds.bottom as isize;
|
||||
self.y = block_y + self.hit_bounds.bottom as i32;
|
||||
} else if self.flags.hit_bottom_wall() {
|
||||
self.y = block_y - self.hit_bounds.top as isize;
|
||||
self.y = block_y - self.hit_bounds.top as i32;
|
||||
}
|
||||
} else if self.flags.hit_left_wall() || self.flags.hit_top_wall()
|
||||
|| self.flags.hit_right_wall() || self.flags.hit_bottom_wall() {
|
||||
|
@ -494,22 +494,22 @@ impl Bullet {
|
|||
|
||||
impl PhysicalEntity for Bullet {
|
||||
#[inline(always)]
|
||||
fn x(&self) -> isize {
|
||||
fn x(&self) -> i32 {
|
||||
self.x
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn y(&self) -> isize {
|
||||
fn y(&self) -> i32 {
|
||||
self.y
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn vel_x(&self) -> isize {
|
||||
fn vel_x(&self) -> i32 {
|
||||
self.vel_x
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn vel_y(&self) -> isize {
|
||||
fn vel_y(&self) -> i32 {
|
||||
self.vel_y
|
||||
}
|
||||
|
||||
|
@ -523,22 +523,22 @@ impl PhysicalEntity for Bullet {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn set_x(&mut self, x: isize) {
|
||||
fn set_x(&mut self, x: i32) {
|
||||
self.x = x;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn set_y(&mut self, y: isize) {
|
||||
fn set_y(&mut self, y: i32) {
|
||||
self.y = y;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn set_vel_x(&mut self, vel_x: isize) {
|
||||
fn set_vel_x(&mut self, vel_x: i32) {
|
||||
self.vel_x = vel_x;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn set_vel_y(&mut self, vel_y: isize) {
|
||||
fn set_vel_y(&mut self, vel_y: i32) {
|
||||
self.vel_y = vel_y;
|
||||
}
|
||||
|
||||
|
@ -562,11 +562,11 @@ impl PhysicalEntity for Bullet {
|
|||
false
|
||||
}
|
||||
|
||||
fn judge_hit_block(&mut self, _state: &mut SharedGameState, x: isize, y: isize) {
|
||||
if (self.x - self.hit_bounds.left as isize) < (x * 16 + 8) * 0x200
|
||||
&& (self.x + self.hit_bounds.right as isize) > (x * 16 - 8) * 0x200
|
||||
&& (self.y - self.hit_bounds.top as isize) < (y * 16 + 8) * 0x200
|
||||
&& (self.y + self.hit_bounds.bottom as isize) > (y * 16 - 8) * 0x200
|
||||
fn judge_hit_block(&mut self, _state: &mut SharedGameState, x: i32, y: i32) {
|
||||
if (self.x - self.hit_bounds.left as i32) < (x * 16 + 8) * 0x200
|
||||
&& (self.x + self.hit_bounds.right as i32) > (x * 16 - 8) * 0x200
|
||||
&& (self.y - self.hit_bounds.top as i32) < (y * 16 + 8) * 0x200
|
||||
&& (self.y + self.hit_bounds.bottom as i32) > (y * 16 - 8) * 0x200
|
||||
{
|
||||
self.flags.set_weapon_hit_block(true);
|
||||
}
|
||||
|
@ -578,8 +578,8 @@ impl PhysicalEntity for Bullet {
|
|||
return;
|
||||
}
|
||||
|
||||
let x = clamp(self.x() / 16 / 0x200, 0, stage.map.width as isize);
|
||||
let y = clamp(self.y() / 16 / 0x200, 0, stage.map.height as isize);
|
||||
let x = clamp(self.x() / 16 / 0x200, 0, stage.map.width as i32);
|
||||
let y = clamp(self.y() / 16 / 0x200, 0, stage.map.height as i32);
|
||||
let mut hit_attribs = [0u8; 4];
|
||||
|
||||
for (idx, (&ox, &oy)) in OFF_X.iter().zip(OFF_Y.iter()).enumerate() {
|
||||
|
@ -615,13 +615,13 @@ impl PhysicalEntity for Bullet {
|
|||
npc.y = (y * 16 + 8) * 0x200;
|
||||
|
||||
for _ in 0..4 {
|
||||
npc.vel_x = state.game_rng.range(-0x200..0x200) as isize;
|
||||
npc.vel_y = state.game_rng.range(-0x200..0x200) as isize;
|
||||
npc.vel_x = state.game_rng.range(-0x200..0x200) as i32;
|
||||
npc.vel_y = state.game_rng.range(-0x200..0x200) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
}
|
||||
|
||||
if let Some(tile) = stage.map.tiles.get_mut(stage.map.width * (y + oy) as usize + (x + ox) as usize) {
|
||||
if let Some(tile) = stage.map.tiles.get_mut(stage.map.width as usize * (y + oy) as usize + (x + ox) as usize) {
|
||||
*tile = tile.wrapping_sub(1);
|
||||
}
|
||||
}
|
||||
|
|
28
src/caret.rs
28
src/caret.rs
|
@ -26,14 +26,14 @@ pub enum CaretType {
|
|||
|
||||
pub struct Caret {
|
||||
pub ctype: CaretType,
|
||||
pub x: isize,
|
||||
pub y: isize,
|
||||
pub vel_x: isize,
|
||||
pub vel_y: isize,
|
||||
pub offset_x: isize,
|
||||
pub offset_y: isize,
|
||||
pub prev_x: isize,
|
||||
pub prev_y: isize,
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
pub vel_x: i32,
|
||||
pub vel_y: i32,
|
||||
pub offset_x: i32,
|
||||
pub offset_y: i32,
|
||||
pub prev_x: i32,
|
||||
pub prev_y: i32,
|
||||
pub cond: Condition,
|
||||
pub direction: Direction,
|
||||
pub anim_rect: Rect<u16>,
|
||||
|
@ -43,7 +43,7 @@ pub struct Caret {
|
|||
}
|
||||
|
||||
impl Caret {
|
||||
pub fn new(x: isize, y: isize, ctype: CaretType, direct: Direction, constants: &EngineConstants) -> Caret {
|
||||
pub fn new(x: i32, y: i32, ctype: CaretType, direct: Direction, constants: &EngineConstants) -> Caret {
|
||||
let (offset_x, offset_y) = constants.caret.offsets[ctype as usize];
|
||||
|
||||
Caret {
|
||||
|
@ -236,8 +236,8 @@ impl Caret {
|
|||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
let angle = rng.range(0..255) as f64 * CDEG_RAD;
|
||||
self.vel_x = (angle.cos() * 1024.0) as isize;
|
||||
self.vel_y = (angle.sin() * 1024.0) as isize;
|
||||
self.vel_x = (angle.cos() * 1024.0) as i32;
|
||||
self.vel_y = (angle.sin() * 1024.0) as i32;
|
||||
}
|
||||
|
||||
self.x += self.vel_x;
|
||||
|
@ -276,11 +276,11 @@ impl Caret {
|
|||
if self.anim_num == 0 {
|
||||
match self.direction {
|
||||
Direction::Left => {
|
||||
self.vel_x = rng.range(-0x600..0x600) as isize; // -3.0fix9..3.0fix9
|
||||
self.vel_y = rng.range(-0x200..0x200) as isize; // -1.0fix9..1.0fix9
|
||||
self.vel_x = rng.range(-0x600..0x600) as i32; // -3.0fix9..3.0fix9
|
||||
self.vel_y = rng.range(-0x200..0x200) as i32; // -1.0fix9..1.0fix9
|
||||
}
|
||||
Direction::Up => {
|
||||
self.vel_y = rng.range(-3..-1) as isize * 0x200;
|
||||
self.vel_y = rng.range(-3..-1) as i32 * 0x200;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
@ -213,7 +213,7 @@ impl Direction {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn vector_x(&self) -> isize {
|
||||
pub fn vector_x(&self) -> i32 {
|
||||
match self {
|
||||
Direction::Left => { -1 }
|
||||
Direction::Up => { 0 }
|
||||
|
@ -223,7 +223,7 @@ impl Direction {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn vector_y(&self) -> isize {
|
||||
pub fn vector_y(&self) -> i32 {
|
||||
match self {
|
||||
Direction::Left => { 0 }
|
||||
Direction::Up => { -1 }
|
||||
|
@ -350,11 +350,12 @@ macro_rules! rect_deserialze {
|
|||
|
||||
rect_deserialze!(u8);
|
||||
rect_deserialze!(u16);
|
||||
rect_deserialze!(i32);
|
||||
rect_deserialze!(isize);
|
||||
rect_deserialze!(usize);
|
||||
|
||||
#[inline(always)]
|
||||
pub fn fix9_scale(val: isize, scale: f32) -> f32 {
|
||||
pub fn fix9_scale(val: i32, scale: f32) -> f32 {
|
||||
(val as f64 * scale as f64 / 512.0).floor() as f32 / scale
|
||||
}
|
||||
|
||||
|
@ -363,11 +364,10 @@ fn lerp_f64(v1: f64, v2: f64, t: f64) -> f64 {
|
|||
v1 * (1.0 - t.fract()) + v2 * t.fract()
|
||||
}
|
||||
|
||||
pub fn interpolate_fix9_scale(old_val: isize, val: isize, frame_delta: f64) -> f32 {
|
||||
pub fn interpolate_fix9_scale(old_val: i32, val: i32, frame_delta: f64) -> f32 {
|
||||
if (frame_delta - 1.0).abs() < 0.001 {
|
||||
return (val / 0x200) as f32;
|
||||
}
|
||||
|
||||
(lerp_f64(old_val as f64, val as f64, frame_delta) / 512.0) as f32
|
||||
//((lerp_f64(old_val as f64, val as f64, frame_delta) * scale as f64 / 512.0).floor() / (scale as f64)) as f32
|
||||
}
|
||||
|
|
|
@ -12,24 +12,24 @@ mod npcs;
|
|||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct PhysicsConsts {
|
||||
pub max_dash: isize,
|
||||
pub max_move: isize,
|
||||
pub gravity_ground: isize,
|
||||
pub gravity_air: isize,
|
||||
pub dash_ground: isize,
|
||||
pub dash_air: isize,
|
||||
pub resist: isize,
|
||||
pub jump: isize,
|
||||
pub max_dash: i32,
|
||||
pub max_move: i32,
|
||||
pub gravity_ground: i32,
|
||||
pub gravity_air: i32,
|
||||
pub dash_ground: i32,
|
||||
pub dash_air: i32,
|
||||
pub resist: i32,
|
||||
pub jump: i32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct BoosterConsts {
|
||||
pub fuel: usize,
|
||||
pub b2_0_up: isize,
|
||||
pub b2_0_up_nokey: isize,
|
||||
pub b2_0_down: isize,
|
||||
pub b2_0_left: isize,
|
||||
pub b2_0_right: isize,
|
||||
pub fuel: u32,
|
||||
pub b2_0_up: i32,
|
||||
pub b2_0_up_nokey: i32,
|
||||
pub b2_0_down: i32,
|
||||
pub b2_0_left: i32,
|
||||
pub b2_0_right: i32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
|
@ -47,7 +47,7 @@ pub struct MyCharConsts {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct CaretConsts {
|
||||
pub offsets: [(isize, isize); 18],
|
||||
pub offsets: [(i32, i32); 18],
|
||||
pub bubble_left_rects: Vec<Rect<u16>>,
|
||||
pub bubble_right_rects: Vec<Rect<u16>>,
|
||||
pub projectile_dissipation_left_rects: Vec<Rect<u16>>,
|
||||
|
@ -707,7 +707,7 @@ impl EngineConstants {
|
|||
"Title" => (320, 48),
|
||||
},
|
||||
textscript: TextScriptConsts {
|
||||
encoding: TextScriptEncoding::UTF8,
|
||||
encoding: TextScriptEncoding::ShiftJIS,
|
||||
encrypted: true,
|
||||
animated_face_pics: false,
|
||||
textbox_rect_top: Rect { left: 0, top: 0, right: 244, bottom: 8 },
|
||||
|
|
50
src/frame.rs
50
src/frame.rs
|
@ -12,14 +12,14 @@ pub enum UpdateTarget {
|
|||
}
|
||||
|
||||
pub struct Frame {
|
||||
pub x: isize,
|
||||
pub y: isize,
|
||||
pub prev_x: isize,
|
||||
pub prev_y: isize,
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
pub prev_x: i32,
|
||||
pub prev_y: i32,
|
||||
pub update_target: UpdateTarget,
|
||||
pub target_x: isize,
|
||||
pub target_y: isize,
|
||||
pub wait: isize,
|
||||
pub target_x: i32,
|
||||
pub target_y: i32,
|
||||
pub wait: i32,
|
||||
}
|
||||
|
||||
impl Frame {
|
||||
|
@ -35,31 +35,31 @@ impl Frame {
|
|||
}
|
||||
|
||||
pub fn immediate_update(&mut self, state: &mut SharedGameState, stage: &Stage) {
|
||||
if (stage.map.width - 1) * 16 < state.canvas_size.0 as usize {
|
||||
self.x = -(((state.canvas_size.0 as isize - ((stage.map.width - 1) * 16) as isize) * 0x200) / 2);
|
||||
if (stage.map.width as usize).saturating_sub(1) * 16 < state.canvas_size.0 as usize {
|
||||
self.x = -(((state.canvas_size.0 as i32 - ((stage.map.width - 1) * 16) as i32) * 0x200) / 2);
|
||||
} else {
|
||||
self.x = self.target_x - (state.canvas_size.0 as isize * 0x200 / 2);
|
||||
self.x = self.target_x - (state.canvas_size.0 as i32 * 0x200 / 2);
|
||||
|
||||
if self.x < 0 {
|
||||
self.x = 0;
|
||||
}
|
||||
|
||||
let max_x = (((stage.map.width as isize - 1) * 16) - state.canvas_size.0 as isize) * 0x200;
|
||||
let max_x = (((stage.map.width as i32 - 1) * 16) - state.canvas_size.0 as i32) * 0x200;
|
||||
if self.x > max_x {
|
||||
self.x = max_x;
|
||||
}
|
||||
}
|
||||
|
||||
if (stage.map.height - 1) * 16 < state.canvas_size.1 as usize {
|
||||
self.y = -(((state.canvas_size.1 as isize - ((stage.map.height - 1) * 16) as isize) * 0x200) / 2);
|
||||
if (stage.map.height as usize).saturating_sub(1) * 16 < state.canvas_size.1 as usize {
|
||||
self.y = -(((state.canvas_size.1 as i32 - ((stage.map.height - 1) * 16) as i32) * 0x200) / 2);
|
||||
} else {
|
||||
self.y = self.target_y - (state.canvas_size.1 as isize * 0x200 / 2);
|
||||
self.y = self.target_y - (state.canvas_size.1 as i32 * 0x200 / 2);
|
||||
|
||||
if self.y < 0 {
|
||||
self.y = 0;
|
||||
}
|
||||
|
||||
let max_y = (((stage.map.height as isize - 1) * 16) - state.canvas_size.1 as isize) * 0x200;
|
||||
let max_y = (((stage.map.height as i32 - 1) * 16) - state.canvas_size.1 as i32) * 0x200;
|
||||
if self.y > max_y {
|
||||
self.y = max_y;
|
||||
}
|
||||
|
@ -70,31 +70,31 @@ impl Frame {
|
|||
}
|
||||
|
||||
pub fn update(&mut self, state: &mut SharedGameState, stage: &Stage) {
|
||||
if (stage.map.width - 1) * 16 < state.canvas_size.0 as usize {
|
||||
self.x = -(((state.canvas_size.0 as isize - ((stage.map.width - 1) * 16) as isize) * 0x200) / 2);
|
||||
if (stage.map.width as usize).saturating_sub(1) * 16 < state.canvas_size.0 as usize {
|
||||
self.x = -(((state.canvas_size.0 as i32 - ((stage.map.width - 1) * 16) as i32) * 0x200) / 2);
|
||||
} else {
|
||||
self.x += (self.target_x - (state.canvas_size.0 as isize * 0x200 / 2) - self.x) / self.wait;
|
||||
self.x += (self.target_x - (state.canvas_size.0 as i32 * 0x200 / 2) - self.x) / self.wait;
|
||||
|
||||
if self.x < 0 {
|
||||
self.x = 0;
|
||||
}
|
||||
|
||||
let max_x = (((stage.map.width as isize - 1) * 16) - state.canvas_size.0 as isize) * 0x200;
|
||||
let max_x = (((stage.map.width as i32 - 1) * 16) - state.canvas_size.0 as i32) * 0x200;
|
||||
if self.x > max_x {
|
||||
self.x = max_x;
|
||||
}
|
||||
}
|
||||
|
||||
if (stage.map.height - 1) * 16 < state.canvas_size.1 as usize {
|
||||
self.y = -(((state.canvas_size.1 as isize - ((stage.map.height - 1) * 16) as isize) * 0x200) / 2);
|
||||
if (stage.map.height as usize).saturating_sub(1) * 16 < state.canvas_size.1 as usize {
|
||||
self.y = -(((state.canvas_size.1 as i32 - ((stage.map.height - 1) * 16) as i32) * 0x200) / 2);
|
||||
} else {
|
||||
self.y += (self.target_y - (state.canvas_size.1 as isize * 0x200 / 2) - self.y) / self.wait;
|
||||
self.y += (self.target_y - (state.canvas_size.1 as i32 * 0x200 / 2) - self.y) / self.wait;
|
||||
|
||||
if self.y < 0 {
|
||||
self.y = 0;
|
||||
}
|
||||
|
||||
let max_y = (((stage.map.height as isize - 1) * 16) - state.canvas_size.1 as isize) * 0x200;
|
||||
let max_y = (((stage.map.height as i32 - 1) * 16) - state.canvas_size.1 as i32) * 0x200;
|
||||
if self.y > max_y {
|
||||
self.y = max_y;
|
||||
}
|
||||
|
@ -103,8 +103,8 @@ impl Frame {
|
|||
if state.quake_counter > 0 {
|
||||
state.quake_counter -= 1;
|
||||
|
||||
self.x += state.effect_rng.range(-0x300..0x300) as isize;
|
||||
self.y += state.effect_rng.range(-0x300..0x300) as isize;
|
||||
self.x += state.effect_rng.range(-0x300..0x300) as i32;
|
||||
self.y += state.effect_rng.range(-0x300..0x300) as i32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
89
src/lib.rs
89
src/lib.rs
|
@ -1,10 +1,14 @@
|
|||
#[macro_use]
|
||||
extern crate log;
|
||||
#[cfg_attr(feature = "scripting", macro_use)]
|
||||
#[cfg(feature = "scripting")]
|
||||
extern crate lua_ffi;
|
||||
extern crate strum;
|
||||
#[macro_use]
|
||||
extern crate strum_macros;
|
||||
|
||||
use std::{env, mem};
|
||||
use std::cell::UnsafeCell;
|
||||
use std::path;
|
||||
use std::time::Instant;
|
||||
|
||||
|
@ -53,6 +57,8 @@ mod player;
|
|||
mod profile;
|
||||
mod rng;
|
||||
mod scene;
|
||||
#[cfg(feature = "scripting")]
|
||||
mod scripting;
|
||||
mod settings;
|
||||
mod shaders;
|
||||
mod shared_game_state;
|
||||
|
@ -65,7 +71,7 @@ mod weapon;
|
|||
|
||||
struct Game {
|
||||
scene: Option<Box<dyn Scene>>,
|
||||
state: SharedGameState,
|
||||
state: UnsafeCell<SharedGameState>,
|
||||
ui: UI,
|
||||
def_matrix: ColumnMatrix4<f32>,
|
||||
start_time: Instant,
|
||||
|
@ -80,7 +86,7 @@ impl Game {
|
|||
scene: None,
|
||||
ui: UI::new(ctx)?,
|
||||
def_matrix: DrawParam::new().to_matrix(),
|
||||
state: SharedGameState::new(ctx)?,
|
||||
state: UnsafeCell::new(SharedGameState::new(ctx)?),
|
||||
start_time: Instant::now(),
|
||||
last_tick: 0,
|
||||
next_tick: 0,
|
||||
|
@ -92,15 +98,17 @@ impl Game {
|
|||
|
||||
fn update(&mut self, ctx: &mut Context) -> GameResult {
|
||||
if let Some(scene) = self.scene.as_mut() {
|
||||
match self.state.timing_mode {
|
||||
let state_ref = unsafe { &mut *self.state.get() };
|
||||
|
||||
match state_ref.timing_mode {
|
||||
TimingMode::_50Hz | TimingMode::_60Hz => {
|
||||
let last_tick = self.next_tick;
|
||||
|
||||
while self.start_time.elapsed().as_nanos() >= self.next_tick && self.loops < 10 {
|
||||
if (self.state.settings.speed - 1.0).abs() < 0.01 {
|
||||
self.next_tick += self.state.timing_mode.get_delta() as u128;
|
||||
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 += (self.state.timing_mode.get_delta() as f64 / self.state.settings.speed) as u128;
|
||||
self.next_tick += (state_ref.timing_mode.get_delta() as f64 / state_ref.settings.speed) as u128;
|
||||
}
|
||||
self.loops += 1;
|
||||
}
|
||||
|
@ -108,21 +116,21 @@ 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 + (self.state.timing_mode.get_delta() as f64 / self.state.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;
|
||||
}
|
||||
|
||||
if self.loops != 0 {
|
||||
scene.draw_tick(&mut self.state)?;
|
||||
scene.draw_tick(state_ref)?;
|
||||
self.last_tick = last_tick;
|
||||
}
|
||||
|
||||
for _ in 0..self.loops {
|
||||
scene.tick(&mut self.state, ctx)?;
|
||||
scene.tick(state_ref, ctx)?;
|
||||
}
|
||||
}
|
||||
TimingMode::FrameSynchronized => {
|
||||
scene.tick(&mut self.state, ctx)?;
|
||||
scene.tick(state_ref, ctx)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -130,28 +138,30 @@ impl Game {
|
|||
}
|
||||
|
||||
fn draw(&mut self, ctx: &mut Context) -> GameResult {
|
||||
if self.state.timing_mode != TimingMode::FrameSynchronized {
|
||||
let state_ref = unsafe { &mut *self.state.get() };
|
||||
|
||||
if state_ref.timing_mode != TimingMode::FrameSynchronized {
|
||||
let n1 = (self.start_time.elapsed().as_nanos() - self.last_tick) as f64;
|
||||
let n2 = (self.next_tick - self.last_tick) as f64;
|
||||
self.state.frame_time = n1 / n2;
|
||||
state_ref.frame_time = n1 / n2;
|
||||
}
|
||||
self.loops = 0;
|
||||
|
||||
graphics::clear(ctx, [0.0, 0.0, 0.0, 1.0].into());
|
||||
graphics::set_transform(ctx, DrawParam::new()
|
||||
.scale(Vector2::new(self.state.scale, self.state.scale))
|
||||
.scale(Vector2::new(state_ref.scale, state_ref.scale))
|
||||
.to_matrix());
|
||||
graphics::apply_transformations(ctx)?;
|
||||
|
||||
if let Some(scene) = self.scene.as_mut() {
|
||||
scene.draw(&mut self.state, ctx)?;
|
||||
if self.state.settings.touch_controls {
|
||||
self.state.touch_controls.draw(self.state.canvas_size, &self.state.constants, &mut self.state.texture_set, ctx)?;
|
||||
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)?;
|
||||
}
|
||||
|
||||
graphics::set_transform(ctx, self.def_matrix);
|
||||
graphics::apply_transformations(ctx)?;
|
||||
self.ui.draw(&mut self.state, ctx, scene)?;
|
||||
self.ui.draw(state_ref, ctx, scene)?;
|
||||
}
|
||||
|
||||
graphics::present(ctx)?;
|
||||
|
@ -161,7 +171,7 @@ impl Game {
|
|||
fn key_down_event(&mut self, key_code: KeyCode, _key_mod: KeyMods, repeat: bool) {
|
||||
if repeat { return; }
|
||||
|
||||
let state = &mut self.state;
|
||||
let state = unsafe { &mut *self.state.get() };
|
||||
match key_code {
|
||||
KeyCode::F7 => { state.set_speed(1.0) }
|
||||
KeyCode::F8 => {
|
||||
|
@ -328,8 +338,19 @@ pub fn init() -> GameResult {
|
|||
game.ui.handle_events(ctx, &event);
|
||||
} else {
|
||||
let mut new_game = Game::new(ctx).unwrap();
|
||||
new_game.state.next_scene = Some(Box::new(LoadingScene::new()));
|
||||
let state_ref = unsafe { &mut *new_game.state.get() };
|
||||
state_ref.next_scene = Some(Box::new(LoadingScene::new()));
|
||||
game = Some(new_game);
|
||||
|
||||
#[cfg(feature = "scripting")]
|
||||
{
|
||||
unsafe {
|
||||
let game_ref = game.as_mut().unwrap();
|
||||
let state_ref = game_ref.state.get();
|
||||
|
||||
(&mut *state_ref).lua.update_refs(game_ref.state.get(), ctx as *mut Context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -358,22 +379,26 @@ pub fn init() -> GameResult {
|
|||
match event {
|
||||
WindowEvent::CloseRequested => {
|
||||
if let Some(game) = &mut game {
|
||||
game.state.shutdown();
|
||||
let state_ref = unsafe { &mut *game.state.get() };
|
||||
state_ref.shutdown();
|
||||
}
|
||||
*flow = ControlFlow::Exit;
|
||||
}
|
||||
WindowEvent::Resized(_) => {
|
||||
if let (Some(ctx), Some(game)) = (&mut context, &mut game) {
|
||||
game.state.tmp_canvas = Canvas::with_window_size(ctx).unwrap();
|
||||
game.state.game_canvas = Canvas::with_window_size(ctx).unwrap();
|
||||
game.state.lightmap_canvas = Canvas::with_window_size(ctx).unwrap();
|
||||
game.state.handle_resize(ctx).unwrap();
|
||||
let state_ref = unsafe { &mut *game.state.get() };
|
||||
|
||||
state_ref.tmp_canvas = Canvas::with_window_size(ctx).unwrap();
|
||||
state_ref.game_canvas = Canvas::with_window_size(ctx).unwrap();
|
||||
state_ref.lightmap_canvas = Canvas::with_window_size(ctx).unwrap();
|
||||
state_ref.handle_resize(ctx).unwrap();
|
||||
graphics::window(ctx).update_gfx(&mut game.ui.main_color, &mut game.ui.main_depth);
|
||||
}
|
||||
}
|
||||
WindowEvent::Touch(touch) => {
|
||||
if let Some(game) = &mut game {
|
||||
game.state.touch_controls.process_winit_event(game.state.scale, touch);
|
||||
let state_ref = unsafe { &mut *game.state.get() };
|
||||
state_ref.touch_controls.process_winit_event(state_ref.scale, touch);
|
||||
}
|
||||
}
|
||||
WindowEvent::KeyboardInput {
|
||||
|
@ -420,19 +445,21 @@ pub fn init() -> GameResult {
|
|||
}
|
||||
window(ctx).window().request_redraw();
|
||||
|
||||
if game.state.shutdown {
|
||||
let state_ref = unsafe { &mut *game.state.get() };
|
||||
|
||||
if state_ref.shutdown {
|
||||
log::info!("Shutting down...");
|
||||
*flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
|
||||
if game.state.next_scene.is_some() {
|
||||
mem::swap(&mut game.scene, &mut game.state.next_scene);
|
||||
game.state.next_scene = None;
|
||||
if state_ref.next_scene.is_some() {
|
||||
mem::swap(&mut game.scene, &mut state_ref.next_scene);
|
||||
state_ref.next_scene = None;
|
||||
|
||||
game.scene.as_mut().unwrap().init(&mut game.state, ctx).unwrap();
|
||||
game.scene.as_mut().unwrap().init(state_ref, ctx).unwrap();
|
||||
game.loops = 0;
|
||||
game.state.frame_time = 0.0;
|
||||
state_ref.frame_time = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ use itertools::Itertools;
|
|||
|
||||
use crate::scene::game_scene::GameScene;
|
||||
use crate::shared_game_state::SharedGameState;
|
||||
use crate::text_script::TextScriptExecutionState;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||
#[repr(u8)]
|
||||
|
@ -95,7 +96,7 @@ impl LiveDebugger {
|
|||
state.set_speed(speed);
|
||||
}
|
||||
|
||||
if ui.button(im_str!("Map Selector"), [0.0, 0.0]) {
|
||||
if ui.button(im_str!("Maps"), [0.0, 0.0]) {
|
||||
self.map_selector_visible = !self.map_selector_visible;
|
||||
}
|
||||
|
||||
|
@ -104,16 +105,22 @@ impl LiveDebugger {
|
|||
self.events_visible = !self.events_visible;
|
||||
}
|
||||
|
||||
ui.same_line(0.0);
|
||||
if ui.button(im_str!("Hacks"), [0.0, 0.0]) {
|
||||
self.hacks_visible = !self.hacks_visible;
|
||||
}
|
||||
|
||||
ui.same_line(0.0);
|
||||
if ui.button(im_str!("Flags"), [0.0, 0.0]) {
|
||||
self.flags_visible = !self.flags_visible;
|
||||
}
|
||||
|
||||
#[cfg(feature = "scripting")]
|
||||
{
|
||||
ui.same_line(0.0);
|
||||
if ui.button(im_str!("Reload Scripts"), [0.0, 0.0]) {
|
||||
if let Err(err) = state.lua.reload_scripts(ctx) {
|
||||
log::error!("Error reloading scripts: {:?}", err);
|
||||
self.error = Some(ImString::new(err.to_string()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui.same_line(0.0);
|
||||
if game_scene.player2.cond.alive() {
|
||||
if ui.button(im_str!("Drop Player 2"), [0.0, 0.0]) {
|
||||
|
@ -152,21 +159,23 @@ impl LiveDebugger {
|
|||
scene.inventory_player2 = game_scene.inventory_player2.clone();
|
||||
|
||||
scene.player1 = game_scene.player1.clone();
|
||||
scene.player1.x = (scene.stage.map.width / 2 * 16 * 0x200) as isize;
|
||||
scene.player1.y = (scene.stage.map.height / 2 * 16 * 0x200) as isize;
|
||||
scene.player1.x = scene.stage.map.width as i32 / 2 * 16 * 0x200;
|
||||
scene.player1.y = scene.stage.map.height as i32 / 2 * 16 * 0x200;
|
||||
|
||||
if scene.player1.life == 0 {
|
||||
scene.player1.life = scene.player1.max_life;
|
||||
}
|
||||
|
||||
scene.player2 = game_scene.player2.clone();
|
||||
scene.player2.x = (scene.stage.map.width / 2 * 16 * 0x200) as isize;
|
||||
scene.player2.y = (scene.stage.map.height / 2 * 16 * 0x200) as isize;
|
||||
scene.player2.x = scene.stage.map.width as i32 / 2 * 16 * 0x200;
|
||||
scene.player2.y = scene.stage.map.height as i32 / 2 * 16 * 0x200;
|
||||
|
||||
if scene.player2.life == 0 {
|
||||
scene.player2.life = scene.player1.max_life;
|
||||
}
|
||||
|
||||
state.textscript_vm.suspend = true;
|
||||
state.textscript_vm.state = TextScriptExecutionState::Running(94, 0);
|
||||
state.next_scene = Some(Box::new(scene));
|
||||
}
|
||||
Err(e) => {
|
||||
|
|
14
src/map.rs
14
src/map.rs
|
@ -10,8 +10,8 @@ static SUPPORTED_PXM_VERSIONS: [u8; 1] = [0x10];
|
|||
static SUPPORTED_PXE_VERSIONS: [u8; 2] = [0, 0x10];
|
||||
|
||||
pub struct Map {
|
||||
pub width: usize,
|
||||
pub height: usize,
|
||||
pub width: u16,
|
||||
pub height: u16,
|
||||
pub tiles: Vec<u8>,
|
||||
pub attrib: [u8; 0x100],
|
||||
}
|
||||
|
@ -33,9 +33,9 @@ impl Map {
|
|||
return Err(ResourceLoadError(format!("Unsupported PXM version: {:#x}", version)));
|
||||
}
|
||||
|
||||
let width = map_data.read_u16::<LE>()? as usize;
|
||||
let height = map_data.read_u16::<LE>()? as usize;
|
||||
let mut tiles = vec![0u8; width * height];
|
||||
let width = map_data.read_u16::<LE>()?;
|
||||
let height = map_data.read_u16::<LE>()?;
|
||||
let mut tiles = vec![0u8; (width * height) as usize];
|
||||
let mut attrib = [0u8; 0x100];
|
||||
|
||||
log::info!("Map size: {}x{}", width, height);
|
||||
|
@ -54,11 +54,11 @@ impl Map {
|
|||
}
|
||||
|
||||
pub fn get_attribute(&self, x: usize, y: usize) -> u8 {
|
||||
if x >= self.width || y >= self.height {
|
||||
if x >= self.width as usize || y >= self.height as usize {
|
||||
return 0;
|
||||
}
|
||||
|
||||
self.attrib[*self.tiles.get(self.width * y + x).unwrap_or_else(|| &0u8) as usize]
|
||||
self.attrib[*self.tiles.get(self.width as usize * y + x).unwrap_or_else(|| &0u8) as usize]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,15 +4,31 @@ use crate::common::Rect;
|
|||
use crate::input::combined_menu_controller::CombinedMenuController;
|
||||
use crate::shared_game_state::SharedGameState;
|
||||
|
||||
pub struct MenuSaveInfo {
|
||||
|
||||
}
|
||||
|
||||
pub enum MenuEntry {
|
||||
Hidden,
|
||||
Active(String),
|
||||
Disabled(String),
|
||||
Toggle(String, bool),
|
||||
Options(String, usize, Vec<String>),
|
||||
SaveData(MenuSaveInfo),
|
||||
NewSave,
|
||||
}
|
||||
|
||||
impl MenuEntry {
|
||||
pub fn height(&self) -> f64 {
|
||||
14.0
|
||||
match self {
|
||||
MenuEntry::Hidden => 0.0,
|
||||
MenuEntry::Active(_) => 14.0,
|
||||
MenuEntry::Disabled(_) => 14.0,
|
||||
MenuEntry::Toggle(_, _) => 14.0,
|
||||
MenuEntry::Options(_, _, _) => 14.0,
|
||||
MenuEntry::SaveData(_) => 30.0,
|
||||
MenuEntry::NewSave => 30.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,6 +45,7 @@ pub struct Menu {
|
|||
pub height: u16,
|
||||
pub selected: usize,
|
||||
pub entries: Vec<MenuEntry>,
|
||||
entry_y: u16,
|
||||
anim_num: u16,
|
||||
anim_wait: u16,
|
||||
}
|
||||
|
@ -43,6 +60,7 @@ impl Menu {
|
|||
width,
|
||||
height,
|
||||
selected: 0,
|
||||
entry_y: 0,
|
||||
anim_num: 0,
|
||||
anim_wait: 0,
|
||||
entries: Vec::new(),
|
||||
|
@ -53,6 +71,16 @@ impl Menu {
|
|||
self.entries.push(entry);
|
||||
}
|
||||
|
||||
pub fn update_height(&mut self) {
|
||||
let mut height = 6.0;
|
||||
|
||||
for entry in self.entries.iter() {
|
||||
height += entry.height();
|
||||
}
|
||||
|
||||
self.height = height.max(6.0) as u16;
|
||||
}
|
||||
|
||||
pub fn draw(&self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
||||
let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "TextBox")?;
|
||||
|
||||
|
@ -155,7 +183,7 @@ impl Menu {
|
|||
rect.bottom = rect.top + 16;
|
||||
|
||||
batch.add_rect(self.x as f32,
|
||||
self.y as f32 + 2.0 + (self.selected as f32 * 14.0),
|
||||
self.y as f32 + 2.0 + self.entry_y as f32,
|
||||
&rect);
|
||||
|
||||
batch.draw(ctx)?;
|
||||
|
@ -177,6 +205,8 @@ impl Menu {
|
|||
|
||||
state.font.draw_text(value_text.chars(), self.x as f32 + self.width as f32 - val_text_len, y, &state.constants, &mut state.texture_set, ctx)?;
|
||||
}
|
||||
MenuEntry::Hidden => {}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
y += entry.height() as f32;
|
||||
|
@ -218,6 +248,14 @@ impl Menu {
|
|||
}
|
||||
}
|
||||
|
||||
if !self.entries.is_empty() {
|
||||
self.entry_y = self.entries[0..(self.selected)]
|
||||
.iter()
|
||||
.map(|e| e.height())
|
||||
.sum::<f64>()
|
||||
.max(0.0) as u16;
|
||||
}
|
||||
|
||||
let mut y = self.y as f32 + 6.0;
|
||||
for (idx, entry) in self.entries.iter_mut().enumerate() {
|
||||
let entry_bounds = Rect::new_size(self.x, y as isize, self.width as isize, entry.height() as isize);
|
||||
|
|
|
@ -34,10 +34,10 @@ impl NPC {
|
|||
npc.direction = Direction::Left;
|
||||
|
||||
for _ in 0..3 {
|
||||
npc.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
npc.x = self.x + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as i32;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
}
|
||||
|
@ -104,8 +104,8 @@ impl NPC {
|
|||
|
||||
let mut angle = ((self.y + 4 * 0x200 - player.y) as f64 / (self.x - player.y) as f64).atan();
|
||||
angle += self.rng.range(-16..16) as f64 * std::f64::consts::FRAC_PI_8;
|
||||
npc.vel_x = (angle.cos() * 512.0) as isize; // 1.0fix9
|
||||
npc.vel_y = (angle.sin() * 512.0) as isize;
|
||||
npc.vel_x = (angle.cos() * 512.0) as i32; // 1.0fix9
|
||||
npc.vel_y = (angle.sin() * 512.0) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc);
|
||||
|
||||
|
@ -293,10 +293,10 @@ impl NPC {
|
|||
for _ in 0..3 {
|
||||
npc.cond.set_alive(true);
|
||||
npc.direction = Direction::Left;
|
||||
npc.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
npc.x = self.x + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as i32;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
}
|
||||
|
@ -475,8 +475,8 @@ impl NPC {
|
|||
}
|
||||
}
|
||||
102 => {
|
||||
let x = clamp(self.x / (16 * 0x200), 0, stage.map.width as isize) as usize;
|
||||
let y = clamp(self.y / (16 * 0x200), 0, stage.map.height as isize) as usize;
|
||||
let x = clamp(self.x / (16 * 0x200), 0, stage.map.width as i32) as usize;
|
||||
let y = clamp(self.y / (16 * 0x200), 0, stage.map.height as i32) as usize;
|
||||
|
||||
if y <= 34 && stage.change_tile(x, y, 0) {
|
||||
state.sound_manager.play_sfx(44);
|
||||
|
@ -484,20 +484,20 @@ impl NPC {
|
|||
|
||||
let mut npc = NPC::create(4, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
npc.x = x as isize * 16 * 0x200;
|
||||
npc.y = y as isize * 16 * 0x200;
|
||||
npc.x = x as i32 * 16 * 0x200;
|
||||
npc.y = y as i32 * 16 * 0x200;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
|
||||
if x > 0 && stage.change_tile(x - 1, y, 0) {
|
||||
npc.x = (x - 1) as isize * 16 * 0x200;
|
||||
npc.x = (x - 1) as i32 * 16 * 0x200;
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
}
|
||||
|
||||
if x < stage.map.width && stage.change_tile(x + 1, y, 0) {
|
||||
npc.x = (x + 1) as isize * 16 * 0x200;
|
||||
if x < stage.map.width as usize && stage.change_tile(x + 1, y, 0) {
|
||||
npc.x = (x + 1) as i32 * 16 * 0x200;
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
let _ = npc_list.spawn(0x100, npc);
|
||||
}
|
||||
|
@ -516,10 +516,10 @@ impl NPC {
|
|||
let mut npc = NPC::create(4, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
npc.direction = Direction::Left;
|
||||
npc.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
npc.x = self.x + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as i32;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc);
|
||||
}
|
||||
|
@ -554,10 +554,10 @@ impl NPC {
|
|||
npc.direction = Direction::Left;
|
||||
|
||||
for _ in 0..16 {
|
||||
npc.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
npc.x = self.x + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as i32;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
}
|
||||
|
@ -682,8 +682,8 @@ impl NPC {
|
|||
|
||||
let mut npc = NPC::create(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.vel_x = (angle.cos() * -512.0) as i32;
|
||||
npc.vel_y = (angle.sin() * -512.0) as i32;
|
||||
npc.x = self.x;
|
||||
npc.y = self.y + 4 * 0x200;
|
||||
|
||||
|
@ -766,16 +766,16 @@ impl NPC {
|
|||
npc_proj.direction = Direction::Left;
|
||||
|
||||
for _ in 0..8 {
|
||||
npc_smoke.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc_smoke.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc_smoke.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc_smoke.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
npc_smoke.x = self.x + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc_smoke.y = self.y + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc_smoke.vel_x = self.rng.range(-0x155..0x155) as i32;
|
||||
npc_smoke.vel_y = self.rng.range(-0x600..0) as i32;
|
||||
let _ = npc_list.spawn(0x100, npc_smoke.clone());
|
||||
|
||||
npc_proj.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc_proj.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc_proj.vel_x = self.rng.range(-0x400..0x400) as isize;
|
||||
npc_proj.vel_y = self.rng.range(-0x400..0) as isize;
|
||||
npc_proj.x = self.x + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc_proj.y = self.y + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc_proj.vel_x = self.rng.range(-0x400..0x400) as i32;
|
||||
npc_proj.vel_y = self.rng.range(-0x400..0) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc_proj.clone());
|
||||
}
|
||||
|
@ -865,7 +865,7 @@ impl NPC {
|
|||
&& self.y - 12 * 0x200 < players[pi].y && self.y + 8 * 0x200 > players[pi].y { // 12.0fix9 / 8.0fix9
|
||||
self.action_num = 10;
|
||||
self.anim_num = 5;
|
||||
self.vel_y2 = pi as isize;
|
||||
self.vel_y2 = pi as i32;
|
||||
players[pi].cond.set_hidden(true);
|
||||
players[pi].damage(2, state, npc_list);
|
||||
} else {
|
||||
|
@ -894,7 +894,7 @@ impl NPC {
|
|||
&& self.y - 12 * 0x200 < players[pi].y && self.y + 8 * 0x200 > players[pi].y {
|
||||
self.action_num = 10;
|
||||
self.anim_num = 5;
|
||||
self.vel_y2 = pi as isize;
|
||||
self.vel_y2 = pi as i32;
|
||||
players[pi].cond.set_hidden(true);
|
||||
players[pi].damage(2, state, npc_list);
|
||||
}
|
||||
|
|
|
@ -628,8 +628,8 @@ impl NPC {
|
|||
npc.cond.set_alive(true);
|
||||
npc.x = self.x;
|
||||
npc.y = self.y;
|
||||
npc.vel_x = (angle.cos() * -1024.0) as isize;
|
||||
npc.vel_y = (angle.sin() * -1024.0) as isize;
|
||||
npc.vel_x = (angle.cos() * -1024.0) as i32;
|
||||
npc.vel_y = (angle.sin() * -1024.0) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc);
|
||||
state.sound_manager.play_sfx(39);
|
||||
|
|
|
@ -142,12 +142,12 @@ impl NPC {
|
|||
0 | 1 => {
|
||||
if self.action_num == 0 {
|
||||
let angle = self.rng.range(0..0xff);
|
||||
self.vel_x = ((angle as f64 * 1.40625).cos() * 512.0) as isize;
|
||||
self.target_x = self.x + ((angle as f64 * 1.40625 + std::f64::consts::FRAC_2_PI).cos() * 8.0 * 512.0) as isize;
|
||||
self.vel_x = ((angle as f64 * 1.40625).cos() * 512.0) as i32;
|
||||
self.target_x = self.x + ((angle as f64 * 1.40625 + std::f64::consts::FRAC_2_PI).cos() * 8.0 * 512.0) as i32;
|
||||
|
||||
let angle = self.rng.range(0..0xff);
|
||||
self.vel_y = ((angle as f64 * 1.40625).sin() * 512.0) as isize;
|
||||
self.target_y = self.y + ((angle as f64 * 1.40625 + std::f64::consts::FRAC_2_PI).sin() * 8.0 * 512.0) as isize;
|
||||
self.vel_y = ((angle as f64 * 1.40625).sin() * 512.0) as i32;
|
||||
self.target_y = self.y + ((angle as f64 * 1.40625 + std::f64::consts::FRAC_2_PI).sin() * 8.0 * 512.0) as i32;
|
||||
|
||||
self.action_num = 1;
|
||||
self.action_counter2 = 120;
|
||||
|
@ -873,8 +873,8 @@ impl NPC {
|
|||
npc.x = self.x;
|
||||
npc.y = self.y;
|
||||
for _ in 0..4 {
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as i32;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
}
|
||||
|
@ -938,8 +938,8 @@ impl NPC {
|
|||
npc.x = self.x;
|
||||
npc.y = self.y;
|
||||
for _ in 0..8 {
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as i32;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
}
|
||||
|
@ -978,8 +978,8 @@ impl NPC {
|
|||
npc.x = self.x;
|
||||
npc.y = self.y;
|
||||
for _ in 0..4 {
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as i32;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
}
|
||||
|
@ -1059,8 +1059,8 @@ impl NPC {
|
|||
npc.x = self.x;
|
||||
npc.y = self.y;
|
||||
for _ in 0..8 {
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as i32;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
}
|
||||
|
@ -1224,8 +1224,8 @@ impl NPC {
|
|||
self.target_y = self.y;
|
||||
}
|
||||
|
||||
self.x = self.target_x + self.rng.range(-1..1) as isize * 0x200;
|
||||
self.y = self.target_y + self.rng.range(-1..1) as isize * 0x200;
|
||||
self.x = self.target_x + self.rng.range(-1..1) as i32 * 0x200;
|
||||
self.y = self.target_y + self.rng.range(-1..1) as i32 * 0x200;
|
||||
|
||||
self.action_counter += 1;
|
||||
if self.action_counter > 30 {
|
||||
|
@ -1245,7 +1245,7 @@ impl NPC {
|
|||
|
||||
self.vel_x += 0x20;
|
||||
self.x += self.vel_x;
|
||||
self.y = self.target_y + self.rng.range(-1..1) as isize * 0x200;
|
||||
self.y = self.target_y + self.rng.range(-1..1) as i32 * 0x200;
|
||||
self.action_counter += 1;
|
||||
|
||||
if self.action_counter > 10 {
|
||||
|
|
|
@ -204,10 +204,10 @@ impl NPC {
|
|||
npc.cond.set_alive(true);
|
||||
|
||||
for _ in 0..4 {
|
||||
npc.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
npc.x = self.x + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as i32;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
}
|
||||
|
@ -235,8 +235,8 @@ impl NPC {
|
|||
self.action_counter += 1;
|
||||
if self.action_counter > 100 && self.action_counter % 6 == 1 {
|
||||
let deg = (if self.direction == Direction::Left { 0x88 } else { 0xf8 } + self.rng.range(-16..16)) as f64 * CDEG_RAD;
|
||||
let vel_x = (deg.cos() * 1536.0) as isize;
|
||||
let vel_y = (deg.sin() * 1536.0) as isize;
|
||||
let vel_x = (deg.cos() * 1536.0) as i32;
|
||||
let vel_y = (deg.sin() * 1536.0) as i32;
|
||||
|
||||
let mut npc = NPC::create(11, &state.npc_table);
|
||||
|
||||
|
@ -289,10 +289,10 @@ impl NPC {
|
|||
npc.cond.set_alive(true);
|
||||
|
||||
for _ in 0..8 {
|
||||
npc.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
npc.x = self.x + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as i32;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
}
|
||||
|
@ -309,10 +309,10 @@ impl NPC {
|
|||
|
||||
npc.cond.set_alive(true);
|
||||
npc.direction = Direction::Left;
|
||||
npc.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
npc.x = self.x + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as i32;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc);
|
||||
}
|
||||
|
@ -349,10 +349,10 @@ impl NPC {
|
|||
|
||||
npc.cond.set_alive(true);
|
||||
npc.direction = Direction::Left;
|
||||
npc.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
npc.x = self.x + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as i32;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc);
|
||||
}
|
||||
|
|
|
@ -122,7 +122,7 @@ impl NPC {
|
|||
|
||||
self.anim_counter += 1;
|
||||
if (self.anim_counter % 8) == 1 {
|
||||
state.create_caret(self.x + state.effect_rng.range(-8..8) as isize * 0x200,
|
||||
state.create_caret(self.x + state.effect_rng.range(-8..8) as i32 * 0x200,
|
||||
self.y + 8 * 0x200,
|
||||
CaretType::LittleParticles, Direction::Up);
|
||||
}
|
||||
|
|
|
@ -31,85 +31,4 @@ impl NPC {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n361_gaudi_dashing(&mut self, state: &mut SharedGameState, players: [&mut Player; 2], npc_list: &NPCList) -> GameResult {
|
||||
match self.action_num {
|
||||
0 | 1 => {
|
||||
if self.action_num == 0 {
|
||||
self.vel_x2 = 0;
|
||||
self.vel_y2 = 0;
|
||||
self.action_num = 1;
|
||||
}
|
||||
|
||||
let player = self.get_closest_player_mut(players);
|
||||
if (self.direction == Direction::Right && player.x > self.x + 272 * 0x200 && player.x < self.x + 288 * 0x200)
|
||||
|| (self.direction == Direction::Left && player.x < self.x - 272 * 0x200 && player.x > self.x - 288 * 0x200) {
|
||||
self.action_num = 10;
|
||||
} else {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
10 | 11 => {
|
||||
if self.action_num == 10 {
|
||||
self.npc_flags.set_shootable(true);
|
||||
self.action_num = 11;
|
||||
self.damage = 5;
|
||||
}
|
||||
|
||||
let player = self.get_closest_player_mut(players);
|
||||
if self.x > player.x {
|
||||
self.direction = Direction::Left;
|
||||
} else {
|
||||
self.direction = Direction::Right;
|
||||
}
|
||||
|
||||
self.anim_counter += 1;
|
||||
if self.anim_counter > 1 {
|
||||
self.anim_counter = 0;
|
||||
self.anim_num += 1;
|
||||
|
||||
if self.anim_num > 1 {
|
||||
self.anim_num = 0;
|
||||
}
|
||||
}
|
||||
|
||||
self.vel_x2 += self.direction.vector_x() * 0x10;
|
||||
self.vel_y2 += (player.y - self.y).signum() * 0x10;
|
||||
|
||||
if self.vel_x2 < 0 && self.flags.hit_left_wall() {
|
||||
self.vel_x2 /= -2;
|
||||
}
|
||||
|
||||
if self.vel_x2 > 0 && self.flags.hit_right_wall() {
|
||||
self.vel_x2 /= -2;
|
||||
}
|
||||
|
||||
if self.vel_y2 < 0 && self.flags.hit_top_wall() {
|
||||
self.vel_y2 *= -1;
|
||||
}
|
||||
|
||||
if self.vel_y2 > 0 && self.flags.hit_bottom_wall() {
|
||||
self.vel_y2 /= -2;
|
||||
}
|
||||
|
||||
self.vel_x2 = clamp(self.vel_x2, -0x5ff, 0x5ff);
|
||||
self.vel_y2 = clamp(self.vel_y2, -0x5ff, 0x5ff);
|
||||
|
||||
self.x += self.vel_x2;
|
||||
self.y += self.vel_y2;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if self.life <= 985 {
|
||||
npc_list.create_death_smoke(self.x, self.y, 0, 2, state, &self.rng);
|
||||
self.npc_type = 154;
|
||||
self.action_num = 0;
|
||||
}
|
||||
|
||||
let dir_offset = if self.direction == Direction::Left { 0 } else { 2 };
|
||||
self.anim_rect = state.constants.npc.n361_gaudi_dashing[self.anim_num as usize + dir_offset];
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,8 +54,8 @@ impl NPC {
|
|||
|
||||
if self.direction == Direction::Left || self.direction == Direction::Up {
|
||||
let angle = self.rng.range(0..31415) as f32 / 5000.0;
|
||||
self.vel_x = (angle.cos() * self.rng.range(0x200..0x5ff) as f32) as isize;
|
||||
self.vel_y = (angle.sin() * self.rng.range(0x200..0x5ff) as f32) as isize;
|
||||
self.vel_x = (angle.cos() * self.rng.range(0x200..0x5ff) as f32) as i32;
|
||||
self.vel_y = (angle.sin() * self.rng.range(0x200..0x5ff) as f32) as i32;
|
||||
}
|
||||
} else {
|
||||
self.vel_x = (self.vel_x * 20) / 21;
|
||||
|
@ -147,10 +147,10 @@ impl NPC {
|
|||
npc.cond.set_alive(true);
|
||||
|
||||
for _ in 0..4 {
|
||||
npc.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
npc.x = self.x + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as i32;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
}
|
||||
|
@ -307,8 +307,8 @@ impl NPC {
|
|||
npc.x = self.x;
|
||||
npc.y = self.y;
|
||||
for _ in 0..4 {
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as i32;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
}
|
||||
|
@ -571,13 +571,13 @@ impl NPC {
|
|||
droplet.direction = Direction::Left;
|
||||
droplet.x = self.x;
|
||||
droplet.y = self.y;
|
||||
droplet.vel_x = 2 * self.rng.range(-0x200..0x200) as isize;
|
||||
droplet.vel_y = 3 * self.rng.range(-0x200..0x80) as isize;
|
||||
droplet.vel_x = 2 * self.rng.range(-0x200..0x200) as i32;
|
||||
droplet.vel_y = 3 * self.rng.range(-0x200..0x80) as i32;
|
||||
let _ = npc_list.spawn(0x100, droplet.clone());
|
||||
|
||||
if self.action_counter % 2 == 0 {
|
||||
droplet.vel_x = 2 * self.rng.range(-0x200..0x200) as isize;
|
||||
droplet.vel_y = 3 * self.rng.range(-0x200..0x80) as isize;
|
||||
droplet.vel_x = 2 * self.rng.range(-0x200..0x200) as i32;
|
||||
droplet.vel_y = 3 * self.rng.range(-0x200..0x80) as i32;
|
||||
let _ = npc_list.spawn(0x100, droplet);
|
||||
}
|
||||
}
|
||||
|
@ -610,7 +610,7 @@ impl NPC {
|
|||
self.cond.set_alive(false);
|
||||
}
|
||||
|
||||
if self.y > stage.map.height as isize * 16 * 0x200 {
|
||||
if self.y > stage.map.height as i32 * 16 * 0x200 {
|
||||
// out of map
|
||||
self.cond.set_alive(false);
|
||||
}
|
||||
|
@ -698,7 +698,7 @@ impl NPC {
|
|||
particle.cond.set_alive(true);
|
||||
particle.direction = Direction::Left;
|
||||
particle.x = self.x;
|
||||
particle.y = self.y + (self.rng.range(-8..8) * 0x200) as isize;
|
||||
particle.y = self.y + (self.rng.range(-8..8) * 0x200) as i32;
|
||||
let _ = npc_list.spawn(0x100, particle);
|
||||
}
|
||||
}
|
||||
|
@ -750,7 +750,7 @@ impl NPC {
|
|||
let mut particle = NPC::create(199, &state.npc_table);
|
||||
particle.cond.set_alive(true);
|
||||
particle.direction = Direction::Up;
|
||||
particle.x = self.x + (self.rng.range(-8..8) * 0x200) as isize;
|
||||
particle.x = self.x + (self.rng.range(-8..8) * 0x200) as i32;
|
||||
particle.y = self.y;
|
||||
let _ = npc_list.spawn(0x100, particle);
|
||||
}
|
||||
|
@ -803,7 +803,7 @@ impl NPC {
|
|||
particle.cond.set_alive(true);
|
||||
particle.direction = Direction::Right;
|
||||
particle.x = self.x;
|
||||
particle.y = self.y + (self.rng.range(-8..8) * 0x200) as isize;
|
||||
particle.y = self.y + (self.rng.range(-8..8) * 0x200) as i32;
|
||||
let _ = npc_list.spawn(0x100, particle);
|
||||
}
|
||||
}
|
||||
|
@ -851,7 +851,7 @@ impl NPC {
|
|||
let mut particle = NPC::create(199, &state.npc_table);
|
||||
particle.cond.set_alive(true);
|
||||
particle.direction = Direction::Bottom;
|
||||
particle.x = self.x + (self.rng.range(-8..8) * 0x200) as isize;
|
||||
particle.x = self.x + (self.rng.range(-8..8) * 0x200) as i32;
|
||||
particle.y = self.y;
|
||||
let _ = npc_list.spawn(0x100, particle);
|
||||
}
|
||||
|
@ -944,8 +944,8 @@ impl NPC {
|
|||
npc.y = self.y;
|
||||
|
||||
for _ in 0..4 {
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as i32;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
}
|
||||
|
@ -1051,10 +1051,10 @@ impl NPC {
|
|||
let mut npc = NPC::create(4, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
for _ in 0..3 {
|
||||
npc.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
npc.x = self.x + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as i32;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
}
|
||||
|
@ -1099,10 +1099,10 @@ impl NPC {
|
|||
let mut npc = NPC::create(4, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
for _ in 0..3 {
|
||||
npc.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
npc.x = self.x + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as i32;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
}
|
||||
|
@ -1170,10 +1170,10 @@ impl NPC {
|
|||
let mut npc = NPC::create(4, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
for _ in 0..3 {
|
||||
npc.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
npc.x = self.x + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as i32;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
}
|
||||
|
@ -1218,10 +1218,10 @@ impl NPC {
|
|||
let mut npc = NPC::create(4, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
for _ in 0..3 {
|
||||
npc.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
npc.x = self.x + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as i32 * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as i32;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
}
|
||||
|
@ -1267,8 +1267,8 @@ impl NPC {
|
|||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
self.anim_num = self.rng.range(0..2) as u16;
|
||||
self.vel_x = self.direction.vector_x() * (self.rng.range(4..8) * 0x200 / 2) as isize;
|
||||
self.vel_y = self.direction.vector_y() * (self.rng.range(4..8) * 0x200 / 2) as isize;
|
||||
self.vel_x = self.direction.vector_x() * (self.rng.range(4..8) * 0x200 / 2) as i32;
|
||||
self.vel_y = self.direction.vector_y() * (self.rng.range(4..8) * 0x200 / 2) as i32;
|
||||
}
|
||||
|
||||
self.anim_counter += 1;
|
||||
|
|
|
@ -18,8 +18,8 @@ impl NPC {
|
|||
self.target_y = npc.y;
|
||||
|
||||
let angle = ((self.y - self.target_y) as f64 / (self.x - self.target_x) as f64).atan();
|
||||
self.vel_x = (angle.cos() * 1024.0) as isize; // 2.0fix9
|
||||
self.vel_y = (angle.sin() * 1024.0) as isize;
|
||||
self.vel_x = (angle.cos() * 1024.0) as i32; // 2.0fix9
|
||||
self.vel_y = (angle.sin() * 1024.0) as i32;
|
||||
}
|
||||
|
||||
if self.action_counter2 == 0 {
|
||||
|
@ -78,7 +78,7 @@ impl NPC {
|
|||
state.sound_manager.play_sfx(29);
|
||||
}
|
||||
|
||||
self.x = self.target_x + self.rng.range(-1..1) as isize * 0x200;
|
||||
self.x = self.target_x + self.rng.range(-1..1) as i32 * 0x200;
|
||||
|
||||
self.action_counter += 1;
|
||||
if self.action_counter >= 32 {
|
||||
|
@ -341,7 +341,7 @@ impl NPC {
|
|||
npc.x = self.x + 8 * 0x200;
|
||||
npc.y = self.y - 8 * 0x200;
|
||||
npc.vel_x = 0x600;
|
||||
npc.vel_y = self.rng.range(-0x200..0) as isize;
|
||||
npc.vel_y = self.rng.range(-0x200..0) as i32;
|
||||
npc.cond.set_alive(true);
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc);
|
||||
|
|
|
@ -12,8 +12,8 @@ impl NPC {
|
|||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
|
||||
self.vel_x = self.rng.range(-0x80..0x80) as isize;
|
||||
self.vel_y = self.rng.range(-0x7f..0x100) as isize;
|
||||
self.vel_x = self.rng.range(-0x80..0x80) as i32;
|
||||
self.vel_y = self.rng.range(-0x7f..0x100) as i32;
|
||||
}
|
||||
|
||||
self.vel_x -= 0x8;
|
||||
|
@ -43,8 +43,8 @@ impl NPC {
|
|||
self.action_num = 1;
|
||||
self.anim_num = self.rng.range(0..4) as u16;
|
||||
|
||||
self.vel_x = self.rng.range(-0x200..0x200) as isize;
|
||||
self.vel_y = self.rng.range(-0x400..0) as isize;
|
||||
self.vel_x = self.rng.range(-0x200..0x200) as i32;
|
||||
self.vel_y = self.rng.range(-0x400..0) as i32;
|
||||
|
||||
self.direction = if self.rng.range(0..1) != 0 {
|
||||
Direction::Left
|
||||
|
@ -162,8 +162,8 @@ impl NPC {
|
|||
if state.control_flags.wind() {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
self.vel_x = self.rng.range(0x7f..0x100) as isize;
|
||||
self.vel_y = self.rng.range(-0x20..0x20) as isize;
|
||||
self.vel_x = self.rng.range(0x7f..0x100) as i32;
|
||||
self.vel_y = self.rng.range(-0x20..0x20) as i32;
|
||||
}
|
||||
|
||||
self.vel_x -= 0x08;
|
||||
|
@ -230,8 +230,8 @@ impl NPC {
|
|||
if state.control_flags.wind() {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
self.vel_x = self.rng.range(0x7f..0x100) as isize;
|
||||
self.vel_y = self.rng.range(-0x20..0x20) as isize;
|
||||
self.vel_x = self.rng.range(0x7f..0x100) as i32;
|
||||
self.vel_y = self.rng.range(-0x20..0x20) as i32;
|
||||
}
|
||||
|
||||
self.vel_x -= 0x08;
|
||||
|
|
|
@ -167,8 +167,8 @@ impl NPC {
|
|||
npc.y = self.y;
|
||||
|
||||
for _ in 0..4 {
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as i32;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
}
|
||||
|
@ -216,8 +216,8 @@ impl NPC {
|
|||
}
|
||||
|
||||
self.target_y += 0x100;
|
||||
self.x = self.target_x + self.rng.range(-1..1) as isize * 0x200;
|
||||
self.y = self.target_y + self.rng.range(-1..1) as isize * 0x200;
|
||||
self.x = self.target_x + self.rng.range(-1..1) as i32 * 0x200;
|
||||
self.y = self.target_y + self.rng.range(-1..1) as i32 * 0x200;
|
||||
}
|
||||
70 | 71 => {
|
||||
if self.action_num == 70 {
|
||||
|
@ -227,7 +227,7 @@ impl NPC {
|
|||
self.anim_counter = 0;
|
||||
}
|
||||
|
||||
self.x += (self.direction.vector_x() as isize | 1) * 0x100;
|
||||
self.x += (self.direction.vector_x() as i32 | 1) * 0x100;
|
||||
|
||||
self.anim_counter += 1;
|
||||
if self.anim_counter > 8 {
|
||||
|
|
|
@ -153,14 +153,14 @@ impl NPC {
|
|||
if self.action_num == 0 {
|
||||
self.action_num = 2;
|
||||
self.vel_x = if self.rng.next_u16() & 1 != 0 {
|
||||
self.rng.range(-0x200..-0x100) as isize
|
||||
self.rng.range(-0x200..-0x100) as i32
|
||||
} else {
|
||||
self.rng.range(0x100..0x200) as isize
|
||||
self.rng.range(0x100..0x200) as i32
|
||||
};
|
||||
self.vel_y = if self.rng.next_u16() & 1 != 0 {
|
||||
self.rng.range(-0x200..-0x100) as isize
|
||||
self.rng.range(-0x200..-0x100) as i32
|
||||
} else {
|
||||
self.rng.range(0x100..0x200) as isize
|
||||
self.rng.range(0x100..0x200) as i32
|
||||
};
|
||||
self.vel_x2 = self.vel_x;
|
||||
self.vel_y2 = self.vel_y;
|
||||
|
|
|
@ -80,10 +80,10 @@ impl BossNPC {
|
|||
for _ in 0..8 {
|
||||
npc.cond.set_alive(true);
|
||||
npc.direction = Direction::Left;
|
||||
npc.x = self.parts[0].x + self.parts[0].rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.parts[0].y + self.parts[0].rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.parts[0].rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.parts[0].rng.range(-0x600..0) as isize;
|
||||
npc.x = self.parts[0].x + self.parts[0].rng.range(-12..12) as i32 * 0x200;
|
||||
npc.y = self.parts[0].y + self.parts[0].rng.range(-12..12) as i32 * 0x200;
|
||||
npc.vel_x = self.parts[0].rng.range(-0x155..0x155) as i32;
|
||||
npc.vel_y = self.parts[0].rng.range(-0x600..0) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
}
|
||||
|
@ -168,8 +168,8 @@ impl BossNPC {
|
|||
|
||||
let mut npc = NPC::create(110, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
npc.x = self.parts[0].rng.range(4..16) as isize * 16 * 0x200;
|
||||
npc.y = self.parts[0].rng.range(0..4) as isize * 16 * 0x200;
|
||||
npc.x = self.parts[0].rng.range(4..16) as i32 * 16 * 0x200;
|
||||
npc.y = self.parts[0].rng.range(0..4) as i32 * 16 * 0x200;
|
||||
npc.direction = Direction::FacingPlayer;
|
||||
|
||||
let _ = npc_list.spawn(0x80, npc);
|
||||
|
@ -179,10 +179,10 @@ impl BossNPC {
|
|||
for _ in 0..4 {
|
||||
npc.cond.set_alive(true);
|
||||
npc.direction = Direction::Left;
|
||||
npc.x = self.parts[0].x + self.parts[0].rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.parts[0].y + self.parts[0].rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.parts[0].rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.parts[0].rng.range(-0x600..0) as isize;
|
||||
npc.x = self.parts[0].x + self.parts[0].rng.range(-12..12) as i32 * 0x200;
|
||||
npc.y = self.parts[0].y + self.parts[0].rng.range(-12..12) as i32 * 0x200;
|
||||
npc.vel_x = self.parts[0].rng.range(-0x155..0x155) as i32;
|
||||
npc.vel_y = self.parts[0].rng.range(-0x600..0) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
}
|
||||
|
@ -216,7 +216,7 @@ impl BossNPC {
|
|||
self.parts[0].action_counter = 0;
|
||||
self.parts[0].vel_x2 = 16;
|
||||
self.parts[0].anim_num = 3;
|
||||
self.parts[0].target_x = self.parts[0].life as isize;
|
||||
self.parts[0].target_x = self.parts[0].life as i32;
|
||||
self.parts[1].npc_flags.set_shootable(true);
|
||||
}
|
||||
}
|
||||
|
@ -250,14 +250,14 @@ impl BossNPC {
|
|||
npc.cond.set_alive(true);
|
||||
npc.x = self.parts[0].x + self.parts[0].direction.vector_x() * 2 * 16 * 0x200;
|
||||
npc.y = self.parts[0].y - 8 * 0x200;
|
||||
npc.vel_x = (deg.cos() * -512.0) as isize;
|
||||
npc.vel_y = (deg.sin() * -512.0) as isize;
|
||||
npc.vel_x = (deg.cos() * -512.0) as i32;
|
||||
npc.vel_y = (deg.sin() * -512.0) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc);
|
||||
|
||||
state.sound_manager.play_sfx(39);
|
||||
|
||||
if self.parts[0].vel_x2 == 0 || (self.parts[0].life as isize) < self.parts[0].target_x - 90 {
|
||||
if self.parts[0].vel_x2 == 0 || (self.parts[0].life as i32) < self.parts[0].target_x - 90 {
|
||||
self.parts[0].action_num = 114;
|
||||
self.parts[0].action_counter = 0;
|
||||
self.parts[0].anim_num = 2;
|
||||
|
@ -326,8 +326,8 @@ impl BossNPC {
|
|||
let mut npc = NPC::create(104, &state.npc_table);
|
||||
for _ in 0..2 {
|
||||
npc.cond.set_alive(true);
|
||||
npc.x = self.parts[0].rng.range(4..16) as isize * 16 * 0x200;
|
||||
npc.y = self.parts[0].rng.range(0..4) as isize * 16 * 0x200;
|
||||
npc.x = self.parts[0].rng.range(4..16) as i32 * 16 * 0x200;
|
||||
npc.y = self.parts[0].rng.range(0..4) as i32 * 16 * 0x200;
|
||||
npc.direction = Direction::FacingPlayer;
|
||||
|
||||
let _ = npc_list.spawn(0x80, npc.clone());
|
||||
|
@ -336,8 +336,8 @@ impl BossNPC {
|
|||
let mut npc = NPC::create(110, &state.npc_table);
|
||||
for _ in 0..6 {
|
||||
npc.cond.set_alive(true);
|
||||
npc.x = self.parts[0].rng.range(4..16) as isize * 16 * 0x200;
|
||||
npc.y = self.parts[0].rng.range(0..4) as isize * 16 * 0x200;
|
||||
npc.x = self.parts[0].rng.range(4..16) as i32 * 16 * 0x200;
|
||||
npc.y = self.parts[0].rng.range(0..4) as i32 * 16 * 0x200;
|
||||
npc.direction = Direction::FacingPlayer;
|
||||
|
||||
let _ = npc_list.spawn(0x80, npc.clone());
|
||||
|
@ -346,10 +346,10 @@ impl BossNPC {
|
|||
let mut npc = NPC::create(4, &state.npc_table);
|
||||
for _ in 0..8 {
|
||||
npc.cond.set_alive(true);
|
||||
npc.x = self.parts[0].x + self.parts[0].rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.parts[0].y + self.parts[0].hit_bounds.bottom as isize;
|
||||
npc.vel_x = self.parts[0].rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.parts[0].rng.range(-0x600..0) as isize;
|
||||
npc.x = self.parts[0].x + self.parts[0].rng.range(-12..12) as i32 * 0x200;
|
||||
npc.y = self.parts[0].y + self.parts[0].hit_bounds.bottom as i32;
|
||||
npc.vel_x = self.parts[0].rng.range(-0x155..0x155) as i32;
|
||||
npc.vel_y = self.parts[0].rng.range(-0x600..0) as i32;
|
||||
npc.direction = Direction::Left;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
|
@ -385,10 +385,10 @@ impl BossNPC {
|
|||
let mut npc = NPC::create(4, &state.npc_table);
|
||||
for _ in 0..8 {
|
||||
npc.cond.set_alive(true);
|
||||
npc.x = self.parts[0].x + self.parts[0].rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.parts[0].y + self.parts[0].rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.parts[0].rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.parts[0].rng.range(-0x600..0) as isize;
|
||||
npc.x = self.parts[0].x + self.parts[0].rng.range(-12..12) as i32 * 0x200;
|
||||
npc.y = self.parts[0].y + self.parts[0].rng.range(-12..12) as i32 * 0x200;
|
||||
npc.vel_x = self.parts[0].rng.range(-0x155..0x155) as i32;
|
||||
npc.vel_y = self.parts[0].rng.range(-0x600..0) as i32;
|
||||
npc.direction = Direction::Left;
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
}
|
||||
|
@ -398,10 +398,10 @@ impl BossNPC {
|
|||
if (self.parts[0].action_counter % 5) == 0 {
|
||||
let mut npc = NPC::create(4, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
npc.x = self.parts[0].x + self.parts[0].rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.parts[0].y + self.parts[0].rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.parts[0].rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.parts[0].rng.range(-0x600..0) as isize;
|
||||
npc.x = self.parts[0].x + self.parts[0].rng.range(-12..12) as i32 * 0x200;
|
||||
npc.y = self.parts[0].y + self.parts[0].rng.range(-12..12) as i32 * 0x200;
|
||||
npc.vel_x = self.parts[0].rng.range(-0x155..0x155) as i32;
|
||||
npc.vel_y = self.parts[0].rng.range(-0x600..0) as i32;
|
||||
npc.direction = Direction::Left;
|
||||
let _ = npc_list.spawn(0x100, npc);
|
||||
}
|
||||
|
@ -440,10 +440,10 @@ impl BossNPC {
|
|||
if (self.parts[0].action_counter % 9) == 0 {
|
||||
let mut npc = NPC::create(4, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
npc.x = self.parts[0].x + self.parts[0].rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.parts[0].y + self.parts[0].rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.parts[0].rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.parts[0].rng.range(-0x600..0) as isize;
|
||||
npc.x = self.parts[0].x + self.parts[0].rng.range(-12..12) as i32 * 0x200;
|
||||
npc.y = self.parts[0].y + self.parts[0].rng.range(-12..12) as i32 * 0x200;
|
||||
npc.vel_x = self.parts[0].rng.range(-0x155..0x155) as i32;
|
||||
npc.vel_y = self.parts[0].rng.range(-0x600..0) as i32;
|
||||
npc.direction = Direction::Left;
|
||||
let _ = npc_list.spawn(0x100, npc);
|
||||
}
|
||||
|
|
|
@ -96,17 +96,17 @@ impl GameEntity<([&mut Player; 2], &NPCList, &mut Stage, &BulletManager)> for Bo
|
|||
continue;
|
||||
}
|
||||
|
||||
let off_x = if npc.direction == Direction::Left { npc.display_bounds.left } else { npc.display_bounds.right } as isize;
|
||||
let off_x = if npc.direction == Direction::Left { npc.display_bounds.left } else { npc.display_bounds.right } as i32;
|
||||
let shock = if npc.shock > 0 {
|
||||
(2 * ((npc.shock as isize / 2) % 2) - 1) as f32
|
||||
(2 * ((npc.shock as i32 / 2) % 2) - 1) as f32
|
||||
} else { 0.0 };
|
||||
|
||||
batch.add_rect(
|
||||
interpolate_fix9_scale(npc.prev_x - off_x - frame.prev_x,
|
||||
npc.x - off_x - frame.x,
|
||||
state.frame_time) + shock,
|
||||
interpolate_fix9_scale(npc.prev_y - npc.display_bounds.top as isize - frame.prev_y,
|
||||
npc.y - npc.display_bounds.top as isize - frame.y,
|
||||
interpolate_fix9_scale(npc.prev_y - npc.display_bounds.top as i32 - frame.prev_y,
|
||||
npc.y - npc.display_bounds.top as i32 - frame.y,
|
||||
state.frame_time),
|
||||
&npc.anim_rect,
|
||||
);
|
||||
|
|
|
@ -27,8 +27,8 @@ impl NPC {
|
|||
}
|
||||
|
||||
let radians = self.action_counter2 as f64 * CDEG_RAD;
|
||||
self.vel_x = 2 * (radians.cos() * 512.0) as isize;
|
||||
self.vel_y = 2 * (radians.sin() * 512.0) as isize;
|
||||
self.vel_x = 2 * (radians.cos() * 512.0) as i32;
|
||||
self.vel_y = 2 * (radians.sin() * 512.0) as i32;
|
||||
self.x += self.vel_x;
|
||||
self.y += self.vel_y;
|
||||
|
||||
|
@ -391,13 +391,13 @@ impl BossNPC {
|
|||
if self.parts[0].action_num == 600 {
|
||||
self.parts[0].action_num = 601;
|
||||
self.parts[0].action_counter = 0;
|
||||
self.parts[0].vel_y2 = self.parts[0].life as isize;
|
||||
self.parts[0].vel_y2 = self.parts[0].life as i32;
|
||||
self.parts[1].action_num = 30;
|
||||
self.parts[2].action_num = 30;
|
||||
}
|
||||
|
||||
self.parts[0].action_counter += 1;
|
||||
if (self.parts[0].life as isize) < self.parts[0].vel_y2.saturating_sub(200)
|
||||
if (self.parts[0].life as i32) < self.parts[0].vel_y2.saturating_sub(200)
|
||||
|| self.parts[0].action_counter > 300 {
|
||||
self.parts[0].action_num = 602;
|
||||
self.parts[0].action_counter = 0;
|
||||
|
@ -429,8 +429,8 @@ impl BossNPC {
|
|||
|
||||
let mut npc = NPC::create(4, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
npc.x = self.parts[0].x + self.parts[0].rng.range(-72..72) as isize * 0x200;
|
||||
npc.y = self.parts[0].y + self.parts[0].rng.range(-64..64) as isize * 0x200;
|
||||
npc.x = self.parts[0].x + self.parts[0].rng.range(-72..72) as i32 * 0x200;
|
||||
npc.y = self.parts[0].y + self.parts[0].rng.range(-64..64) as i32 * 0x200;
|
||||
let _ = npc_list.spawn(0x100, npc);
|
||||
|
||||
if self.parts[0].action_counter > 100 {
|
||||
|
@ -805,8 +805,8 @@ impl BossNPC {
|
|||
npc.cond.set_alive(true);
|
||||
npc.x = self.parts[i].x;
|
||||
npc.y = self.parts[i].y;
|
||||
npc.vel_x = (deg.cos() * -1536.0) as isize;
|
||||
npc.vel_y = (deg.sin() * -1536.0) as isize;
|
||||
npc.vel_x = (deg.cos() * -1536.0) as i32;
|
||||
npc.vel_y = (deg.sin() * -1536.0) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc);
|
||||
|
||||
|
|
|
@ -187,7 +187,7 @@ impl BossNPC {
|
|||
npc.cond.set_alive(true);
|
||||
npc.x = self.parts[0].x;
|
||||
npc.y = self.parts[0].y - 16 * 0x200;
|
||||
npc.vel_x = self.parts[0].rng.range(-0x100..0x100) as isize;
|
||||
npc.vel_x = self.parts[0].rng.range(-0x100..0x100) as i32;
|
||||
npc.vel_y = -0x333;
|
||||
npc.direction = if self.parts[0].rng.range(0..9) <= 7 {
|
||||
Direction::Left
|
||||
|
@ -253,7 +253,7 @@ impl BossNPC {
|
|||
if self.parts[0].action_counter == 120 {
|
||||
self.parts[0].action_num = 30;
|
||||
self.parts[0].action_counter = 0;
|
||||
self.parts[0].x = self.parts[0].target_x + self.parts[0].rng.range(-0x40..0x40) as isize * 0x200;
|
||||
self.parts[0].x = self.parts[0].target_x + self.parts[0].rng.range(-0x40..0x40) as i32 * 0x200;
|
||||
self.parts[0].y = self.parts[0].target_y;
|
||||
}
|
||||
}
|
||||
|
@ -285,7 +285,7 @@ impl BossNPC {
|
|||
npc.cond.set_alive(true);
|
||||
npc.x = self.parts[0].x;
|
||||
npc.y = self.parts[0].y - 16 * 0x200;
|
||||
npc.vel_x = self.parts[0].rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_x = self.parts[0].rng.range(-0x155..0x155) as i32;
|
||||
npc.vel_y = -0x333;
|
||||
npc.direction = Direction::Left;
|
||||
|
||||
|
@ -350,8 +350,8 @@ impl BossNPC {
|
|||
state.sound_manager.play_sfx(52);
|
||||
}
|
||||
|
||||
let dest_x = self.parts[0].x + self.parts[0].rng.range(-0x30..0x30) as isize * 0x200;
|
||||
let dest_y = self.parts[0].y + self.parts[0].rng.range(-0x30..0x18) as isize * 0x200;
|
||||
let dest_x = self.parts[0].x + self.parts[0].rng.range(-0x30..0x30) as i32 * 0x200;
|
||||
let dest_y = self.parts[0].y + self.parts[0].rng.range(-0x30..0x18) as i32 * 0x200;
|
||||
|
||||
let mut npc = NPC::create(4, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
|
|
|
@ -53,22 +53,22 @@ bitfield! {
|
|||
pub struct NPC {
|
||||
pub id: u16,
|
||||
pub npc_type: u16,
|
||||
pub x: isize,
|
||||
pub y: isize,
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
/// X velocity, affected by physics code
|
||||
pub vel_x: isize,
|
||||
pub vel_x: i32,
|
||||
/// Y velocity, affected by physics code
|
||||
pub vel_y: isize,
|
||||
pub vel_y: i32,
|
||||
/// X velocity, unaffected by physics code
|
||||
pub vel_x2: isize,
|
||||
pub vel_x2: i32,
|
||||
/// Y velocity, unaffected by physics code
|
||||
pub vel_y2: isize,
|
||||
pub target_x: isize,
|
||||
pub target_y: isize,
|
||||
pub vel_y2: i32,
|
||||
pub target_x: i32,
|
||||
pub target_y: i32,
|
||||
/// Previous X position, used by frame interpolator
|
||||
pub prev_x: isize,
|
||||
pub prev_x: i32,
|
||||
/// Previous Y position, used by frame interpolator
|
||||
pub prev_y: isize,
|
||||
pub prev_y: i32,
|
||||
pub exp: u16,
|
||||
pub size: u8,
|
||||
pub shock: u16,
|
||||
|
@ -276,7 +276,6 @@ impl GameEntity<([&mut Player; 2], &NPCList, &mut Stage, &BulletManager)> for NP
|
|||
298 => self.tick_n298_intro_doctor(state),
|
||||
299 => self.tick_n299_intro_balrog_misery(state),
|
||||
300 => self.tick_n300_intro_demon_crown(state),
|
||||
361 => self.tick_n361_gaudi_dashing(state, players, npc_list),
|
||||
_ => Ok(()),
|
||||
}?;
|
||||
|
||||
|
@ -302,17 +301,17 @@ impl GameEntity<([&mut Player; 2], &NPCList, &mut Stage, &BulletManager)> for NP
|
|||
|
||||
let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, state.npc_table.get_texture_name(self.npc_type))?;
|
||||
|
||||
let off_x = if self.direction == Direction::Left { self.display_bounds.left } else { self.display_bounds.right } as isize;
|
||||
let off_x = if self.direction == Direction::Left { self.display_bounds.left } else { self.display_bounds.right } as i32;
|
||||
let shock = if self.shock > 0 {
|
||||
(2 * ((self.shock as isize / 2) % 2) - 1) as f32
|
||||
(2 * ((self.shock as i32 / 2) % 2) - 1) as f32
|
||||
} else { 0.0 };
|
||||
|
||||
batch.add_rect(
|
||||
interpolate_fix9_scale(self.prev_x - off_x - frame.prev_x,
|
||||
self.x - off_x - frame.x,
|
||||
state.frame_time) + shock,
|
||||
interpolate_fix9_scale(self.prev_y - self.display_bounds.top as isize - frame.prev_y,
|
||||
self.y - self.display_bounds.top as isize - frame.y,
|
||||
interpolate_fix9_scale(self.prev_y - self.display_bounds.top as i32 - frame.prev_y,
|
||||
self.y - self.display_bounds.top as i32 - frame.y,
|
||||
state.frame_time),
|
||||
&self.anim_rect,
|
||||
);
|
||||
|
@ -324,16 +323,16 @@ impl GameEntity<([&mut Player; 2], &NPCList, &mut Stage, &BulletManager)> for NP
|
|||
|
||||
impl PhysicalEntity for NPC {
|
||||
#[inline(always)]
|
||||
fn x(&self) -> isize { self.x }
|
||||
fn x(&self) -> i32 { self.x }
|
||||
|
||||
#[inline(always)]
|
||||
fn y(&self) -> isize { self.y }
|
||||
fn y(&self) -> i32 { self.y }
|
||||
|
||||
#[inline(always)]
|
||||
fn vel_x(&self) -> isize { self.vel_x }
|
||||
fn vel_x(&self) -> i32 { self.vel_x }
|
||||
|
||||
#[inline(always)]
|
||||
fn vel_y(&self) -> isize { self.vel_y }
|
||||
fn vel_y(&self) -> i32 { self.vel_y }
|
||||
|
||||
#[inline(always)]
|
||||
fn hit_rect_size(&self) -> usize {
|
||||
|
@ -345,10 +344,10 @@ impl PhysicalEntity for NPC {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn offset_x(&self) -> isize { if self.size >= 3 && !self.cond.drs_boss() { -0x1000 } else { 0 } }
|
||||
fn offset_x(&self) -> i32 { if self.size >= 3 && !self.cond.drs_boss() { -0x1000 } else { 0 } }
|
||||
|
||||
#[inline(always)]
|
||||
fn offset_y(&self) -> isize { if self.size >= 3 && !self.cond.drs_boss() { -0x1000 } else { 0 } }
|
||||
fn offset_y(&self) -> i32 { if self.size >= 3 && !self.cond.drs_boss() { -0x1000 } else { 0 } }
|
||||
|
||||
#[inline(always)]
|
||||
fn hit_bounds(&self) -> &Rect<usize> {
|
||||
|
@ -356,22 +355,22 @@ impl PhysicalEntity for NPC {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn set_x(&mut self, x: isize) {
|
||||
fn set_x(&mut self, x: i32) {
|
||||
self.x = x;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn set_y(&mut self, y: isize) {
|
||||
fn set_y(&mut self, y: i32) {
|
||||
self.y = y;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn set_vel_x(&mut self, vel_x: isize) {
|
||||
fn set_vel_x(&mut self, vel_x: i32) {
|
||||
self.vel_x = vel_x;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn set_vel_y(&mut self, vel_y: isize) {
|
||||
fn set_vel_y(&mut self, vel_y: i32) {
|
||||
self.vel_y = vel_y;
|
||||
}
|
||||
|
||||
|
|
|
@ -82,8 +82,8 @@ impl NPC {
|
|||
NPC {
|
||||
id: data.id,
|
||||
npc_type: data.npc_type,
|
||||
x: data.x as isize * 16 * 0x200,
|
||||
y: data.y as isize * 16 * 0x200,
|
||||
x: data.x as i32 * 16 * 0x200,
|
||||
y: data.y as i32 * 16 * 0x200,
|
||||
vel_x: 0,
|
||||
vel_y: 0,
|
||||
vel_x2: 0,
|
||||
|
@ -172,16 +172,16 @@ impl NPC {
|
|||
pub fn collides_with_bullet(&self, bullet: &Bullet) -> bool {
|
||||
(
|
||||
self.npc_flags.shootable()
|
||||
&& (self.x - self.hit_bounds.right as isize) < (bullet.x + bullet.enemy_hit_width as isize)
|
||||
&& (self.x + self.hit_bounds.right as isize) > (bullet.x - bullet.enemy_hit_width as isize)
|
||||
&& (self.y - self.hit_bounds.top as isize) < (bullet.y + bullet.enemy_hit_height as isize)
|
||||
&& (self.y + self.hit_bounds.bottom as isize) > (bullet.y - bullet.enemy_hit_height as isize)
|
||||
&& (self.x - self.hit_bounds.right as i32) < (bullet.x + bullet.enemy_hit_width as i32)
|
||||
&& (self.x + self.hit_bounds.right as i32) > (bullet.x - bullet.enemy_hit_width as i32)
|
||||
&& (self.y - self.hit_bounds.top as i32) < (bullet.y + bullet.enemy_hit_height as i32)
|
||||
&& (self.y + self.hit_bounds.bottom as i32) > (bullet.y - bullet.enemy_hit_height as i32)
|
||||
) || (
|
||||
self.npc_flags.invulnerable()
|
||||
&& (self.x - self.hit_bounds.right as isize) < (bullet.x + bullet.hit_bounds.right as isize)
|
||||
&& (self.x + self.hit_bounds.right as isize) > (bullet.x - bullet.hit_bounds.left as isize)
|
||||
&& (self.y - self.hit_bounds.top as isize) < (bullet.y + bullet.hit_bounds.bottom as isize)
|
||||
&& (self.y + self.hit_bounds.bottom as isize) > (bullet.y - bullet.hit_bounds.top as isize)
|
||||
&& (self.x - self.hit_bounds.right as i32) < (bullet.x + bullet.hit_bounds.right as i32)
|
||||
&& (self.x + self.hit_bounds.right as i32) > (bullet.x - bullet.hit_bounds.left as i32)
|
||||
&& (self.y - self.hit_bounds.top as i32) < (bullet.y + bullet.hit_bounds.bottom as i32)
|
||||
&& (self.y + self.hit_bounds.bottom as i32) > (bullet.y - bullet.hit_bounds.top as i32)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -323,18 +323,18 @@ impl NPCList {
|
|||
|
||||
/// Creates NPC death smoke diffusing in random directions.
|
||||
#[inline]
|
||||
pub fn create_death_smoke(&self, x: isize, y: isize, radius: usize, amount: usize, state: &mut SharedGameState, rng: &dyn RNG) {
|
||||
pub fn create_death_smoke(&self, x: i32, y: i32, radius: usize, amount: usize, state: &mut SharedGameState, rng: &dyn RNG) {
|
||||
self.create_death_smoke_common(x, y, radius, amount, Direction::Left, state, rng)
|
||||
}
|
||||
|
||||
/// Creates NPC death smoke diffusing upwards.
|
||||
#[inline]
|
||||
pub fn create_death_smoke_up(&self, x: isize, y: isize, radius: usize, amount: usize, state: &mut SharedGameState, rng: &dyn RNG) {
|
||||
pub fn create_death_smoke_up(&self, x: i32, y: i32, radius: usize, amount: usize, state: &mut SharedGameState, rng: &dyn RNG) {
|
||||
self.create_death_smoke_common(x, y, radius, amount, Direction::Up, state, rng)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn create_death_smoke_common(&self, x: isize, y: isize, radius: usize, amount: usize, direction: Direction, state: &mut SharedGameState, rng: &dyn RNG) {
|
||||
fn create_death_smoke_common(&self, x: i32, y: i32, radius: usize, amount: usize, direction: Direction, state: &mut SharedGameState, rng: &dyn RNG) {
|
||||
let radius = (radius / 0x200) as i32;
|
||||
|
||||
let mut npc = NPC::create(4, &state.npc_table);
|
||||
|
@ -342,8 +342,8 @@ impl NPCList {
|
|||
npc.direction = direction;
|
||||
|
||||
for _ in 0..amount {
|
||||
let off_x = rng.range(-radius..radius) as isize * 0x200;
|
||||
let off_y = rng.range(-radius..radius) as isize * 0x200;
|
||||
let off_x = rng.range(-radius..radius) as i32 * 0x200;
|
||||
let off_y = rng.range(-radius..radius) as i32 * 0x200;
|
||||
|
||||
npc.x = x + off_x;
|
||||
npc.y = y + off_y;
|
||||
|
|
172
src/physics.rs
172
src/physics.rs
|
@ -12,25 +12,25 @@ use crate::npc::list::NPCList;
|
|||
// 0 | 11 1 2 5
|
||||
// 1 | 12 3 4 6
|
||||
// 2 | 13 8 9 7
|
||||
pub const OFF_X: [isize; 16] = [0, 1, 0, 1, 2, 2, 2, 0, 1, -1, -1, -1, -1, 0, 1, 2];
|
||||
pub const OFF_Y: [isize; 16] = [0, 0, 1, 1, 0, 1, 2, 2, 2, -1, 0, 1, 2, -1, -1, -1];
|
||||
pub const OFF_X: [i32; 16] = [0, 1, 0, 1, 2, 2, 2, 0, 1, -1, -1, -1, -1, 0, 1, 2];
|
||||
pub const OFF_Y: [i32; 16] = [0, 0, 1, 1, 0, 1, 2, 2, 2, -1, 0, 1, 2, -1, -1, -1];
|
||||
|
||||
pub trait PhysicalEntity {
|
||||
fn x(&self) -> isize;
|
||||
fn y(&self) -> isize;
|
||||
fn vel_x(&self) -> isize;
|
||||
fn vel_y(&self) -> isize;
|
||||
fn x(&self) -> i32;
|
||||
fn y(&self) -> i32;
|
||||
fn vel_x(&self) -> i32;
|
||||
fn vel_y(&self) -> i32;
|
||||
|
||||
fn hit_rect_size(&self) -> usize;
|
||||
fn offset_x(&self) -> isize { 0 }
|
||||
fn offset_y(&self) -> isize { 0 }
|
||||
fn offset_x(&self) -> i32 { 0 }
|
||||
fn offset_y(&self) -> i32 { 0 }
|
||||
|
||||
fn hit_bounds(&self) -> &Rect<usize>;
|
||||
|
||||
fn set_x(&mut self, x: isize);
|
||||
fn set_y(&mut self, y: isize);
|
||||
fn set_vel_x(&mut self, x: isize);
|
||||
fn set_vel_y(&mut self, y: isize);
|
||||
fn set_x(&mut self, x: i32);
|
||||
fn set_y(&mut self, y: i32);
|
||||
fn set_vel_x(&mut self, x: i32);
|
||||
fn set_vel_y(&mut self, y: i32);
|
||||
|
||||
fn cond(&mut self) -> &mut Condition;
|
||||
fn flags(&mut self) -> &mut Flag;
|
||||
|
@ -41,15 +41,15 @@ pub trait PhysicalEntity {
|
|||
fn player_left_pressed(&self) -> bool { false }
|
||||
fn player_right_pressed(&self) -> bool { false }
|
||||
|
||||
fn judge_hit_block(&mut self, state: &mut SharedGameState, x: isize, y: isize) {
|
||||
fn judge_hit_block(&mut self, state: &mut SharedGameState, x: i32, y: i32) {
|
||||
let bounds_x = if self.is_player() { 5 } else { 8 };
|
||||
let bounds_y = if self.is_player() { 4 } else { 5 };
|
||||
// left wall
|
||||
if (self.y() - self.hit_bounds().top as isize) < (y * 16 + bounds_y) * 0x200
|
||||
&& (self.y() + self.hit_bounds().bottom as isize) > (y * 16 - bounds_y) * 0x200
|
||||
&& (self.x() - self.hit_bounds().right as isize) < (x * 16 + 8) * 0x200
|
||||
&& (self.x() - self.hit_bounds().right as isize) > x * 16 * 0x200 {
|
||||
self.set_x(((x * 16 + 8) * 0x200) + self.hit_bounds().right as isize);
|
||||
if (self.y() - self.hit_bounds().top as i32) < (y * 16 + bounds_y) * 0x200
|
||||
&& (self.y() + self.hit_bounds().bottom as i32) > (y * 16 - bounds_y) * 0x200
|
||||
&& (self.x() - self.hit_bounds().right as i32) < (x * 16 + 8) * 0x200
|
||||
&& (self.x() - self.hit_bounds().right as i32) > x * 16 * 0x200 {
|
||||
self.set_x(((x * 16 + 8) * 0x200) + self.hit_bounds().right as i32);
|
||||
|
||||
if self.is_player() {
|
||||
if self.vel_x() < -0x180 {
|
||||
|
@ -65,11 +65,11 @@ pub trait PhysicalEntity {
|
|||
}
|
||||
|
||||
// right wall
|
||||
if (self.y() - self.hit_bounds().top as isize) < (y * 16 + bounds_y) * 0x200
|
||||
&& self.y() + self.hit_bounds().bottom as isize > (y * 16 - bounds_y) * 0x200
|
||||
&& (self.x() + self.hit_bounds().right as isize) > (x * 16 - 8) * 0x200
|
||||
&& (self.x() + self.hit_bounds().right as isize) < x * 16 * 0x200 {
|
||||
self.set_x(((x * 16 - 8) * 0x200) - self.hit_bounds().right as isize);
|
||||
if (self.y() - self.hit_bounds().top as i32) < (y * 16 + bounds_y) * 0x200
|
||||
&& self.y() + self.hit_bounds().bottom as i32 > (y * 16 - bounds_y) * 0x200
|
||||
&& (self.x() + self.hit_bounds().right as i32) > (x * 16 - 8) * 0x200
|
||||
&& (self.x() + self.hit_bounds().right as i32) < x * 16 * 0x200 {
|
||||
self.set_x(((x * 16 - 8) * 0x200) - self.hit_bounds().right as i32);
|
||||
|
||||
if self.is_player() {
|
||||
if self.vel_x() > 0x180 {
|
||||
|
@ -85,17 +85,17 @@ pub trait PhysicalEntity {
|
|||
}
|
||||
|
||||
// ceiling
|
||||
if (self.x() - self.hit_bounds().right as isize) < (x * 16 + bounds_x) * 0x200
|
||||
&& (self.x() + self.hit_bounds().right as isize) > (x * 16 - bounds_x) * 0x200
|
||||
&& (self.y() - self.hit_bounds().top as isize) < (y * 16 + 8) * 0x200
|
||||
&& (self.y() - self.hit_bounds().top as isize) > y * 16 * 0x200 {
|
||||
self.set_y(((y * 16 + 8) * 0x200) + self.hit_bounds().top as isize);
|
||||
if (self.x() - self.hit_bounds().right as i32) < (x * 16 + bounds_x) * 0x200
|
||||
&& (self.x() + self.hit_bounds().right as i32) > (x * 16 - bounds_x) * 0x200
|
||||
&& (self.y() - self.hit_bounds().top as i32) < (y * 16 + 8) * 0x200
|
||||
&& (self.y() - self.hit_bounds().top as i32) > y * 16 * 0x200 {
|
||||
self.set_y(((y * 16 + 8) * 0x200) + self.hit_bounds().top as i32);
|
||||
|
||||
if self.is_player() {
|
||||
if !self.cond().hidden() && self.vel_y() < -0x200 {
|
||||
state.sound_manager.play_sfx(3);
|
||||
state.create_caret(self.x(), self.y() - self.hit_bounds().top as isize, CaretType::LittleParticles, Direction::Left);
|
||||
state.create_caret(self.x(), self.y() - self.hit_bounds().top as isize, CaretType::LittleParticles, Direction::Left);
|
||||
state.create_caret(self.x(), self.y() - self.hit_bounds().top as i32, CaretType::LittleParticles, Direction::Left);
|
||||
state.create_caret(self.x(), self.y() - self.hit_bounds().top as i32, CaretType::LittleParticles, Direction::Left);
|
||||
}
|
||||
|
||||
if self.vel_y() < 0 {
|
||||
|
@ -109,11 +109,11 @@ pub trait PhysicalEntity {
|
|||
}
|
||||
|
||||
// floor
|
||||
if ((self.x() - self.hit_bounds().right as isize) < (x * 16 + bounds_x) * 0x200)
|
||||
&& ((self.x() + self.hit_bounds().right as isize) > (x * 16 - bounds_x) * 0x200)
|
||||
&& ((self.y() + self.hit_bounds().bottom as isize) > ((y * 16 - 8) * 0x200))
|
||||
&& ((self.y() + self.hit_bounds().bottom as isize) < (y * 16 * 0x200)) {
|
||||
self.set_y(((y * 16 - 8) * 0x200) - self.hit_bounds().bottom as isize);
|
||||
if ((self.x() - self.hit_bounds().right as i32) < (x * 16 + bounds_x) * 0x200)
|
||||
&& ((self.x() + self.hit_bounds().right as i32) > (x * 16 - bounds_x) * 0x200)
|
||||
&& ((self.y() + self.hit_bounds().bottom as i32) > ((y * 16 - 8) * 0x200))
|
||||
&& ((self.y() + self.hit_bounds().bottom as i32) < (y * 16 * 0x200)) {
|
||||
self.set_y(((y * 16 - 8) * 0x200) - self.hit_bounds().bottom as i32);
|
||||
|
||||
if self.is_player() {
|
||||
if self.vel_y() > 0x400 {
|
||||
|
@ -132,17 +132,17 @@ pub trait PhysicalEntity {
|
|||
}
|
||||
|
||||
// upper left slope (bigger half)
|
||||
fn judge_hit_triangle_a(&mut self, state: &mut SharedGameState, x: isize, y: isize) {
|
||||
fn judge_hit_triangle_a(&mut self, state: &mut SharedGameState, x: i32, y: i32) {
|
||||
if self.x() < (x * 16 + 8) * 0x200
|
||||
&& self.x() > (x * 16 - 8) * 0x200
|
||||
&& (self.y() - self.hit_bounds().top as isize) < (y * 16 * 0x200) - (self.x() - x * 16 * 0x200) / 2 + 0x800
|
||||
&& (self.y() + self.hit_bounds().bottom as isize) > (y * 16 - 8) * 0x200 {
|
||||
self.set_y((y * 16 * 0x200) - ((self.x() - x * 16 * 0x200) / 2) + 0x800 + self.hit_bounds().top as isize);
|
||||
&& (self.y() - self.hit_bounds().top as i32) < (y * 16 * 0x200) - (self.x() - x * 16 * 0x200) / 2 + 0x800
|
||||
&& (self.y() + self.hit_bounds().bottom as i32) > (y * 16 - 8) * 0x200 {
|
||||
self.set_y((y * 16 * 0x200) - ((self.x() - x * 16 * 0x200) / 2) + 0x800 + self.hit_bounds().top as i32);
|
||||
|
||||
if self.is_player() && !self.cond().hidden() && self.vel_y() < -0x200 {
|
||||
state.sound_manager.play_sfx(3);
|
||||
state.create_caret(self.x(), self.y() - self.hit_bounds().top as isize, CaretType::LittleParticles, Direction::Left);
|
||||
state.create_caret(self.x(), self.y() - self.hit_bounds().top as isize, CaretType::LittleParticles, Direction::Left);
|
||||
state.create_caret(self.x(), self.y() - self.hit_bounds().top as i32, CaretType::LittleParticles, Direction::Left);
|
||||
state.create_caret(self.x(), self.y() - self.hit_bounds().top as i32, CaretType::LittleParticles, Direction::Left);
|
||||
}
|
||||
|
||||
if self.vel_y() < 0 {
|
||||
|
@ -154,17 +154,17 @@ pub trait PhysicalEntity {
|
|||
}
|
||||
|
||||
// upper left slope (smaller half)
|
||||
fn judge_hit_triangle_b(&mut self, state: &mut SharedGameState, x: isize, y: isize) {
|
||||
fn judge_hit_triangle_b(&mut self, state: &mut SharedGameState, x: i32, y: i32) {
|
||||
if self.x() < (x * 16 + 8) * 0x200
|
||||
&& self.x() > (x * 16 - 8) * 0x200
|
||||
&& (self.y() - self.hit_bounds().top as isize) < (y * 16 * 0x200) - (self.x() - x * 16 * 0x200) / 2 - 0x800
|
||||
&& (self.y() + self.hit_bounds().bottom as isize) > (y * 16 - 8) * 0x200 {
|
||||
self.set_y((y * 16 * 0x200) - ((self.x() - x * 16 * 0x200) / 2) - 0x800 + self.hit_bounds().top as isize);
|
||||
&& (self.y() - self.hit_bounds().top as i32) < (y * 16 * 0x200) - (self.x() - x * 16 * 0x200) / 2 - 0x800
|
||||
&& (self.y() + self.hit_bounds().bottom as i32) > (y * 16 - 8) * 0x200 {
|
||||
self.set_y((y * 16 * 0x200) - ((self.x() - x * 16 * 0x200) / 2) - 0x800 + self.hit_bounds().top as i32);
|
||||
|
||||
if self.is_player() && !self.cond().hidden() && self.vel_y() < -0x200 {
|
||||
state.sound_manager.play_sfx(3);
|
||||
state.create_caret(self.x(), self.y() - self.hit_bounds().top as isize, CaretType::LittleParticles, Direction::Left);
|
||||
state.create_caret(self.x(), self.y() - self.hit_bounds().top as isize, CaretType::LittleParticles, Direction::Left);
|
||||
state.create_caret(self.x(), self.y() - self.hit_bounds().top as i32, CaretType::LittleParticles, Direction::Left);
|
||||
state.create_caret(self.x(), self.y() - self.hit_bounds().top as i32, CaretType::LittleParticles, Direction::Left);
|
||||
}
|
||||
|
||||
if self.vel_y() < 0 {
|
||||
|
@ -176,17 +176,17 @@ pub trait PhysicalEntity {
|
|||
}
|
||||
|
||||
// upper right slope (smaller half)
|
||||
fn judge_hit_triangle_c(&mut self, state: &mut SharedGameState, x: isize, y: isize) {
|
||||
fn judge_hit_triangle_c(&mut self, state: &mut SharedGameState, x: i32, y: i32) {
|
||||
if self.x() < (x * 16 + 8) * 0x200
|
||||
&& self.x() > (x * 16 - 8) * 0x200
|
||||
&& (self.y() - self.hit_bounds().top as isize) < (y * 16 * 0x200) + (self.x() - x * 16 * 0x200) / 2 - 0x800
|
||||
&& (self.y() + self.hit_bounds().bottom as isize) > (y * 16 - 8) * 0x200 {
|
||||
self.set_y((y * 16 * 0x200) + ((self.x() - x * 16 * 0x200) / 2) - 0x800 + self.hit_bounds().top as isize);
|
||||
&& (self.y() - self.hit_bounds().top as i32) < (y * 16 * 0x200) + (self.x() - x * 16 * 0x200) / 2 - 0x800
|
||||
&& (self.y() + self.hit_bounds().bottom as i32) > (y * 16 - 8) * 0x200 {
|
||||
self.set_y((y * 16 * 0x200) + ((self.x() - x * 16 * 0x200) / 2) - 0x800 + self.hit_bounds().top as i32);
|
||||
|
||||
if self.is_player() && !self.cond().hidden() && self.vel_y() < -0x200 {
|
||||
state.sound_manager.play_sfx(3);
|
||||
state.create_caret(self.x(), self.y() - self.hit_bounds().top as isize, CaretType::LittleParticles, Direction::Left);
|
||||
state.create_caret(self.x(), self.y() - self.hit_bounds().top as isize, CaretType::LittleParticles, Direction::Left);
|
||||
state.create_caret(self.x(), self.y() - self.hit_bounds().top as i32, CaretType::LittleParticles, Direction::Left);
|
||||
state.create_caret(self.x(), self.y() - self.hit_bounds().top as i32, CaretType::LittleParticles, Direction::Left);
|
||||
}
|
||||
|
||||
if self.vel_y() < 0 {
|
||||
|
@ -198,17 +198,17 @@ pub trait PhysicalEntity {
|
|||
}
|
||||
|
||||
// upper right slope (bigger half)
|
||||
fn judge_hit_triangle_d(&mut self, state: &mut SharedGameState, x: isize, y: isize) {
|
||||
fn judge_hit_triangle_d(&mut self, state: &mut SharedGameState, x: i32, y: i32) {
|
||||
if (self.x() < (x * 16 + 8) * 0x200)
|
||||
&& (self.x() > (x * 16 - 8) * 0x200)
|
||||
&& (self.y() - self.hit_bounds().top as isize) < (y * 16 * 0x200) + (self.x() - x * 16 * 0x200) / 2 + 0x800
|
||||
&& (self.y() + self.hit_bounds().bottom as isize) > (y * 16 - 8) * 0x200 {
|
||||
self.set_y((y * 16 * 0x200) + ((self.x() - x * 16 * 0x200) / 2) + 0x800 + self.hit_bounds().top as isize);
|
||||
&& (self.y() - self.hit_bounds().top as i32) < (y * 16 * 0x200) + (self.x() - x * 16 * 0x200) / 2 + 0x800
|
||||
&& (self.y() + self.hit_bounds().bottom as i32) > (y * 16 - 8) * 0x200 {
|
||||
self.set_y((y * 16 * 0x200) + ((self.x() - x * 16 * 0x200) / 2) + 0x800 + self.hit_bounds().top as i32);
|
||||
|
||||
if self.is_player() && !self.cond().hidden() && self.vel_y() < -0x200 {
|
||||
state.sound_manager.play_sfx(3);
|
||||
state.create_caret(self.x(), self.y() - self.hit_bounds().top as isize, CaretType::LittleParticles, Direction::Left);
|
||||
state.create_caret(self.x(), self.y() - self.hit_bounds().top as isize, CaretType::LittleParticles, Direction::Left);
|
||||
state.create_caret(self.x(), self.y() - self.hit_bounds().top as i32, CaretType::LittleParticles, Direction::Left);
|
||||
state.create_caret(self.x(), self.y() - self.hit_bounds().top as i32, CaretType::LittleParticles, Direction::Left);
|
||||
}
|
||||
|
||||
if self.vel_y() < 0 {
|
||||
|
@ -220,14 +220,14 @@ pub trait PhysicalEntity {
|
|||
}
|
||||
|
||||
// lower left half (bigger)
|
||||
fn judge_hit_triangle_e(&mut self, state: &mut SharedGameState, x: isize, y: isize) {
|
||||
fn judge_hit_triangle_e(&mut self, state: &mut SharedGameState, x: i32, y: i32) {
|
||||
self.flags().set_hit_left_bigger_half(true);
|
||||
|
||||
if (self.x() < (x * 16 + 8) * 0x200)
|
||||
&& (self.x() > (x * 16 - 8) * 0x200)
|
||||
&& (self.y() + self.hit_bounds().bottom as isize) > (y * 16 * 0x200) + (self.x() - x * 16 * 0x200) / 2 - 0x800
|
||||
&& (self.y() - self.hit_bounds().top as isize) < (y * 16 + 8) * 0x200 {
|
||||
self.set_y((y * 16 * 0x200) + ((self.x() - x * 16 * 0x200) / 2) - 0x800 - self.hit_bounds().bottom as isize);
|
||||
&& (self.y() + self.hit_bounds().bottom as i32) > (y * 16 * 0x200) + (self.x() - x * 16 * 0x200) / 2 - 0x800
|
||||
&& (self.y() - self.hit_bounds().top as i32) < (y * 16 + 8) * 0x200 {
|
||||
self.set_y((y * 16 * 0x200) + ((self.x() - x * 16 * 0x200) / 2) - 0x800 - self.hit_bounds().bottom as i32);
|
||||
|
||||
if self.is_player() && self.vel_y() > 0x400 {
|
||||
state.sound_manager.play_sfx(23);
|
||||
|
@ -243,14 +243,14 @@ pub trait PhysicalEntity {
|
|||
}
|
||||
|
||||
// lower left half (smaller)
|
||||
fn judge_hit_triangle_f(&mut self, state: &mut SharedGameState, x: isize, y: isize) {
|
||||
fn judge_hit_triangle_f(&mut self, state: &mut SharedGameState, x: i32, y: i32) {
|
||||
self.flags().set_hit_left_smaller_half(true);
|
||||
|
||||
if (self.x() < (x * 16 + 8) * 0x200)
|
||||
&& (self.x() > (x * 16 - 8) * 0x200)
|
||||
&& (self.y() + self.hit_bounds().bottom as isize) > (y * 16 * 0x200) + (self.x() - x * 16 * 0x200) / 2 + 0x800
|
||||
&& (self.y() - self.hit_bounds().top as isize) < (y * 16 + 8) * 0x200 {
|
||||
self.set_y((y * 16 * 0x200) + ((self.x() - x * 16 * 0x200) / 2) + 0x800 - self.hit_bounds().bottom as isize);
|
||||
&& (self.y() + self.hit_bounds().bottom as i32) > (y * 16 * 0x200) + (self.x() - x * 16 * 0x200) / 2 + 0x800
|
||||
&& (self.y() - self.hit_bounds().top as i32) < (y * 16 + 8) * 0x200 {
|
||||
self.set_y((y * 16 * 0x200) + ((self.x() - x * 16 * 0x200) / 2) + 0x800 - self.hit_bounds().bottom as i32);
|
||||
|
||||
if self.is_player() && self.vel_y() > 0x400 {
|
||||
state.sound_manager.play_sfx(23);
|
||||
|
@ -266,14 +266,14 @@ pub trait PhysicalEntity {
|
|||
}
|
||||
|
||||
// lower right half (smaller)
|
||||
fn judge_hit_triangle_g(&mut self, state: &mut SharedGameState, x: isize, y: isize) {
|
||||
fn judge_hit_triangle_g(&mut self, state: &mut SharedGameState, x: i32, y: i32) {
|
||||
self.flags().set_hit_right_smaller_half(true);
|
||||
|
||||
if (self.x() < (x * 16 + 8) * 0x200)
|
||||
&& (self.x() > (x * 16 - 8) * 0x200)
|
||||
&& (self.y() + self.hit_bounds().bottom as isize) > (y * 16 * 0x200) - (self.x() - x * 16 * 0x200) / 2 + 0x800
|
||||
&& (self.y() - self.hit_bounds().top as isize) < (y * 16 + 8) * 0x200 {
|
||||
self.set_y((y * 16 * 0x200) - ((self.x() - x * 16 * 0x200) / 2) + 0x800 - self.hit_bounds().bottom as isize);
|
||||
&& (self.y() + self.hit_bounds().bottom as i32) > (y * 16 * 0x200) - (self.x() - x * 16 * 0x200) / 2 + 0x800
|
||||
&& (self.y() - self.hit_bounds().top as i32) < (y * 16 + 8) * 0x200 {
|
||||
self.set_y((y * 16 * 0x200) - ((self.x() - x * 16 * 0x200) / 2) + 0x800 - self.hit_bounds().bottom as i32);
|
||||
|
||||
if self.is_player() && self.vel_y() > 0x400 {
|
||||
state.sound_manager.play_sfx(23);
|
||||
|
@ -289,14 +289,14 @@ pub trait PhysicalEntity {
|
|||
}
|
||||
|
||||
// lower right half (bigger)
|
||||
fn judge_hit_triangle_h(&mut self, state: &mut SharedGameState, x: isize, y: isize) {
|
||||
fn judge_hit_triangle_h(&mut self, state: &mut SharedGameState, x: i32, y: i32) {
|
||||
self.flags().set_hit_right_bigger_half(true);
|
||||
|
||||
if (self.x() < (x * 16 + 8) * 0x200)
|
||||
&& (self.x() > (x * 16 - 8) * 0x200)
|
||||
&& (self.y() + self.hit_bounds().bottom as isize) > (y * 16 * 0x200) - (self.x() - x * 16 * 0x200) / 2 - 0x800
|
||||
&& (self.y() - self.hit_bounds().top as isize) < (y * 16 + 8) * 0x200 {
|
||||
self.set_y((y * 16 * 0x200) - ((self.x() - x * 16 * 0x200) / 2) - 0x800 - self.hit_bounds().bottom as isize);
|
||||
&& (self.y() + self.hit_bounds().bottom as i32) > (y * 16 * 0x200) - (self.x() - x * 16 * 0x200) / 2 - 0x800
|
||||
&& (self.y() - self.hit_bounds().top as i32) < (y * 16 + 8) * 0x200 {
|
||||
self.set_y((y * 16 * 0x200) - ((self.x() - x * 16 * 0x200) / 2) - 0x800 - self.hit_bounds().bottom as i32);
|
||||
|
||||
if self.is_player() && self.vel_y() > 0x400 {
|
||||
state.sound_manager.play_sfx(23);
|
||||
|
@ -311,19 +311,19 @@ pub trait PhysicalEntity {
|
|||
}
|
||||
}
|
||||
|
||||
fn judge_hit_water(&mut self, x: isize, y: isize) {
|
||||
fn judge_hit_water(&mut self, x: i32, y: i32) {
|
||||
let bounds_x = if self.is_player() { 5 } else { 6 };
|
||||
let bounds_up = if self.is_player() { 5 } else { 6 };
|
||||
let bounds_down = if self.is_player() { 0 } else { 6 };
|
||||
if (self.x() - self.hit_bounds().right as isize) < (x * 16 + bounds_x) * 0x200
|
||||
&& (self.x() + self.hit_bounds().right as isize) > (x * 16 - bounds_x) * 0x200
|
||||
&& (self.y() - self.hit_bounds().top as isize) < (y * 16 + bounds_up) * 0x200
|
||||
&& (self.y() + self.hit_bounds().bottom as isize) > (y * 16 - bounds_down) * 0x200 {
|
||||
if (self.x() - self.hit_bounds().right as i32) < (x * 16 + bounds_x) * 0x200
|
||||
&& (self.x() + self.hit_bounds().right as i32) > (x * 16 - bounds_x) * 0x200
|
||||
&& (self.y() - self.hit_bounds().top as i32) < (y * 16 + bounds_up) * 0x200
|
||||
&& (self.y() + self.hit_bounds().bottom as i32) > (y * 16 - bounds_down) * 0x200 {
|
||||
self.flags().set_in_water(true);
|
||||
}
|
||||
}
|
||||
|
||||
fn judge_hit_spike(&mut self, x: isize, y: isize, water: bool) {
|
||||
fn judge_hit_spike(&mut self, x: i32, y: i32, water: bool) {
|
||||
if (self.x() - 0x800) < (x * 16 + 4) * 0x200
|
||||
&& (self.x() + 0x800) > (x * 16 - 4) * 0x200
|
||||
&& (self.y() - 0x800) < (y * 16 + 3) * 0x200
|
||||
|
@ -335,11 +335,11 @@ pub trait PhysicalEntity {
|
|||
}
|
||||
}
|
||||
|
||||
fn judge_hit_force(&mut self, x: isize, y: isize, direction: Direction, water: bool) {
|
||||
if (self.x() - self.hit_bounds().left as isize) < (x * 16 + 6) * 0x200
|
||||
&& (self.x() + self.hit_bounds().right as isize) > (x * 16 - 6) * 0x200
|
||||
&& (self.y() - self.hit_bounds().top as isize) < (y * 16 + 6) * 0x200
|
||||
&& (self.y() + self.hit_bounds().bottom as isize) > (y * 16 - 6) * 0x200 {
|
||||
fn judge_hit_force(&mut self, x: i32, y: i32, direction: Direction, water: bool) {
|
||||
if (self.x() - self.hit_bounds().left as i32) < (x * 16 + 6) * 0x200
|
||||
&& (self.x() + self.hit_bounds().right as i32) > (x * 16 - 6) * 0x200
|
||||
&& (self.y() - self.hit_bounds().top as i32) < (y * 16 + 6) * 0x200
|
||||
&& (self.y() + self.hit_bounds().bottom as i32) > (y * 16 - 6) * 0x200 {
|
||||
match direction {
|
||||
Direction::Left => self.flags().set_force_left(true),
|
||||
Direction::Up => self.flags().set_force_up(true),
|
||||
|
|
|
@ -51,14 +51,14 @@ impl TargetPlayer {
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct Player {
|
||||
pub x: isize,
|
||||
pub y: isize,
|
||||
pub vel_x: isize,
|
||||
pub vel_y: isize,
|
||||
pub target_x: isize,
|
||||
pub target_y: isize,
|
||||
pub prev_x: isize,
|
||||
pub prev_y: isize,
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
pub vel_x: i32,
|
||||
pub vel_y: i32,
|
||||
pub target_x: i32,
|
||||
pub target_y: i32,
|
||||
pub prev_x: i32,
|
||||
pub prev_y: i32,
|
||||
pub life: u16,
|
||||
pub max_life: u16,
|
||||
pub cond: Condition,
|
||||
|
@ -69,7 +69,7 @@ pub struct Player {
|
|||
pub hit_bounds: Rect<usize>,
|
||||
pub control_mode: ControlMode,
|
||||
pub question: bool,
|
||||
pub booster_fuel: usize,
|
||||
pub booster_fuel: u32,
|
||||
pub up: bool,
|
||||
pub down: bool,
|
||||
pub shock_counter: u8,
|
||||
|
@ -81,8 +81,8 @@ pub struct Player {
|
|||
pub appearance: PlayerAppearance,
|
||||
pub controller: Box<dyn PlayerController>,
|
||||
weapon_offset_y: i8,
|
||||
index_x: isize,
|
||||
index_y: isize,
|
||||
index_x: i32,
|
||||
index_y: i32,
|
||||
splash: bool,
|
||||
booster_switch: u8,
|
||||
bubble: u8,
|
||||
|
@ -193,7 +193,7 @@ impl Player {
|
|||
self.booster_switch = 0;
|
||||
|
||||
if state.settings.infinite_booster {
|
||||
self.booster_fuel = usize::MAX;
|
||||
self.booster_fuel = u32::MAX;
|
||||
} else if self.equip.has_booster_0_8() || self.equip.has_booster_2_0() {
|
||||
self.booster_fuel = state.constants.booster.fuel;
|
||||
} else {
|
||||
|
@ -398,7 +398,7 @@ impl Player {
|
|||
self.vel_y -= 0x20;
|
||||
|
||||
if self.booster_fuel % 3 == 0 {
|
||||
state.create_caret(self.x, self.y + self.hit_bounds.bottom as isize / 2, CaretType::Exhaust, Direction::Bottom);
|
||||
state.create_caret(self.x, self.y + self.hit_bounds.bottom as i32 / 2, CaretType::Exhaust, Direction::Bottom);
|
||||
state.sound_manager.play_sfx(113);
|
||||
}
|
||||
|
||||
|
@ -448,15 +448,15 @@ impl Player {
|
|||
droplet.direction = if self.flags.water_splash_facing_right() { Direction::Right } else { Direction::Left };
|
||||
|
||||
for _ in 0..7 {
|
||||
droplet.x = self.x + (state.game_rng.range(-8..8) * 0x200) as isize;
|
||||
droplet.x = self.x + (state.game_rng.range(-8..8) * 0x200) as i32;
|
||||
droplet.vel_x = if vertical_splash {
|
||||
(self.vel_x + state.game_rng.range(-0x200..0x200) as isize) - (self.vel_x / 2)
|
||||
(self.vel_x + state.game_rng.range(-0x200..0x200) as i32) - (self.vel_x / 2)
|
||||
} else if horizontal_splash {
|
||||
self.vel_x + state.game_rng.range(-0x200..0x200) as isize
|
||||
self.vel_x + state.game_rng.range(-0x200..0x200) as i32
|
||||
} else {
|
||||
0 as isize
|
||||
0 as i32
|
||||
};
|
||||
droplet.vel_y = state.game_rng.range(-0x200..0x80) as isize;
|
||||
droplet.vel_y = state.game_rng.range(-0x200..0x80) as i32;
|
||||
|
||||
let _ = npc_list.spawn(0x100, droplet.clone());
|
||||
}
|
||||
|
@ -616,7 +616,7 @@ impl Player {
|
|||
self.anim_rect.bottom += offset;
|
||||
}
|
||||
|
||||
pub fn damage(&mut self, hp: isize, state: &mut SharedGameState, npc_list: &NPCList) {
|
||||
pub fn damage(&mut self, hp: i32, state: &mut SharedGameState, npc_list: &NPCList) {
|
||||
if state.settings.god_mode || self.shock_counter > 0 {
|
||||
return;
|
||||
}
|
||||
|
@ -648,8 +648,8 @@ impl Player {
|
|||
let mut npc = NPC::create(4, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
for _ in 0..0x40 {
|
||||
npc.x = self.x + state.game_rng.range(-10..10) as isize * 0x200;
|
||||
npc.y = self.y + state.game_rng.range(-10..10) as isize * 0x200;
|
||||
npc.x = self.x + state.game_rng.range(-10..10) as i32 * 0x200;
|
||||
npc.y = self.y + state.game_rng.range(-10..10) as i32 * 0x200;
|
||||
|
||||
let _ = npc_list.spawn(0x100, npc.clone());
|
||||
}
|
||||
|
@ -694,11 +694,11 @@ impl GameEntity<&NPCList> for Player {
|
|||
{
|
||||
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 isize - frame.prev_x,
|
||||
self.x - self.display_bounds.left as isize - frame.x,
|
||||
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 isize - frame.prev_y,
|
||||
self.y - self.display_bounds.left as isize - frame.y,
|
||||
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,
|
||||
);
|
||||
|
@ -710,22 +710,22 @@ impl GameEntity<&NPCList> for Player {
|
|||
match self.direction {
|
||||
Direction::Left => {
|
||||
batch.add_rect(
|
||||
interpolate_fix9_scale(self.prev_x - self.display_bounds.left as isize - frame.prev_x,
|
||||
self.x - self.display_bounds.left as isize - frame.x,
|
||||
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) - 8.0,
|
||||
interpolate_fix9_scale(self.prev_y - self.display_bounds.left as isize - frame.prev_y,
|
||||
self.y - self.display_bounds.left as isize - frame.y,
|
||||
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.weapon_offset_y as f32,
|
||||
&self.weapon_rect,
|
||||
);
|
||||
}
|
||||
Direction::Right => {
|
||||
batch.add_rect(
|
||||
interpolate_fix9_scale(self.prev_x - self.display_bounds.left as isize - frame.prev_x,
|
||||
self.x - self.display_bounds.left as isize - frame.x,
|
||||
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 isize - frame.prev_y,
|
||||
self.y - self.display_bounds.left as isize - frame.y,
|
||||
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.weapon_offset_y as f32,
|
||||
&self.weapon_rect,
|
||||
);
|
||||
|
|
|
@ -14,22 +14,22 @@ use crate::shared_game_state::SharedGameState;
|
|||
|
||||
impl PhysicalEntity for Player {
|
||||
#[inline(always)]
|
||||
fn x(&self) -> isize {
|
||||
fn x(&self) -> i32 {
|
||||
self.x
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn y(&self) -> isize {
|
||||
fn y(&self) -> i32 {
|
||||
self.y
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn vel_x(&self) -> isize {
|
||||
fn vel_x(&self) -> i32 {
|
||||
self.vel_x
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn vel_y(&self) -> isize {
|
||||
fn vel_y(&self) -> i32 {
|
||||
self.vel_y
|
||||
}
|
||||
|
||||
|
@ -43,22 +43,22 @@ impl PhysicalEntity for Player {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn set_x(&mut self, x: isize) {
|
||||
fn set_x(&mut self, x: i32) {
|
||||
self.x = x;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn set_y(&mut self, y: isize) {
|
||||
fn set_y(&mut self, y: i32) {
|
||||
self.y = y;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn set_vel_x(&mut self, vel_x: isize) {
|
||||
fn set_vel_x(&mut self, vel_x: i32) {
|
||||
self.vel_x = vel_x;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn set_vel_y(&mut self, vel_y: isize) {
|
||||
fn set_vel_y(&mut self, vel_y: i32) {
|
||||
self.vel_y = vel_y;
|
||||
}
|
||||
|
||||
|
@ -95,10 +95,10 @@ impl Player {
|
|||
fn judge_hit_npc_solid_soft(&mut self, npc: &NPC) -> Flag {
|
||||
let mut flags = Flag(0);
|
||||
|
||||
if ((self.y - self.hit_bounds.top as isize) < (npc.y + npc.hit_bounds.bottom as isize - 3 * 0x200))
|
||||
&& ((self.y + self.hit_bounds.top as isize) > (npc.y - npc.hit_bounds.bottom as isize + 3 * 0x200))
|
||||
&& ((self.x - self.hit_bounds.right as isize) < (npc.x + npc.hit_bounds.right as isize))
|
||||
&& ((self.x - self.hit_bounds.right as isize) > npc.x) {
|
||||
if ((self.y - self.hit_bounds.top as i32) < (npc.y + npc.hit_bounds.bottom as i32 - 3 * 0x200))
|
||||
&& ((self.y + self.hit_bounds.top as i32) > (npc.y - npc.hit_bounds.bottom as i32 + 3 * 0x200))
|
||||
&& ((self.x - self.hit_bounds.right as i32) < (npc.x + npc.hit_bounds.right as i32))
|
||||
&& ((self.x - self.hit_bounds.right as i32) > npc.x) {
|
||||
if self.vel_x < 0x200 {
|
||||
self.vel_x += 0x200;
|
||||
}
|
||||
|
@ -106,10 +106,10 @@ impl Player {
|
|||
flags.set_hit_left_wall(true);
|
||||
}
|
||||
|
||||
if ((self.y - self.hit_bounds.top as isize) < (npc.y + npc.hit_bounds.bottom as isize - 3 * 0x200))
|
||||
&& ((self.y + self.hit_bounds.top as isize) > (npc.y - npc.hit_bounds.bottom as isize + 3 * 0x200))
|
||||
&& ((self.x + self.hit_bounds.right as isize - 0x200) > (npc.x - npc.hit_bounds.right as isize))
|
||||
&& ((self.x + self.hit_bounds.right as isize - 0x200) < npc.x) {
|
||||
if ((self.y - self.hit_bounds.top as i32) < (npc.y + npc.hit_bounds.bottom as i32 - 3 * 0x200))
|
||||
&& ((self.y + self.hit_bounds.top as i32) > (npc.y - npc.hit_bounds.bottom as i32 + 3 * 0x200))
|
||||
&& ((self.x + self.hit_bounds.right as i32 - 0x200) > (npc.x - npc.hit_bounds.right as i32))
|
||||
&& ((self.x + self.hit_bounds.right as i32 - 0x200) < npc.x) {
|
||||
if self.vel_x > -0x200 {
|
||||
self.vel_x -= 0x200;
|
||||
}
|
||||
|
@ -118,10 +118,10 @@ impl Player {
|
|||
}
|
||||
|
||||
|
||||
if ((self.x - self.hit_bounds.right as isize) < (npc.x + npc.hit_bounds.right as isize - 3 * 0x200))
|
||||
&& ((self.x + self.hit_bounds.right as isize) > (npc.x - npc.hit_bounds.right as isize + 3 * 0x200))
|
||||
&& ((self.y - self.hit_bounds.top as isize) < (npc.y + npc.hit_bounds.bottom as isize))
|
||||
&& ((self.y - self.hit_bounds.top as isize) > npc.y) {
|
||||
if ((self.x - self.hit_bounds.right as i32) < (npc.x + npc.hit_bounds.right as i32 - 3 * 0x200))
|
||||
&& ((self.x + self.hit_bounds.right as i32) > (npc.x - npc.hit_bounds.right as i32 + 3 * 0x200))
|
||||
&& ((self.y - self.hit_bounds.top as i32) < (npc.y + npc.hit_bounds.bottom as i32))
|
||||
&& ((self.y - self.hit_bounds.top as i32) > npc.y) {
|
||||
if self.vel_y < 0 {
|
||||
self.vel_y = 0;
|
||||
}
|
||||
|
@ -129,15 +129,15 @@ impl Player {
|
|||
flags.set_hit_top_wall(true);
|
||||
}
|
||||
|
||||
if ((self.x - self.hit_bounds.right as isize) < (npc.x + npc.hit_bounds.right as isize - 3 * 0x200))
|
||||
&& ((self.x + self.hit_bounds.right as isize) > (npc.x - npc.hit_bounds.right as isize + 3 * 0x200))
|
||||
&& ((self.y + self.hit_bounds.bottom as isize - 0x200) > (npc.y - npc.hit_bounds.top as isize))
|
||||
&& ((self.y + self.hit_bounds.bottom as isize - 0x200) < (npc.y + 3 * 0x200)) {
|
||||
if ((self.x - self.hit_bounds.right as i32) < (npc.x + npc.hit_bounds.right as i32 - 3 * 0x200))
|
||||
&& ((self.x + self.hit_bounds.right as i32) > (npc.x - npc.hit_bounds.right as i32 + 3 * 0x200))
|
||||
&& ((self.y + self.hit_bounds.bottom as i32 - 0x200) > (npc.y - npc.hit_bounds.top as i32))
|
||||
&& ((self.y + self.hit_bounds.bottom as i32 - 0x200) < (npc.y + 3 * 0x200)) {
|
||||
if npc.npc_flags.bouncy() {
|
||||
self.vel_y = npc.vel_y - 0x200;
|
||||
flags.set_hit_bottom_wall(true);
|
||||
} else if !self.flags.hit_bottom_wall() && self.vel_y > npc.vel_y {
|
||||
self.y = npc.y - npc.hit_bounds.top as isize - self.hit_bounds.bottom as isize + 0x200;
|
||||
self.y = npc.y - npc.hit_bounds.top as i32 - self.hit_bounds.bottom as i32 + 0x200;
|
||||
self.vel_y = npc.vel_y;
|
||||
self.x += npc.vel_x;
|
||||
flags.set_hit_bottom_wall(true);
|
||||
|
@ -160,58 +160,58 @@ impl Player {
|
|||
let fx2 = if fx2 == 0.0 { 1.0 } else { fx2 };
|
||||
|
||||
if fy1 / fx1 <= fy2 / fx2 {
|
||||
if (self.y - self.hit_bounds.top as isize) < (npc.y + npc.hit_bounds.bottom as isize)
|
||||
&& (self.y + self.hit_bounds.bottom as isize) > (npc.y - npc.hit_bounds.top as isize) {
|
||||
if (self.x - self.hit_bounds.right as isize) < (npc.x + npc.hit_bounds.right as isize)
|
||||
&& (self.x - self.hit_bounds.right as isize) > npc.x {
|
||||
if (self.y - self.hit_bounds.top as i32) < (npc.y + npc.hit_bounds.bottom as i32)
|
||||
&& (self.y + self.hit_bounds.bottom as i32) > (npc.y - npc.hit_bounds.top as i32) {
|
||||
if (self.x - self.hit_bounds.right as i32) < (npc.x + npc.hit_bounds.right as i32)
|
||||
&& (self.x - self.hit_bounds.right as i32) > npc.x {
|
||||
if self.vel_x < npc.vel_x {
|
||||
self.vel_x = npc.vel_x;
|
||||
}
|
||||
|
||||
self.x = npc.x + npc.hit_bounds.right as isize + self.hit_bounds.right as isize;
|
||||
self.x = npc.x + npc.hit_bounds.right as i32 + self.hit_bounds.right as i32;
|
||||
flags.set_hit_left_wall(true);
|
||||
}
|
||||
|
||||
if (self.x + self.hit_bounds.right as isize) > (npc.x - npc.hit_bounds.right as isize)
|
||||
&& (self.x + self.hit_bounds.right as isize) < npc.x {
|
||||
if (self.x + self.hit_bounds.right as i32) > (npc.x - npc.hit_bounds.right as i32)
|
||||
&& (self.x + self.hit_bounds.right as i32) < npc.x {
|
||||
if self.vel_x > npc.vel_x {
|
||||
self.vel_x = npc.vel_x;
|
||||
}
|
||||
|
||||
self.x = npc.x - npc.hit_bounds.right as isize - self.hit_bounds.right as isize;
|
||||
self.x = npc.x - npc.hit_bounds.right as i32 - self.hit_bounds.right as i32;
|
||||
flags.set_hit_right_wall(true);
|
||||
}
|
||||
}
|
||||
} else if (self.x - self.hit_bounds.right as isize) < (npc.x + npc.hit_bounds.right as isize)
|
||||
&& (self.x + self.hit_bounds.right as isize) > (npc.x - npc.hit_bounds.right as isize) {
|
||||
if (self.y - self.hit_bounds.top as isize) < (npc.y + npc.hit_bounds.bottom as isize)
|
||||
&& (self.y - self.hit_bounds.top as isize) > npc.y {
|
||||
} else if (self.x - self.hit_bounds.right as i32) < (npc.x + npc.hit_bounds.right as i32)
|
||||
&& (self.x + self.hit_bounds.right as i32) > (npc.x - npc.hit_bounds.right as i32) {
|
||||
if (self.y - self.hit_bounds.top as i32) < (npc.y + npc.hit_bounds.bottom as i32)
|
||||
&& (self.y - self.hit_bounds.top as i32) > npc.y {
|
||||
if self.vel_y >= npc.vel_y {
|
||||
if self.vel_y < 0 {
|
||||
self.vel_y = 0;
|
||||
}
|
||||
} else {
|
||||
self.y = npc.y + npc.hit_bounds.bottom as isize + self.hit_bounds.top as isize + 0x200;
|
||||
self.y = npc.y + npc.hit_bounds.bottom as i32 + self.hit_bounds.top as i32 + 0x200;
|
||||
self.vel_y = npc.vel_y;
|
||||
}
|
||||
|
||||
flags.set_hit_top_wall(true);
|
||||
}
|
||||
|
||||
if (self.y + self.hit_bounds.bottom as isize) > (npc.y - npc.hit_bounds.top as isize)
|
||||
&& (self.y + self.hit_bounds.bottom as isize) < (npc.y + 3 * 0x200) {
|
||||
if (self.y + self.hit_bounds.bottom as i32) > (npc.y - npc.hit_bounds.top as i32)
|
||||
&& (self.y + self.hit_bounds.bottom as i32) < (npc.y + 3 * 0x200) {
|
||||
if self.vel_y - npc.vel_y > 2 * 0x200 {
|
||||
state.sound_manager.play_sfx(23);
|
||||
}
|
||||
|
||||
if self.control_mode == ControlMode::IronHead {
|
||||
self.y = npc.y - npc.hit_bounds.top as isize - self.hit_bounds.bottom as isize + 0x200;
|
||||
self.y = npc.y - npc.hit_bounds.top as i32 - self.hit_bounds.bottom as i32 + 0x200;
|
||||
flags.set_hit_bottom_wall(true);
|
||||
} else if npc.npc_flags.bouncy() {
|
||||
self.vel_y = npc.vel_y - 0x200;
|
||||
flags.set_hit_bottom_wall(true);
|
||||
} else if !self.flags.hit_bottom_wall() && self.vel_y > npc.vel_y {
|
||||
self.y = npc.y - npc.hit_bounds.top as isize - self.hit_bounds.bottom as isize + 0x200;
|
||||
self.y = npc.y - npc.hit_bounds.top as i32 - self.hit_bounds.bottom as i32 + 0x200;
|
||||
self.vel_y = npc.vel_y;
|
||||
self.x += npc.vel_x;
|
||||
|
||||
|
@ -225,13 +225,13 @@ impl Player {
|
|||
|
||||
fn judge_hit_npc_non_solid(&mut self, npc: &NPC) -> Flag {
|
||||
let mut flags = Flag(0);
|
||||
let hit_left = if npc.direction == Direction::Left { npc.hit_bounds.left } else { npc.hit_bounds.right } as isize;
|
||||
let hit_right = if npc.direction == Direction::Left { npc.hit_bounds.right } else { npc.hit_bounds.left } as isize;
|
||||
let hit_left = if npc.direction == Direction::Left { npc.hit_bounds.left } else { npc.hit_bounds.right } as i32;
|
||||
let hit_right = if npc.direction == Direction::Left { npc.hit_bounds.right } else { npc.hit_bounds.left } as i32;
|
||||
|
||||
if self.x + (2 * 0x200) > npc.x - hit_left
|
||||
&& self.x - (2 * 0x200) < npc.x + hit_right
|
||||
&& self.y + (2 * 0x200) > npc.y - npc.hit_bounds.top as isize
|
||||
&& self.y - (2 * 0x200) < npc.y + npc.hit_bounds.bottom as isize {
|
||||
&& self.y + (2 * 0x200) > npc.y - npc.hit_bounds.top as i32
|
||||
&& self.y - (2 * 0x200) < npc.y + npc.hit_bounds.bottom as i32 {
|
||||
flags.set_hit_left_wall(true);
|
||||
}
|
||||
|
||||
|
@ -316,10 +316,10 @@ impl Player {
|
|||
|| flags.hit_right_wall() && npc.vel_x < 0
|
||||
|| flags.hit_top_wall() && npc.vel_y > 0
|
||||
|| flags.hit_bottom_wall() && npc.vel_y < 0 {
|
||||
self.damage(npc.damage as isize, state, npc_list);
|
||||
self.damage(npc.damage as i32, state, npc_list);
|
||||
}
|
||||
} else if flags.0 != 0 && npc.damage != 0 && !state.control_flags.interactions_disabled() {
|
||||
self.damage(npc.damage as isize, state, npc_list);
|
||||
self.damage(npc.damage as i32, state, npc_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,8 +96,8 @@ impl GameProfile {
|
|||
|
||||
game_scene.player1.equip.0 = self.equipment as u16;
|
||||
|
||||
game_scene.player1.x = self.pos_x as isize;
|
||||
game_scene.player1.y = self.pos_y as isize;
|
||||
game_scene.player1.x = self.pos_x;
|
||||
game_scene.player1.y = self.pos_y;
|
||||
|
||||
game_scene.player1.control_mode = if self.control_mode == 1 { ControlMode::IronHead } else { ControlMode::Normal };
|
||||
game_scene.player1.direction = self.direction;
|
||||
|
|
|
@ -32,7 +32,7 @@ use crate::ui::Components;
|
|||
use crate::weapon::WeaponType;
|
||||
|
||||
pub struct GameScene {
|
||||
pub tick: usize,
|
||||
pub tick: u32,
|
||||
pub stage: Stage,
|
||||
pub boss_life_bar: BossLifeBar,
|
||||
pub stage_select: StageSelect,
|
||||
|
@ -180,9 +180,9 @@ impl GameScene {
|
|||
BackgroundType::OutsideWind | BackgroundType::Outside => {
|
||||
graphics::clear(ctx, Color::from_rgb(0, 0, 0));
|
||||
|
||||
let offset = (self.tick % 640) as isize;
|
||||
let offset = (self.tick % 640) as i32;
|
||||
|
||||
for x in (0..(state.canvas_size.0 as isize)).step_by(200) {
|
||||
for x in (0..(state.canvas_size.0 as i32)).step_by(200) {
|
||||
batch.add_rect(x as f32, 0.0,
|
||||
&Rect::new_size(0, 0, 200, 88));
|
||||
}
|
||||
|
@ -190,22 +190,22 @@ impl GameScene {
|
|||
batch.add_rect(state.canvas_size.0 - 320.0, 0.0,
|
||||
&Rect::new_size(0, 0, 320, 88));
|
||||
|
||||
for x in ((-offset / 2)..(state.canvas_size.0 as isize)).step_by(320) {
|
||||
for x in ((-offset / 2)..(state.canvas_size.0 as i32)).step_by(320) {
|
||||
batch.add_rect(x as f32, 88.0,
|
||||
&Rect::new_size(0, 88, 320, 35));
|
||||
}
|
||||
|
||||
for x in ((-offset % 320)..(state.canvas_size.0 as isize)).step_by(320) {
|
||||
for x in ((-offset % 320)..(state.canvas_size.0 as i32)).step_by(320) {
|
||||
batch.add_rect(x as f32, 123.0,
|
||||
&Rect::new_size(0, 123, 320, 23));
|
||||
}
|
||||
|
||||
for x in ((-offset * 2)..(state.canvas_size.0 as isize)).step_by(320) {
|
||||
for x in ((-offset * 2)..(state.canvas_size.0 as i32)).step_by(320) {
|
||||
batch.add_rect(x as f32, 146.0,
|
||||
&Rect::new_size(0, 146, 320, 30));
|
||||
}
|
||||
|
||||
for x in ((-offset * 4)..(state.canvas_size.0 as isize)).step_by(320) {
|
||||
for x in ((-offset * 4)..(state.canvas_size.0 as i32)).step_by(320) {
|
||||
batch.add_rect(x as f32, 176.0,
|
||||
&Rect::new_size(0, 176, 320, 64));
|
||||
}
|
||||
|
@ -219,36 +219,36 @@ impl GameScene {
|
|||
|
||||
fn draw_bullets(&self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
||||
let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "Bullet")?;
|
||||
let mut x: isize;
|
||||
let mut y: isize;
|
||||
let mut prev_x: isize;
|
||||
let mut prev_y: isize;
|
||||
let mut x: i32;
|
||||
let mut y: i32;
|
||||
let mut prev_x: i32;
|
||||
let mut prev_y: i32;
|
||||
|
||||
for bullet in self.bullet_manager.bullets.iter() {
|
||||
match bullet.direction {
|
||||
Direction::Left => {
|
||||
x = bullet.x - bullet.display_bounds.left as isize;
|
||||
y = bullet.y - bullet.display_bounds.top as isize;
|
||||
prev_x = bullet.prev_x - bullet.display_bounds.left as isize;
|
||||
prev_y = bullet.prev_y - bullet.display_bounds.top as isize;
|
||||
x = bullet.x - bullet.display_bounds.left as i32;
|
||||
y = bullet.y - bullet.display_bounds.top as i32;
|
||||
prev_x = bullet.prev_x - bullet.display_bounds.left as i32;
|
||||
prev_y = bullet.prev_y - bullet.display_bounds.top as i32;
|
||||
}
|
||||
Direction::Up => {
|
||||
x = bullet.x - bullet.display_bounds.top as isize;
|
||||
y = bullet.y - bullet.display_bounds.left as isize;
|
||||
prev_x = bullet.prev_x - bullet.display_bounds.top as isize;
|
||||
prev_y = bullet.prev_y - bullet.display_bounds.left as isize;
|
||||
x = bullet.x - bullet.display_bounds.top as i32;
|
||||
y = bullet.y - bullet.display_bounds.left as i32;
|
||||
prev_x = bullet.prev_x - bullet.display_bounds.top as i32;
|
||||
prev_y = bullet.prev_y - bullet.display_bounds.left as i32;
|
||||
}
|
||||
Direction::Right => {
|
||||
x = bullet.x - bullet.display_bounds.right as isize;
|
||||
y = bullet.y - bullet.display_bounds.top as isize;
|
||||
prev_x = bullet.prev_x - bullet.display_bounds.right as isize;
|
||||
prev_y = bullet.prev_y - bullet.display_bounds.top as isize;
|
||||
x = bullet.x - bullet.display_bounds.right as i32;
|
||||
y = bullet.y - bullet.display_bounds.top as i32;
|
||||
prev_x = bullet.prev_x - bullet.display_bounds.right as i32;
|
||||
prev_y = bullet.prev_y - bullet.display_bounds.top as i32;
|
||||
}
|
||||
Direction::Bottom => {
|
||||
x = bullet.x - bullet.display_bounds.top as isize;
|
||||
y = bullet.y - bullet.display_bounds.right as isize;
|
||||
prev_x = bullet.prev_x - bullet.display_bounds.top as isize;
|
||||
prev_y = bullet.prev_y - bullet.display_bounds.right as isize;
|
||||
x = bullet.x - bullet.display_bounds.top as i32;
|
||||
y = bullet.y - bullet.display_bounds.right as i32;
|
||||
prev_x = bullet.prev_x - bullet.display_bounds.top as i32;
|
||||
prev_y = bullet.prev_y - bullet.display_bounds.right as i32;
|
||||
}
|
||||
Direction::FacingPlayer => unreachable!(),
|
||||
}
|
||||
|
@ -297,14 +297,14 @@ impl GameScene {
|
|||
FadeDirection::Left | FadeDirection::Right => {
|
||||
let mut frame = tick;
|
||||
|
||||
for x in (0..(state.canvas_size.0 as isize + 16)).step_by(16) {
|
||||
for x in (0..(state.canvas_size.0 as i32 + 16)).step_by(16) {
|
||||
if frame > 15 { frame = 15; } else { frame += 1; }
|
||||
|
||||
if frame >= 0 {
|
||||
rect.left = frame as u16 * 16;
|
||||
rect.right = rect.left + 16;
|
||||
|
||||
for y in (0..(state.canvas_size.1 as isize + 16)).step_by(16) {
|
||||
for y in (0..(state.canvas_size.1 as i32 + 16)).step_by(16) {
|
||||
if direction == FadeDirection::Left {
|
||||
batch.add_rect(state.canvas_size.0 - x as f32, y as f32, &rect);
|
||||
} else {
|
||||
|
@ -317,14 +317,14 @@ impl GameScene {
|
|||
FadeDirection::Up | FadeDirection::Down => {
|
||||
let mut frame = tick;
|
||||
|
||||
for y in (0..(state.canvas_size.1 as isize + 16)).step_by(16) {
|
||||
for y in (0..(state.canvas_size.1 as i32 + 16)).step_by(16) {
|
||||
if frame > 15 { frame = 15; } else { frame += 1; }
|
||||
|
||||
if frame >= 0 {
|
||||
rect.left = frame as u16 * 16;
|
||||
rect.right = rect.left + 16;
|
||||
|
||||
for x in (0..(state.canvas_size.0 as isize + 16)).step_by(16) {
|
||||
for x in (0..(state.canvas_size.0 as i32 + 16)).step_by(16) {
|
||||
if direction == FadeDirection::Down {
|
||||
batch.add_rect(x as f32, y as f32, &rect);
|
||||
} else {
|
||||
|
@ -335,8 +335,8 @@ impl GameScene {
|
|||
}
|
||||
}
|
||||
FadeDirection::Center => {
|
||||
let center_x = (state.canvas_size.0 / 2.0 - 8.0) as isize;
|
||||
let center_y = (state.canvas_size.1 / 2.0 - 8.0) as isize;
|
||||
let center_x = (state.canvas_size.0 / 2.0 - 8.0) as i32;
|
||||
let center_y = (state.canvas_size.1 / 2.0 - 8.0) as i32;
|
||||
let mut start_frame = tick;
|
||||
|
||||
for x in (0..(center_x + 16)).step_by(16) {
|
||||
|
@ -534,10 +534,10 @@ impl GameScene {
|
|||
}
|
||||
|
||||
for npc in self.npc_list.iter_alive() {
|
||||
if npc.cond.hidden() || (npc.x < (self.frame.x - 128 * 0x200 - npc.display_bounds.width() as isize * 0x200)
|
||||
|| npc.x > (self.frame.x + 128 * 0x200 + (state.canvas_size.0 as isize + npc.display_bounds.width() as isize) * 0x200)
|
||||
&& npc.y < (self.frame.y - 128 * 0x200 - npc.display_bounds.height() as isize * 0x200)
|
||||
|| npc.y > (self.frame.y + 128 * 0x200 + (state.canvas_size.1 as isize + npc.display_bounds.height() as isize) * 0x200)) {
|
||||
if npc.cond.hidden() || (npc.x < (self.frame.x - 128 * 0x200 - npc.display_bounds.width() as i32 * 0x200)
|
||||
|| npc.x > (self.frame.x + 128 * 0x200 + (state.canvas_size.0 as i32 + npc.display_bounds.width() as i32) * 0x200)
|
||||
&& npc.y < (self.frame.y - 128 * 0x200 - npc.display_bounds.height() as i32 * 0x200)
|
||||
|| npc.y > (self.frame.y + 128 * 0x200 + (state.canvas_size.1 as i32 + npc.display_bounds.height() as i32) * 0x200)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -670,10 +670,10 @@ impl GameScene {
|
|||
// cheap, clones a reference underneath
|
||||
let mut tmp_batch = SpriteBatch::new(state.tmp_canvas.image().clone());
|
||||
|
||||
let tile_start_x = clamp(self.frame.x / 0x200 / 16, 0, self.stage.map.width as isize) as usize;
|
||||
let tile_start_y = clamp(self.frame.y / 0x200 / 16, 0, self.stage.map.height as isize) as usize;
|
||||
let tile_end_x = clamp((self.frame.x / 0x200 + 8 + state.canvas_size.0 as isize) / 16 + 1, 0, self.stage.map.width as isize) as usize;
|
||||
let tile_end_y = clamp((self.frame.y / 0x200 + 8 + state.canvas_size.1 as isize) / 16 + 1, 0, self.stage.map.height as isize) as usize;
|
||||
let tile_start_x = clamp(self.frame.x / 0x200 / 16, 0, self.stage.map.width as i32) as usize;
|
||||
let tile_start_y = clamp(self.frame.y / 0x200 / 16, 0, self.stage.map.height as i32) as usize;
|
||||
let tile_end_x = clamp((self.frame.x / 0x200 + 8 + state.canvas_size.0 as i32) / 16 + 1, 0, self.stage.map.width as i32) as usize;
|
||||
let tile_end_y = clamp((self.frame.y / 0x200 + 8 + state.canvas_size.1 as i32) / 16 + 1, 0, self.stage.map.height as i32) as usize;
|
||||
let mut rect = Rect {
|
||||
left: 0.0,
|
||||
top: 0.0,
|
||||
|
@ -683,12 +683,14 @@ impl GameScene {
|
|||
|
||||
for y in tile_start_y..tile_end_y {
|
||||
for x in tile_start_x..tile_end_x {
|
||||
let tile = self.stage.map.attrib[*self.stage.map.tiles
|
||||
.get((y * self.stage.map.width) + x)
|
||||
.unwrap() as usize];
|
||||
let tile_above = self.stage.map.attrib[*self.stage.map.tiles
|
||||
.get((y.saturating_sub(1) * self.stage.map.width) + x)
|
||||
.unwrap() as usize];
|
||||
let tile = unsafe {
|
||||
self.stage.map.attrib[*self.stage.map.tiles
|
||||
.get_unchecked((y * self.stage.map.width as usize) + x) as usize]
|
||||
};
|
||||
let tile_above = unsafe {
|
||||
self.stage.map.attrib[*self.stage.map.tiles
|
||||
.get_unchecked((y.saturating_sub(1) * self.stage.map.width as usize) + x) as usize]
|
||||
};
|
||||
|
||||
if !self.is_water(tile) {
|
||||
continue;
|
||||
|
@ -733,10 +735,10 @@ impl GameScene {
|
|||
let mut rect = Rect::new(0, 0, 16, 16);
|
||||
let (frame_x, frame_y) = self.frame.xy_interpolated(state.frame_time, state.scale);
|
||||
|
||||
let tile_start_x = clamp(self.frame.x / 0x200 / 16, 0, self.stage.map.width as isize) as usize;
|
||||
let tile_start_y = clamp(self.frame.y / 0x200 / 16, 0, self.stage.map.height as isize) as usize;
|
||||
let tile_end_x = clamp((self.frame.x / 0x200 + 8 + state.canvas_size.0 as isize) / 16 + 1, 0, self.stage.map.width as isize) as usize;
|
||||
let tile_end_y = clamp((self.frame.y / 0x200 + 8 + state.canvas_size.1 as isize) / 16 + 1, 0, self.stage.map.height as isize) as usize;
|
||||
let tile_start_x = clamp(frame_x as i32 / 16, 0, self.stage.map.width as i32) as usize;
|
||||
let tile_start_y = clamp(frame_y as i32 / 16, 0, self.stage.map.height as i32) as usize;
|
||||
let tile_end_x = clamp((frame_x as i32 + 8 + state.canvas_size.0 as i32) / 16 + 1, 0, self.stage.map.width as i32) as usize;
|
||||
let tile_end_y = clamp((frame_y as i32 + 8 + state.canvas_size.1 as i32) / 16 + 1, 0, self.stage.map.height as i32) as usize;
|
||||
|
||||
if layer == TileLayer::Snack {
|
||||
rect = state.constants.world.snack_rect;
|
||||
|
@ -745,7 +747,7 @@ impl GameScene {
|
|||
for y in tile_start_y..tile_end_y {
|
||||
for x in tile_start_x..tile_end_x {
|
||||
let tile = *self.stage.map.tiles
|
||||
.get((y * self.stage.map.width) + x)
|
||||
.get((y * self.stage.map.width as usize) + x)
|
||||
.unwrap();
|
||||
|
||||
match layer {
|
||||
|
@ -874,16 +876,16 @@ impl GameScene {
|
|||
|
||||
let hit = (
|
||||
npc.npc_flags.shootable()
|
||||
&& (npc.x - npc.hit_bounds.right as isize) < (bullet.x + bullet.enemy_hit_width as isize)
|
||||
&& (npc.x + npc.hit_bounds.right as isize) > (bullet.x - bullet.enemy_hit_width as isize)
|
||||
&& (npc.y - npc.hit_bounds.top as isize) < (bullet.y + bullet.enemy_hit_height as isize)
|
||||
&& (npc.y + npc.hit_bounds.bottom as isize) > (bullet.y - bullet.enemy_hit_height as isize)
|
||||
&& (npc.x - npc.hit_bounds.right as i32) < (bullet.x + bullet.enemy_hit_width as i32)
|
||||
&& (npc.x + npc.hit_bounds.right as i32) > (bullet.x - bullet.enemy_hit_width as i32)
|
||||
&& (npc.y - npc.hit_bounds.top as i32) < (bullet.y + bullet.enemy_hit_height as i32)
|
||||
&& (npc.y + npc.hit_bounds.bottom as i32) > (bullet.y - bullet.enemy_hit_height as i32)
|
||||
) || (
|
||||
npc.npc_flags.invulnerable()
|
||||
&& (npc.x - npc.hit_bounds.right as isize) < (bullet.x + bullet.hit_bounds.right as isize)
|
||||
&& (npc.x + npc.hit_bounds.right as isize) > (bullet.x - bullet.hit_bounds.left as isize)
|
||||
&& (npc.y - npc.hit_bounds.top as isize) < (bullet.y + bullet.hit_bounds.bottom as isize)
|
||||
&& (npc.y + npc.hit_bounds.bottom as isize) > (bullet.y - bullet.hit_bounds.top as isize)
|
||||
&& (npc.x - npc.hit_bounds.right as i32) < (bullet.x + bullet.hit_bounds.right as i32)
|
||||
&& (npc.x + npc.hit_bounds.right as i32) > (bullet.x - bullet.hit_bounds.left as i32)
|
||||
&& (npc.y - npc.hit_bounds.top as i32) < (bullet.y + bullet.hit_bounds.bottom as i32)
|
||||
&& (npc.y + npc.hit_bounds.bottom as i32) > (bullet.y - bullet.hit_bounds.top as i32)
|
||||
);
|
||||
|
||||
if !hit {
|
||||
|
@ -1070,10 +1072,10 @@ impl GameScene {
|
|||
}
|
||||
|
||||
fn draw_debug_npc(&self, npc: &NPC, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
||||
if npc.x < (self.frame.x - 128 - npc.display_bounds.width() as isize * 0x200)
|
||||
|| npc.x > (self.frame.x + 128 + (state.canvas_size.0 as isize + npc.display_bounds.width() as isize) * 0x200)
|
||||
&& npc.y < (self.frame.y - 128 - npc.display_bounds.height() as isize * 0x200)
|
||||
|| npc.y > (self.frame.y + 128 + (state.canvas_size.1 as isize + npc.display_bounds.height() as isize) * 0x200) {
|
||||
if npc.x < (self.frame.x - 128 - npc.display_bounds.width() as i32 * 0x200)
|
||||
|| npc.x > (self.frame.x + 128 + (state.canvas_size.0 as i32 + npc.display_bounds.width() as i32) * 0x200)
|
||||
&& npc.y < (self.frame.y - 128 - npc.display_bounds.height() as i32 * 0x200)
|
||||
|| npc.y > (self.frame.y + 128 + (state.canvas_size.1 as i32 + npc.display_bounds.height() as i32) * 0x200) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
@ -1231,6 +1233,10 @@ impl Scene for GameScene {
|
|||
}
|
||||
|
||||
TextScriptVM::run(state, self, ctx)?;
|
||||
|
||||
#[cfg(feature = "scripting")]
|
||||
state.lua.scene_tick(self);
|
||||
|
||||
self.tick = self.tick.wrapping_add(1);
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1286,10 +1292,10 @@ impl Scene for GameScene {
|
|||
|
||||
self.boss.draw(state, ctx, &self.frame)?;
|
||||
for npc in self.npc_list.iter_alive() {
|
||||
if npc.x < (self.frame.x - 128 * 0x200 - npc.display_bounds.width() as isize * 0x200)
|
||||
|| npc.x > (self.frame.x + 128 * 0x200 + (state.canvas_size.0 as isize + npc.display_bounds.width() as isize) * 0x200)
|
||||
&& npc.y < (self.frame.y - 128 * 0x200 - npc.display_bounds.height() as isize * 0x200)
|
||||
|| npc.y > (self.frame.y + 128 * 0x200 + (state.canvas_size.1 as isize + npc.display_bounds.height() as isize) * 0x200) {
|
||||
if npc.x < (self.frame.x - 128 * 0x200 - npc.display_bounds.width() as i32 * 0x200)
|
||||
|| npc.x > (self.frame.x + 128 * 0x200 + (state.canvas_size.0 as i32 + npc.display_bounds.width() as i32) * 0x200)
|
||||
&& npc.y < (self.frame.y - 128 * 0x200 - npc.display_bounds.height() as i32 * 0x200)
|
||||
|| npc.y > (self.frame.y + 128 * 0x200 + (state.canvas_size.1 as i32 + npc.display_bounds.height() as i32) * 0x200) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1333,7 +1339,7 @@ impl Scene for GameScene {
|
|||
state.font.draw_colored_text(P2_LEFT_TEXT.chars(),
|
||||
8.0, y,
|
||||
(96, 96, 255, 255), &state.constants, &mut state.texture_set, ctx)?;
|
||||
} else if self.player2.x - 8 * 0x200 > self.frame.x + state.canvas_size.0 as isize * 0x200 {
|
||||
} else if self.player2.x - 8 * 0x200 > self.frame.x + state.canvas_size.0 as i32 * 0x200 {
|
||||
let width = state.font.text_width(P2_RIGHT_TEXT.chars(), &state.constants);
|
||||
|
||||
state.font.draw_colored_text(P2_RIGHT_TEXT.chars(),
|
||||
|
|
|
@ -13,6 +13,8 @@ use crate::input::touch_controls::TouchControlType;
|
|||
enum CurrentMenu {
|
||||
MainMenu,
|
||||
OptionMenu,
|
||||
SaveSelectMenu,
|
||||
ChallengesMenu,
|
||||
StartGame,
|
||||
LoadGame,
|
||||
}
|
||||
|
@ -23,6 +25,7 @@ pub struct TitleScene {
|
|||
current_menu: CurrentMenu,
|
||||
main_menu: Menu,
|
||||
option_menu: Menu,
|
||||
save_select_menu: Menu,
|
||||
}
|
||||
|
||||
impl TitleScene {
|
||||
|
@ -31,8 +34,9 @@ impl TitleScene {
|
|||
tick: 0,
|
||||
controller: CombinedMenuController::new(),
|
||||
current_menu: CurrentMenu::MainMenu,
|
||||
main_menu: Menu::new(0, 0, 100, 1 * 14 + 6),
|
||||
option_menu: Menu::new(0, 0, 180, 1 * 14 + 6),
|
||||
main_menu: Menu::new(0, 0, 100, 0),
|
||||
option_menu: Menu::new(0, 0, 180, 0),
|
||||
save_select_menu: Menu::new(0, 0, 200, 0),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,9 +97,12 @@ impl Scene for TitleScene {
|
|||
self.main_menu.push_entry(MenuEntry::Active("New game".to_string()));
|
||||
self.main_menu.push_entry(MenuEntry::Active("Load game".to_string()));
|
||||
self.main_menu.push_entry(MenuEntry::Active("Options".to_string()));
|
||||
self.main_menu.push_entry(MenuEntry::Disabled("Editor".to_string()));
|
||||
if cfg!(feature = "editor") {
|
||||
self.main_menu.push_entry(MenuEntry::Active("Editor".to_string()));
|
||||
} else {
|
||||
self.main_menu.push_entry(MenuEntry::Hidden);
|
||||
}
|
||||
self.main_menu.push_entry(MenuEntry::Active("Quit".to_string()));
|
||||
self.main_menu.height = self.main_menu.entries.len() as u16 * 14 + 6;
|
||||
|
||||
self.option_menu.push_entry(MenuEntry::Toggle("Original timing (50TPS)".to_string(), state.timing_mode == TimingMode::_50Hz));
|
||||
self.option_menu.push_entry(MenuEntry::Toggle("Lighting effects".to_string(), state.settings.shader_effects));
|
||||
|
@ -113,7 +120,12 @@ impl Scene for TitleScene {
|
|||
self.option_menu.push_entry(MenuEntry::Active("Join our Discord".to_string()));
|
||||
self.option_menu.push_entry(MenuEntry::Disabled(DISCORD_LINK.to_owned()));
|
||||
self.option_menu.push_entry(MenuEntry::Active("Back".to_string()));
|
||||
self.option_menu.height = self.option_menu.entries.len() as u16 * 14 + 6;
|
||||
|
||||
self.save_select_menu.push_entry(MenuEntry::NewSave);
|
||||
self.save_select_menu.push_entry(MenuEntry::NewSave);
|
||||
self.save_select_menu.push_entry(MenuEntry::NewSave);
|
||||
self.save_select_menu.push_entry(MenuEntry::Active("Delete a save".to_string()));
|
||||
self.save_select_menu.push_entry(MenuEntry::Active("Back".to_string()));
|
||||
|
||||
self.controller.update(state, ctx)?;
|
||||
self.controller.update_trigger();
|
||||
|
@ -126,9 +138,11 @@ impl Scene for TitleScene {
|
|||
self.controller.update(state, ctx)?;
|
||||
self.controller.update_trigger();
|
||||
|
||||
self.main_menu.update_height();
|
||||
self.main_menu.x = ((state.canvas_size.0 - self.main_menu.width as f32) / 2.0).floor() as isize;
|
||||
self.main_menu.y = ((state.canvas_size.1 + 70.0 - self.main_menu.height as f32) / 2.0).floor() as isize;
|
||||
|
||||
self.option_menu.update_height();
|
||||
self.option_menu.x = ((state.canvas_size.0 - self.option_menu.width as f32) / 2.0).floor() as isize;
|
||||
self.option_menu.y = ((state.canvas_size.1 + 70.0 - self.option_menu.height as f32) / 2.0).floor() as isize;
|
||||
|
||||
|
@ -212,6 +226,7 @@ impl Scene for TitleScene {
|
|||
state.load_or_start_game(ctx)?;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.tick += 1;
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
doukutsu = {}
|
||||
|
||||
doukutsu._registered = {
|
||||
tick = {},
|
||||
}
|
||||
|
||||
doukutsu._handlers = setmetatable({
|
||||
tick = function(scene)
|
||||
for _, h in pairs(doukutsu._registered.tick) do
|
||||
pcall(h, scene)
|
||||
end
|
||||
end,
|
||||
}, {
|
||||
__index = function(self, event)
|
||||
error("Unknown event: " .. event)
|
||||
end,
|
||||
})
|
||||
|
||||
doukutsu._initialize_script = function(script)
|
||||
-- for compatibility with Lua 5.2+, copy-pasted from Lua mailing list
|
||||
-- http://lua-users.org/lists/lua-l/2010-06/msg00313.html
|
||||
local _setfenv = setfenv or function(f, t)
|
||||
f = (type(f) == 'function' and f or debug.getinfo(f + 1, 'f').func)
|
||||
local name
|
||||
local up = 0
|
||||
repeat
|
||||
up = up + 1
|
||||
name = debug.getupvalue(f, up)
|
||||
until name == '_ENV' or name == nil
|
||||
if name then
|
||||
|
||||
debug.upvaluejoin(f, up, function()
|
||||
return name
|
||||
end, 1)
|
||||
debug.setupvalue(f, up, t)
|
||||
end
|
||||
end
|
||||
|
||||
global_copy = {}
|
||||
for k, v in pairs(_G) do
|
||||
global_copy[k] = v
|
||||
end
|
||||
|
||||
_setfenv(script, global_copy)
|
||||
script()
|
||||
end
|
||||
|
||||
doukutsu.play_sfx = function(id)
|
||||
__doukutsu:play_sfx(id)
|
||||
end
|
||||
|
||||
doukutsu.play_song = function(id)
|
||||
__doukutsu:play_song(id)
|
||||
end
|
||||
|
||||
doukutsu.on = function(event, handler)
|
||||
assert(type(event) == "string", "event type must be a string.")
|
||||
assert(type(handler) == "function", "event handler must be a function.")
|
||||
|
||||
if doukutsu._registered[event] == nil then
|
||||
error("Unknown event: " .. event)
|
||||
end
|
||||
|
||||
table.insert(doukutsu._registered[event], handler)
|
||||
|
||||
return handler
|
||||
end
|
||||
|
||||
doukutsu.remove_handler = function(event, handler)
|
||||
assert(type(event) == "string", "event type must be a string.")
|
||||
assert(type(handler) == "function", "event handler must be a function.")
|
||||
|
||||
if doukutsu._registered[event] == nil then
|
||||
error("Unknown event: " .. event)
|
||||
end
|
||||
|
||||
local index = -1
|
||||
for i, h in pairs(doukutsu._registered[event]) do
|
||||
if handler == h then
|
||||
index = i
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if index ~= -1 then
|
||||
table.remove(doukutsu._registered[event], index)
|
||||
end
|
||||
|
||||
return handler
|
||||
end
|
|
@ -0,0 +1,64 @@
|
|||
use lua_ffi::ffi::luaL_Reg;
|
||||
use lua_ffi::{LuaObject, State, c_int};
|
||||
|
||||
use crate::scene::game_scene::GameScene;
|
||||
use crate::scripting::LuaScriptingState;
|
||||
use crate::shared_game_state::SharedGameState;
|
||||
|
||||
pub struct Doukutsu {
|
||||
pub ptr: *mut LuaScriptingState,
|
||||
}
|
||||
|
||||
impl Doukutsu {
|
||||
pub fn new(ptr: *mut LuaScriptingState) -> Doukutsu {
|
||||
Doukutsu {
|
||||
ptr,
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn lua_play_sfx(&self, state: &mut State) -> c_int {
|
||||
if let Some(index) = state.to_int(2) {
|
||||
let game_state = &mut (*(*self.ptr).state_ptr);
|
||||
|
||||
game_state.sound_manager.play_sfx(index as u8);
|
||||
}
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
unsafe fn lua_play_song(&self, state: &mut State) -> c_int {
|
||||
if let Some(index) = state.to_int(2) {
|
||||
let game_state = &mut (*(*self.ptr).state_ptr);
|
||||
let ctx = &mut (*(*self.ptr).ctx_ptr);
|
||||
|
||||
game_state.sound_manager.play_song(index as usize, &game_state.constants, ctx);
|
||||
}
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
unsafe fn lua_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));
|
||||
} else {
|
||||
state.push_nil();
|
||||
}
|
||||
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
impl LuaObject for Doukutsu {
|
||||
fn name() -> *const i8 {
|
||||
c_str!("Doukutsu")
|
||||
}
|
||||
|
||||
fn lua_fns() -> Vec<luaL_Reg> {
|
||||
vec![
|
||||
lua_method!("play_sfx", Doukutsu, Doukutsu::lua_play_sfx),
|
||||
lua_method!("play_song", Doukutsu, Doukutsu::lua_play_song),
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
use std::io::{Read, Seek};
|
||||
use std::ptr::null_mut;
|
||||
|
||||
use ggez::{Context, filesystem, GameError, GameResult};
|
||||
use ggez::filesystem::File;
|
||||
use lua_ffi::{c_int, LuaFunction, LuaObject, State, ThreadStatus};
|
||||
use lua_ffi::ffi::lua_pushcfunction;
|
||||
|
||||
use crate::scene::game_scene::GameScene;
|
||||
use crate::scripting::doukutsu::Doukutsu;
|
||||
use crate::shared_game_state::SharedGameState;
|
||||
|
||||
mod doukutsu;
|
||||
mod player;
|
||||
mod scene;
|
||||
|
||||
pub struct LuaScriptingState {
|
||||
state: Option<State>,
|
||||
state_ptr: *mut SharedGameState,
|
||||
ctx_ptr: *mut Context,
|
||||
game_scene: *mut GameScene,
|
||||
}
|
||||
|
||||
pub static REF_ERROR: &str = "Reference went out of scope. DO NOT store/use references to game objects outside the event.";
|
||||
|
||||
static BOOT_SCRIPT: &str = include_str!("boot.lua");
|
||||
|
||||
fn check_status(status: ThreadStatus, state: &mut State) -> GameResult {
|
||||
match status {
|
||||
ThreadStatus::Ok | ThreadStatus::Yield => { return Ok(()); }
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let error = state.to_str(-1).unwrap_or("???");
|
||||
match status {
|
||||
ThreadStatus::RuntimeError => Err(GameError::EventLoopError(format!("Lua Runtime Error: {}", error))),
|
||||
ThreadStatus::SyntaxError => Err(GameError::EventLoopError(format!("Lua Syntax Error: {}", error))),
|
||||
ThreadStatus::MemoryError => Err(GameError::EventLoopError(format!("Lua Memory Error: {}", error))),
|
||||
ThreadStatus::MsgHandlerError => Err(GameError::EventLoopError(format!("Lua Message Handler Error: {}", error))),
|
||||
ThreadStatus::FileError => Err(GameError::EventLoopError(format!("Lua File Error: {}", error))),
|
||||
_ => Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn print(state: &mut State) -> c_int {
|
||||
if let Some(msg) = state.to_str(1) {
|
||||
log::info!("[Lua] {}", msg);
|
||||
}
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
impl LuaScriptingState {
|
||||
pub fn new() -> LuaScriptingState {
|
||||
LuaScriptingState {
|
||||
state: None,
|
||||
state_ptr: null_mut(),
|
||||
ctx_ptr: null_mut(),
|
||||
game_scene: null_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_refs(&mut self, state: *mut SharedGameState, ctx: *mut Context) {
|
||||
self.state_ptr = state;
|
||||
self.ctx_ptr = ctx;
|
||||
}
|
||||
|
||||
fn load_script(mut state: &mut State, path: &str, mut script: File) -> bool {
|
||||
let mut buf = Vec::with_capacity(1024);
|
||||
let res = script.read_to_end(&mut buf);
|
||||
|
||||
if let Err(err) = res {
|
||||
log::warn!("Error reading script {}: {}", path, err);
|
||||
return false;
|
||||
}
|
||||
|
||||
let name = format!("@{}", path);
|
||||
let res = state.load_buffer(&buf, &name);
|
||||
let res = check_status(res, &mut state);
|
||||
if let Err(err) = res {
|
||||
log::warn!("Error loading script {}: {}", path, err);
|
||||
return false;
|
||||
}
|
||||
|
||||
state.get_global("doukutsu");
|
||||
state.get_field(-1, "_initialize_script");
|
||||
state.push_value(-3);
|
||||
|
||||
let res = state.pcall(1, 0, 0);
|
||||
if let Err((_, err)) = res {
|
||||
log::warn!("Error evaluating script {}: {}", path, err);
|
||||
return false;
|
||||
}
|
||||
|
||||
log::info!("Successfully loaded Lua script: {}", path);
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
pub fn reload_scripts(&mut self, ctx: &mut Context) -> GameResult {
|
||||
let mut state = State::new();
|
||||
state.open_libs();
|
||||
|
||||
state.push(lua_fn!(print));
|
||||
state.set_global("print");
|
||||
|
||||
state.push(Doukutsu { ptr: self as *mut LuaScriptingState });
|
||||
state.set_global("__doukutsu");
|
||||
|
||||
let res = state.do_string(BOOT_SCRIPT);
|
||||
check_status(res, &mut state)?;
|
||||
|
||||
if filesystem::exists(ctx, "/scripts/") {
|
||||
let mut script_count = 0;
|
||||
let mut files = filesystem::read_dir(ctx, "/scripts/")?
|
||||
.filter(|f| f.to_string_lossy().to_lowercase().ends_with(".lua"));
|
||||
|
||||
for file in files {
|
||||
let path = file.clone();
|
||||
|
||||
match filesystem::open(ctx, file) {
|
||||
Ok(script) => {
|
||||
if LuaScriptingState::load_script(&mut state, path.to_string_lossy().as_ref(), script) {
|
||||
script_count += 1;
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
log::warn!("Error opening script {:?}: {}", path, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if script_count > 0 {
|
||||
log::info!("{} Lua scripts have been loaded.", script_count);
|
||||
}
|
||||
}
|
||||
|
||||
self.state = Some(state);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
use lua_ffi::{c_int, LuaObject, State};
|
||||
use lua_ffi::ffi::luaL_Reg;
|
||||
|
||||
use crate::inventory::Inventory;
|
||||
use crate::player::Player;
|
||||
use crate::scripting::REF_ERROR;
|
||||
use crate::weapon::WeaponType;
|
||||
|
||||
pub struct LuaPlayer {
|
||||
valid_reference: bool,
|
||||
plr_ptr: *mut Player,
|
||||
inv_ptr: *mut Inventory,
|
||||
}
|
||||
|
||||
impl LuaPlayer {
|
||||
fn check_ref(&self, state: &mut State) -> bool {
|
||||
if !self.valid_reference {
|
||||
state.error(REF_ERROR);
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn lua_get_x(&self, state: &mut State) -> c_int {
|
||||
if self.check_ref(state) { return 0; }
|
||||
|
||||
unsafe {
|
||||
state.push((*self.plr_ptr).x);
|
||||
}
|
||||
|
||||
1
|
||||
}
|
||||
|
||||
fn lua_get_y(&self, state: &mut State) -> c_int {
|
||||
if self.check_ref(state) { return 0; }
|
||||
|
||||
unsafe {
|
||||
state.push((*self.plr_ptr).y);
|
||||
}
|
||||
|
||||
1
|
||||
}
|
||||
|
||||
fn lua_get_vel_x(&self, state: &mut State) -> c_int {
|
||||
if self.check_ref(state) { return 0; }
|
||||
|
||||
unsafe {
|
||||
state.push((*self.plr_ptr).vel_x);
|
||||
}
|
||||
|
||||
1
|
||||
}
|
||||
|
||||
fn lua_get_vel_y(&self, state: &mut State) -> c_int {
|
||||
if self.check_ref(state) { return 0; }
|
||||
|
||||
unsafe {
|
||||
state.push((*self.plr_ptr).vel_y);
|
||||
}
|
||||
|
||||
1
|
||||
}
|
||||
|
||||
fn lua_set_vel_x(&self, state: &mut State) -> c_int {
|
||||
if self.check_ref(state) { return 0; }
|
||||
|
||||
unsafe {
|
||||
if let Some(vel_x) = state.to_int(2) {
|
||||
(*self.plr_ptr).vel_x = vel_x;
|
||||
}
|
||||
}
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
fn lua_set_vel_y(&self, state: &mut State) -> c_int {
|
||||
if self.check_ref(state) { return 0; }
|
||||
|
||||
unsafe {
|
||||
if let Some(vel_y) = state.to_int(2) {
|
||||
(*self.plr_ptr).vel_y = vel_y;
|
||||
}
|
||||
}
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
fn lua_get_weapon_ammo(&self, state: &mut State) -> c_int {
|
||||
if self.check_ref(state) { return 0; }
|
||||
|
||||
if let Some(index) = state.to_int(2) {} else {
|
||||
state.error("Weapon type must be a number");
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
if let Some(weap) = (*self.inv_ptr).get_weapon_by_type_mut(WeaponType::PolarStar) {}
|
||||
}
|
||||
|
||||
1
|
||||
}
|
||||
|
||||
pub(crate) fn new(plr_ptr: *mut Player, inv_ptr: *mut Inventory) -> LuaPlayer {
|
||||
LuaPlayer {
|
||||
valid_reference: true,
|
||||
plr_ptr,
|
||||
inv_ptr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for LuaPlayer {
|
||||
fn drop(&mut self) {
|
||||
self.valid_reference = false;
|
||||
}
|
||||
}
|
||||
|
||||
impl LuaObject for LuaPlayer {
|
||||
fn name() -> *const i8 {
|
||||
c_str!("Player")
|
||||
}
|
||||
|
||||
fn lua_fns() -> Vec<luaL_Reg> {
|
||||
vec![
|
||||
lua_method!("x", LuaPlayer, LuaPlayer::lua_get_x),
|
||||
lua_method!("y", LuaPlayer, LuaPlayer::lua_get_y),
|
||||
lua_method!("vel_x", LuaPlayer, LuaPlayer::lua_get_vel_x),
|
||||
lua_method!("vel_y", LuaPlayer, LuaPlayer::lua_get_vel_y),
|
||||
lua_method!("set_vel_x", LuaPlayer, LuaPlayer::lua_set_vel_x),
|
||||
lua_method!("set_vel_y", LuaPlayer, LuaPlayer::lua_set_vel_y),
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
use lua_ffi::{c_int, LuaObject, State};
|
||||
use lua_ffi::ffi::luaL_Reg;
|
||||
|
||||
use crate::inventory::Inventory;
|
||||
use crate::player::Player;
|
||||
use crate::scene::game_scene::GameScene;
|
||||
use crate::scripting::LuaScriptingState;
|
||||
use crate::scripting::player::LuaPlayer;
|
||||
|
||||
pub struct LuaGameScene {
|
||||
valid_reference: bool,
|
||||
ptr: *mut GameScene,
|
||||
}
|
||||
|
||||
impl LuaGameScene {
|
||||
unsafe fn lua_get_tick(&self, state: &mut State) -> c_int {
|
||||
state.push((*self.ptr).tick as u32);
|
||||
|
||||
1
|
||||
}
|
||||
|
||||
unsafe fn lua_get_player(&self, state: &mut State) -> c_int {
|
||||
if let Some(index) = state.to_int(2) {
|
||||
let (player_ref, inv_ref) = match index {
|
||||
0 => (&mut (*self.ptr).player1, &mut (*self.ptr).inventory_player1),
|
||||
1 => (&mut (*self.ptr).player2, &mut (*self.ptr).inventory_player2),
|
||||
_ => {
|
||||
state.error("Player index out of range!");
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
state.push(LuaPlayer::new(player_ref as *mut Player, inv_ref as *mut Inventory));
|
||||
1
|
||||
} else {
|
||||
state.error("Player index must be a number.");
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn new(ptr: *mut GameScene) -> LuaGameScene {
|
||||
LuaGameScene {
|
||||
valid_reference: true,
|
||||
ptr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for LuaGameScene {
|
||||
fn drop(&mut self) {
|
||||
self.valid_reference = false;
|
||||
}
|
||||
}
|
||||
|
||||
impl LuaObject for LuaGameScene {
|
||||
fn name() -> *const i8 {
|
||||
c_str!("GameScene")
|
||||
}
|
||||
|
||||
fn lua_fns() -> Vec<luaL_Reg> {
|
||||
vec![
|
||||
lua_method!("tick", LuaGameScene, LuaGameScene::lua_get_tick),
|
||||
lua_method!("player", LuaGameScene, LuaGameScene::lua_get_player),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
impl LuaScriptingState {
|
||||
pub fn scene_tick(&mut self, game_scene: &mut GameScene) {
|
||||
self.game_scene = game_scene as *mut GameScene;
|
||||
|
||||
if let Some(state) = self.state.as_mut() {
|
||||
let val = LuaGameScene::new(self.game_scene);
|
||||
|
||||
state.get_global("doukutsu");
|
||||
state.get_field(-1, "_handlers");
|
||||
state.get_field(-1, "tick");
|
||||
|
||||
state.push(val);
|
||||
if let Err((_, err)) = state.pcall(1, 0, 0) {
|
||||
println!("scene_tick error: {}", err);
|
||||
}
|
||||
|
||||
state.pop(2);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,6 +18,8 @@ use crate::profile::GameProfile;
|
|||
use crate::rng::XorShift;
|
||||
use crate::scene::game_scene::GameScene;
|
||||
use crate::scene::Scene;
|
||||
#[cfg(feature = "scripting")]
|
||||
use crate::scripting::LuaScriptingState;
|
||||
use crate::settings::Settings;
|
||||
use crate::shaders::Shaders;
|
||||
use crate::sound::SoundManager;
|
||||
|
@ -96,7 +98,7 @@ pub struct SharedGameState {
|
|||
pub touch_controls: TouchControls,
|
||||
pub base_path: String,
|
||||
pub npc_table: NPCTable,
|
||||
pub npc_super_pos: (isize, isize),
|
||||
pub npc_super_pos: (i32, i32),
|
||||
pub stages: Vec<StageData>,
|
||||
pub frame_time: f64,
|
||||
pub scale: f32,
|
||||
|
@ -112,6 +114,8 @@ pub struct SharedGameState {
|
|||
pub constants: EngineConstants,
|
||||
pub font: BMFontRenderer,
|
||||
pub texture_set: TextureSet,
|
||||
#[cfg(feature = "scripting")]
|
||||
pub lua: LuaScriptingState,
|
||||
pub sound_manager: SoundManager,
|
||||
pub settings: Settings,
|
||||
pub shutdown: bool,
|
||||
|
@ -184,6 +188,8 @@ impl SharedGameState {
|
|||
constants,
|
||||
font,
|
||||
texture_set,
|
||||
#[cfg(feature = "scripting")]
|
||||
lua: LuaScriptingState::new(),
|
||||
sound_manager: SoundManager::new(ctx)?,
|
||||
settings,
|
||||
shutdown: false,
|
||||
|
@ -208,6 +214,9 @@ impl SharedGameState {
|
|||
self.fade_state = FadeState::Hidden;
|
||||
self.textscript_vm.state = TextScriptExecutionState::Running(200, 0);
|
||||
|
||||
#[cfg(feature = "scripting")]
|
||||
self.lua.reload_scripts(ctx)?;
|
||||
|
||||
self.next_scene = Some(Box::new(next_scene));
|
||||
|
||||
Ok(())
|
||||
|
@ -222,6 +231,9 @@ impl SharedGameState {
|
|||
self.fade_state = FadeState::Hidden;
|
||||
self.textscript_vm.state = TextScriptExecutionState::Running(100, 0);
|
||||
|
||||
#[cfg(feature = "scripting")]
|
||||
self.lua.reload_scripts(ctx)?;
|
||||
|
||||
self.next_scene = Some(Box::new(next_scene));
|
||||
|
||||
Ok(())
|
||||
|
@ -247,6 +259,9 @@ impl SharedGameState {
|
|||
|
||||
profile.apply(self, &mut next_scene, ctx);
|
||||
|
||||
#[cfg(feature = "scripting")]
|
||||
self.lua.reload_scripts(ctx)?;
|
||||
|
||||
self.next_scene = Some(Box::new(next_scene));
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -292,7 +307,7 @@ impl SharedGameState {
|
|||
self.carets.retain(|c| !c.is_dead());
|
||||
}
|
||||
|
||||
pub fn create_caret(&mut self, x: isize, y: isize, ctype: CaretType, direct: Direction) {
|
||||
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));
|
||||
}
|
||||
|
||||
|
|
|
@ -459,7 +459,7 @@ impl Stage {
|
|||
}
|
||||
|
||||
pub fn tile_at(&self, x: usize, y: usize) -> u8 {
|
||||
if let Some(&tile) = self.map.tiles.get(y * self.map.width + x) {
|
||||
if let Some(&tile) = self.map.tiles.get(y * self.map.width as usize + x) {
|
||||
tile
|
||||
} else {
|
||||
0
|
||||
|
@ -468,7 +468,7 @@ impl Stage {
|
|||
|
||||
/// Changes map tile. Returns true if smoke should be emitted
|
||||
pub fn change_tile(&mut self, x: usize, y: usize, tile_type: u8) -> bool {
|
||||
if let Some(ptr) = self.map.tiles.get_mut(y * self.map.width + x) {
|
||||
if let Some(ptr) = self.map.tiles.get_mut(y * self.map.width as usize + x) {
|
||||
if *ptr != tile_type {
|
||||
*ptr = tile_type;
|
||||
return true;
|
||||
|
|
|
@ -949,8 +949,8 @@ impl TextScriptVM {
|
|||
if game_scene.stage.change_tile(pos_x, pos_y, tile_type) {
|
||||
let mut npc = NPC::create(4, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
npc.x = pos_x as isize * 16 * 0x200;
|
||||
npc.y = pos_y as isize * 16 * 0x200;
|
||||
npc.x = pos_x as i32 * 16 * 0x200;
|
||||
npc.y = pos_y as i32 * 16 * 0x200;
|
||||
|
||||
game_scene.npc_list.spawn(0x100, npc.clone())?;
|
||||
game_scene.npc_list.spawn(0x100, npc)?;
|
||||
|
@ -1031,8 +1031,8 @@ impl TextScriptVM {
|
|||
OpCode::TRA => {
|
||||
let map_id = read_cur_varint(&mut cursor)? as usize;
|
||||
let event_num = read_cur_varint(&mut cursor)? as u16;
|
||||
let pos_x = read_cur_varint(&mut cursor)? as isize * 16 * 0x200;
|
||||
let pos_y = read_cur_varint(&mut cursor)? as isize * 16 * 0x200;
|
||||
let pos_x = read_cur_varint(&mut cursor)? as i32 * 16 * 0x200;
|
||||
let pos_y = read_cur_varint(&mut cursor)? as i32 * 16 * 0x200;
|
||||
|
||||
let mut new_scene = GameScene::new(state, ctx, map_id)?;
|
||||
new_scene.intro_mode = game_scene.intro_mode;
|
||||
|
@ -1064,8 +1064,8 @@ impl TextScriptVM {
|
|||
exec_state = TextScriptExecutionState::Running(event_num, 0);
|
||||
}
|
||||
OpCode::MOV => {
|
||||
let pos_x = read_cur_varint(&mut cursor)? as isize * 16 * 0x200;
|
||||
let pos_y = read_cur_varint(&mut cursor)? as isize * 16 * 0x200;
|
||||
let pos_x = read_cur_varint(&mut cursor)? as i32 * 16 * 0x200;
|
||||
let pos_y = read_cur_varint(&mut cursor)? as i32 * 16 * 0x200;
|
||||
|
||||
for player in [&mut game_scene.player1, &mut game_scene.player2].iter_mut() {
|
||||
player.vel_x = 0;
|
||||
|
@ -1177,7 +1177,7 @@ impl TextScriptVM {
|
|||
}
|
||||
OpCode::FOB => {
|
||||
let part_id = read_cur_varint(&mut cursor)? as u16;
|
||||
let ticks = read_cur_varint(&mut cursor)? as isize;
|
||||
let ticks = read_cur_varint(&mut cursor)? as i32;
|
||||
|
||||
game_scene.frame.wait = ticks;
|
||||
game_scene.frame.update_target = UpdateTarget::Boss(part_id);
|
||||
|
@ -1185,7 +1185,7 @@ impl TextScriptVM {
|
|||
exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32);
|
||||
}
|
||||
OpCode::FOM => {
|
||||
let ticks = read_cur_varint(&mut cursor)? as isize;
|
||||
let ticks = read_cur_varint(&mut cursor)? as i32;
|
||||
game_scene.frame.wait = ticks;
|
||||
game_scene.frame.update_target = UpdateTarget::Player;
|
||||
|
||||
|
@ -1193,7 +1193,7 @@ impl TextScriptVM {
|
|||
}
|
||||
OpCode::FON => {
|
||||
let event_num = read_cur_varint(&mut cursor)? as u16;
|
||||
let ticks = read_cur_varint(&mut cursor)? as isize;
|
||||
let ticks = read_cur_varint(&mut cursor)? as i32;
|
||||
game_scene.frame.wait = ticks;
|
||||
|
||||
for npc in game_scene.npc_list.iter() {
|
||||
|
@ -1312,8 +1312,8 @@ impl TextScriptVM {
|
|||
}
|
||||
OpCode::MNP => {
|
||||
let event_num = read_cur_varint(&mut cursor)? as u16;
|
||||
let x = read_cur_varint(&mut cursor)? as isize;
|
||||
let y = read_cur_varint(&mut cursor)? as isize;
|
||||
let x = read_cur_varint(&mut cursor)? as i32;
|
||||
let y = read_cur_varint(&mut cursor)? as i32;
|
||||
let tsc_direction = read_cur_varint(&mut cursor)? as usize;
|
||||
let direction = Direction::from_int_facing(tsc_direction).unwrap_or(Direction::Left);
|
||||
|
||||
|
@ -1341,8 +1341,8 @@ impl TextScriptVM {
|
|||
}
|
||||
OpCode::SNP => {
|
||||
let npc_type = read_cur_varint(&mut cursor)? as u16;
|
||||
let x = read_cur_varint(&mut cursor)? as isize;
|
||||
let y = read_cur_varint(&mut cursor)? as isize;
|
||||
let x = read_cur_varint(&mut cursor)? as i32;
|
||||
let y = read_cur_varint(&mut cursor)? as i32;
|
||||
let tsc_direction = read_cur_varint(&mut cursor)? as usize;
|
||||
let direction = Direction::from_int_facing(tsc_direction).unwrap_or(Direction::Left);
|
||||
|
||||
|
|
Loading…
Reference in New Issue