mirror of
https://github.com/doukutsu-rs/doukutsu-rs
synced 2025-07-23 04:50:51 +00:00
Compare commits
7 commits
fe9fb06b5a
...
334d1530c0
Author | SHA1 | Date | |
---|---|---|---|
|
334d1530c0 | ||
|
aa269377ab | ||
|
6a12a9082f | ||
|
af7d7ae744 | ||
|
6c74b5517c | ||
|
f5751f6651 | ||
|
8973da2840 |
|
@ -47,6 +47,8 @@ Vanilla Cave Story does not work yet because some important data files have been
|
|||
#### Credits
|
||||
|
||||
- Studio Pixel/Nicalis for Cave Story
|
||||
- [ggez](https://github.com/ggez/ggez) - we took few bits from it while moving away to SDL2.
|
||||
- [@ClayHanson_](https://twitter.com/ClayHanson_) - for letting us use his .pxchar skin format from Cave Story Multiplayer mod.
|
||||
- [Cave Story Tribute Site](https://cavestory.org) - has lots of useful resources related to the game.
|
||||
- [CSE2](https://github.com/Clownacy/CSE2) - widescreen fixes, mutual help in various things.
|
||||
- [LunarLambda for organism](https://gitdab.com/LunarLambda/organism) - which is being used by us as `.org` playback engine.
|
||||
|
|
|
@ -4,13 +4,12 @@ use std::path::PathBuf;
|
|||
use crate::bmfont::BMFont;
|
||||
use crate::common::{FILE_TYPES, Rect};
|
||||
use crate::engine_constants::EngineConstants;
|
||||
|
||||
use crate::str;
|
||||
use crate::texture_set::TextureSet;
|
||||
use crate::framework::error::GameError::ResourceLoadError;
|
||||
use crate::framework::context::Context;
|
||||
use crate::framework::error::GameError::ResourceLoadError;
|
||||
use crate::framework::error::GameResult;
|
||||
use crate::framework::filesystem;
|
||||
use crate::str;
|
||||
use crate::texture_set::TextureSet;
|
||||
|
||||
pub struct BMFontRenderer {
|
||||
font: BMFont,
|
||||
|
@ -21,8 +20,8 @@ impl BMFontRenderer {
|
|||
pub fn load(root: &str, desc_path: &str, ctx: &mut Context) -> GameResult<BMFontRenderer> {
|
||||
let root = PathBuf::from(root);
|
||||
let full_path = &root.join(PathBuf::from(desc_path));
|
||||
let desc_stem = full_path.file_stem()
|
||||
.ok_or_else(|| ResourceLoadError(str!("Cannot extract the file stem.")))?;
|
||||
let desc_stem =
|
||||
full_path.file_stem().ok_or_else(|| ResourceLoadError(str!("Cannot extract the file stem.")))?;
|
||||
let stem = full_path.parent().unwrap_or(full_path).join(desc_stem);
|
||||
|
||||
let font = BMFont::load_from(filesystem::open(ctx, &full_path)?)?;
|
||||
|
@ -32,10 +31,12 @@ impl BMFontRenderer {
|
|||
.iter()
|
||||
.map(|ext| (1, ext, format!("{}_0{}", stem.to_string_lossy(), ext)))
|
||||
.find(|(_, _, path)| filesystem::exists(ctx, &path))
|
||||
.or_else(|| FILE_TYPES
|
||||
.iter()
|
||||
.map(|ext| (2, ext, format!("{}_00{}", stem.to_string_lossy(), ext)))
|
||||
.find(|(_, _, path)| filesystem::exists(ctx, &path)))
|
||||
.or_else(|| {
|
||||
FILE_TYPES
|
||||
.iter()
|
||||
.map(|ext| (2, ext, format!("{}_00{}", stem.to_string_lossy(), ext)))
|
||||
.find(|(_, _, path)| filesystem::exists(ctx, &path))
|
||||
})
|
||||
.ok_or_else(|| ResourceLoadError(format!("Cannot find glyph atlas 0 for font: {:?}", desc_path)))?;
|
||||
|
||||
for i in 0..font.pages {
|
||||
|
@ -44,49 +45,66 @@ impl BMFontRenderer {
|
|||
pages.push(page_path);
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
font,
|
||||
pages,
|
||||
})
|
||||
Ok(Self { font, pages })
|
||||
}
|
||||
|
||||
pub fn line_height(&self, constants: &EngineConstants) -> f32 {
|
||||
self.font.line_height as f32 * constants.font_scale
|
||||
}
|
||||
|
||||
pub fn text_width<I: Iterator<Item=char>>(&self, iter: I, constants: &EngineConstants) -> f32 {
|
||||
pub fn text_width<I: Iterator<Item = char>>(&self, iter: I, constants: &EngineConstants) -> f32 {
|
||||
let mut offset_x = 0.0;
|
||||
|
||||
for chr in iter {
|
||||
if let Some(glyph) = self.font.chars.get(&chr) {
|
||||
offset_x += ((glyph.width as f32 + glyph.xoffset as f32) * constants.font_scale).floor() + if chr != ' ' { 1.0 } else { constants.font_space_offset };
|
||||
offset_x += ((glyph.width as f32 + glyph.xoffset as f32) * constants.font_scale).floor()
|
||||
+ if chr != ' ' { 1.0 } else { constants.font_space_offset };
|
||||
}
|
||||
}
|
||||
|
||||
offset_x
|
||||
}
|
||||
|
||||
|
||||
pub fn draw_text<I: Iterator<Item=char>>(&self, iter: I, x: f32, y: f32, constants: &EngineConstants, texture_set: &mut TextureSet, ctx: &mut Context) -> GameResult {
|
||||
pub fn draw_text<I: Iterator<Item = char>>(
|
||||
&self,
|
||||
iter: I,
|
||||
x: f32,
|
||||
y: f32,
|
||||
constants: &EngineConstants,
|
||||
texture_set: &mut TextureSet,
|
||||
ctx: &mut Context,
|
||||
) -> GameResult {
|
||||
self.draw_colored_text(iter, x, y, (255, 255, 255, 255), constants, texture_set, ctx)
|
||||
}
|
||||
|
||||
pub fn draw_colored_text<I: Iterator<Item=char>>(&self, iter: I, x: f32, y: f32, color: (u8, u8, u8, u8),
|
||||
constants: &EngineConstants, texture_set: &mut TextureSet, ctx: &mut Context) -> GameResult {
|
||||
pub fn draw_colored_text_scaled<I: Iterator<Item = char>>(
|
||||
&self,
|
||||
iter: I,
|
||||
x: f32,
|
||||
y: f32,
|
||||
scale: f32,
|
||||
color: (u8, u8, u8, u8),
|
||||
constants: &EngineConstants,
|
||||
texture_set: &mut TextureSet,
|
||||
ctx: &mut Context,
|
||||
) -> GameResult {
|
||||
if self.pages.len() == 1 {
|
||||
let batch = texture_set.get_or_load_batch(ctx, constants, self.pages.get(0).unwrap())?;
|
||||
let mut offset_x = x;
|
||||
|
||||
for chr in iter {
|
||||
if let Some(glyph) = self.font.chars.get(&chr) {
|
||||
batch.add_rect_scaled_tinted(offset_x, y + (glyph.yoffset as f32 * constants.font_scale).floor(), color,
|
||||
constants.font_scale, constants.font_scale,
|
||||
&Rect::new_size(
|
||||
glyph.x as u16, glyph.y as u16,
|
||||
glyph.width as u16, glyph.height as u16,
|
||||
));
|
||||
batch.add_rect_scaled_tinted(
|
||||
offset_x,
|
||||
y + (glyph.yoffset as f32 * constants.font_scale).floor(),
|
||||
color,
|
||||
constants.font_scale,
|
||||
constants.font_scale,
|
||||
&Rect::new_size(glyph.x as u16, glyph.y as u16, glyph.width as u16, glyph.height as u16),
|
||||
);
|
||||
|
||||
offset_x += ((glyph.width as f32 + glyph.xoffset as f32) * constants.font_scale).floor() + if chr != ' ' { 1.0 } else { constants.font_space_offset };
|
||||
offset_x += ((glyph.width as f32 + glyph.xoffset as f32) * constants.font_scale).floor()
|
||||
+ if chr != ' ' { 1.0 } else { constants.font_space_offset };
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,15 +132,19 @@ impl BMFontRenderer {
|
|||
|
||||
for (chr, glyph) in chars.iter() {
|
||||
if glyph.page == page {
|
||||
batch.add_rect_scaled_tinted(offset_x, y + (glyph.yoffset as f32 * constants.font_scale).floor(), color,
|
||||
constants.font_scale, constants.font_scale,
|
||||
&Rect::new_size(
|
||||
glyph.x as u16, glyph.y as u16,
|
||||
glyph.width as u16, glyph.height as u16,
|
||||
));
|
||||
batch.add_rect_scaled_tinted(
|
||||
offset_x,
|
||||
y + (glyph.yoffset as f32 * constants.font_scale).floor(),
|
||||
color,
|
||||
constants.font_scale * scale,
|
||||
constants.font_scale * scale,
|
||||
&Rect::new_size(glyph.x as u16, glyph.y as u16, glyph.width as u16, glyph.height as u16),
|
||||
);
|
||||
}
|
||||
|
||||
offset_x += ((glyph.width as f32 + glyph.xoffset as f32) * constants.font_scale).floor() + if *chr != ' ' { 1.0 } else { constants.font_space_offset };
|
||||
offset_x += scale
|
||||
* (((glyph.width as f32 + glyph.xoffset as f32) * constants.font_scale).floor()
|
||||
+ if *chr != ' ' { 1.0 } else { constants.font_space_offset });
|
||||
}
|
||||
|
||||
batch.draw(ctx)?;
|
||||
|
@ -131,4 +153,17 @@ impl BMFontRenderer {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn draw_colored_text<I: Iterator<Item = char>>(
|
||||
&self,
|
||||
iter: I,
|
||||
x: f32,
|
||||
y: f32,
|
||||
color: (u8, u8, u8, u8),
|
||||
constants: &EngineConstants,
|
||||
texture_set: &mut TextureSet,
|
||||
ctx: &mut Context,
|
||||
) -> GameResult {
|
||||
self.draw_colored_text_scaled(iter, x, y, 1.0, color, constants, texture_set, ctx)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,30 @@
|
|||
use crate::entity::GameEntity;
|
||||
use crate::inventory::Inventory;
|
||||
use crate::framework::context::Context;
|
||||
use crate::frame::Frame;
|
||||
use crate::shared_game_state::SharedGameState;
|
||||
use crate::framework::error::GameResult;
|
||||
|
||||
pub struct Inventory {
|
||||
pub struct InventoryUI {
|
||||
text_y_pos: usize,
|
||||
tick: usize,
|
||||
}
|
||||
|
||||
impl Inventory {
|
||||
pub fn new() -> Inventory {
|
||||
Inventory {
|
||||
impl InventoryUI {
|
||||
pub fn new() -> InventoryUI {
|
||||
InventoryUI {
|
||||
text_y_pos: 24,
|
||||
tick: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GameEntity<&mut Inventory> for InventoryUI {
|
||||
fn tick(&mut self, state: &mut SharedGameState, custom: &mut Inventory) -> GameResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn draw(&self, state: &mut SharedGameState, ctx: &mut Context, frame: &Frame) -> GameResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -177,6 +177,9 @@ pub struct TextScriptConsts {
|
|||
pub textbox_rect_bottom: Rect<u16>,
|
||||
pub textbox_rect_yes_no: Rect<u16>,
|
||||
pub textbox_rect_cursor: Rect<u16>,
|
||||
pub inventory_rect_top: Rect<u16>,
|
||||
pub inventory_rect_middle: Rect<u16>,
|
||||
pub inventory_rect_bottom: Rect<u16>,
|
||||
pub get_item_top_left: Rect<u16>,
|
||||
pub get_item_bottom_left: Rect<u16>,
|
||||
pub get_item_top_right: Rect<u16>,
|
||||
|
@ -1356,6 +1359,9 @@ impl EngineConstants {
|
|||
textbox_rect_bottom: Rect { left: 0, top: 16, right: 244, bottom: 24 },
|
||||
textbox_rect_yes_no: Rect { left: 152, top: 48, right: 244, bottom: 80 },
|
||||
textbox_rect_cursor: Rect { left: 112, top: 88, right: 128, bottom: 104 },
|
||||
inventory_rect_top: Rect { left: 0, top: 0, right: 244, bottom: 8 },
|
||||
inventory_rect_middle: Rect { left: 0, top: 8, right: 244, bottom: 16 },
|
||||
inventory_rect_bottom: Rect { left: 0, top: 16, right: 244, bottom: 24 },
|
||||
get_item_top_left: Rect { left: 0, top: 0, right: 72, bottom: 16 },
|
||||
get_item_bottom_left: Rect { left: 0, top: 8, right: 72, bottom: 24 },
|
||||
get_item_top_right: Rect { left: 240, top: 0, right: 244, bottom: 8 },
|
||||
|
|
|
@ -3,9 +3,10 @@ use std::cmp::Ordering;
|
|||
use crate::engine_constants::EngineConstants;
|
||||
use crate::shared_game_state::SharedGameState;
|
||||
use crate::weapon::{Weapon, WeaponLevel, WeaponType};
|
||||
use crate::player::Player;
|
||||
use crate::player::{Player, TargetPlayer};
|
||||
use crate::caret::CaretType;
|
||||
use crate::common::Direction;
|
||||
use crate::weapon::bullet::BulletManager;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
/// (id, amount)
|
||||
|
@ -183,8 +184,7 @@ impl Inventory {
|
|||
|
||||
pub fn reset_current_weapon_xp(&mut self) {
|
||||
if let Some(weapon) = self.get_current_weapon_mut() {
|
||||
weapon.level = WeaponLevel::Level1;
|
||||
weapon.experience = 0;
|
||||
weapon.reset_xp();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -221,43 +221,14 @@ impl Inventory {
|
|||
|
||||
pub fn add_xp(&mut self, exp: u16, player: &mut Player, state: &mut SharedGameState) {
|
||||
if let Some(weapon) = self.get_current_weapon_mut() {
|
||||
let curr_level_idx = weapon.level as usize - 1;
|
||||
let lvl_table = state.constants.weapon.level_table[weapon.wtype as usize];
|
||||
|
||||
weapon.experience += exp;
|
||||
|
||||
if weapon.level == WeaponLevel::Level3 {
|
||||
if weapon.experience > lvl_table[2] {
|
||||
weapon.experience = lvl_table[2];
|
||||
|
||||
if player.equip.has_whimsical_star() && player.stars < 3 {
|
||||
player.stars += 1;
|
||||
}
|
||||
}
|
||||
} else if weapon.experience > lvl_table[curr_level_idx] {
|
||||
weapon.level = weapon.level.next();
|
||||
weapon.experience = 0;
|
||||
|
||||
if weapon.wtype != WeaponType::Spur {
|
||||
state.sound_manager.play_sfx(27);
|
||||
state.create_caret(player.x, player.y, CaretType::LevelUp, Direction::Left);
|
||||
}
|
||||
}
|
||||
weapon.add_xp(exp, player, state);
|
||||
}
|
||||
}
|
||||
|
||||
/// Get current experience state. Returns a (exp, max exp, max level/exp) tuple.
|
||||
pub fn get_current_max_exp(&self, constants: &EngineConstants) -> (u16, u16, bool) {
|
||||
if let Some(weapon) = self.weapons.get(self.current_weapon as usize) {
|
||||
if weapon.level == WeaponLevel::None {
|
||||
return (0, 0, false);
|
||||
}
|
||||
|
||||
let level_idx = weapon.level as usize - 1;
|
||||
let max_exp = constants.weapon.level_table[weapon.wtype as usize][level_idx];
|
||||
let max = weapon.level == WeaponLevel::Level3 && weapon.experience == max_exp;
|
||||
|
||||
(weapon.experience, max_exp, max)
|
||||
weapon.get_max_exp(constants)
|
||||
} else {
|
||||
(0, 0, false)
|
||||
}
|
||||
|
@ -291,6 +262,12 @@ impl Inventory {
|
|||
pub fn has_weapon(&self, wtype: WeaponType) -> bool {
|
||||
self.weapons.iter().any(|weapon| weapon.wtype == wtype)
|
||||
}
|
||||
|
||||
pub fn tick_weapons(&mut self, state: &mut SharedGameState, player: &mut Player, player_id: TargetPlayer, bullet_manager: &mut BulletManager) {
|
||||
if let Some(weapon) = self.get_current_weapon_mut() {
|
||||
weapon.tick(state, player, player_id, bullet_manager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -51,6 +51,9 @@ impl NPC {
|
|||
self.hit_bounds.bottom = 16 * 0x200;
|
||||
self.x -= 16 * 0x200;
|
||||
self.y += 8 * 0x200;
|
||||
// interpolation glitch fix
|
||||
self.prev_x = self.x;
|
||||
self.prev_y = self.y;
|
||||
}
|
||||
|
||||
self.action_counter += 1;
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
use crate::framework::context::Context;
|
||||
use crate::framework::error::GameResult;
|
||||
use num_traits::abs;
|
||||
use num_traits::clamp;
|
||||
|
||||
use crate::caret::CaretType;
|
||||
use crate::common::{Direction, Rect};
|
||||
use crate::npc::{NPC, NPCList};
|
||||
use crate::framework::context::Context;
|
||||
use crate::framework::error::GameResult;
|
||||
use crate::npc::{NPCList, NPC};
|
||||
use crate::player::Player;
|
||||
use crate::rng::RNG;
|
||||
use crate::shared_game_state::SharedGameState;
|
||||
|
||||
impl NPC {
|
||||
pub(crate) fn tick_n024_power_critter(&mut self, state: &mut SharedGameState, players: [&mut Player; 2]) -> GameResult {
|
||||
pub(crate) fn tick_n024_power_critter(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
players: [&mut Player; 2],
|
||||
) -> GameResult {
|
||||
let player = self.get_closest_player_mut(players);
|
||||
|
||||
match self.action_num {
|
||||
|
@ -23,7 +27,9 @@ impl NPC {
|
|||
|
||||
if self.action_counter >= 8
|
||||
&& abs(self.x - player.x) < (128 * 0x200)
|
||||
&& self.y - 128 * 0x200 < player.y && self.y + 48 * 0x200 > player.y {
|
||||
&& self.y - 128 * 0x200 < player.y
|
||||
&& self.y + 48 * 0x200 > player.y
|
||||
{
|
||||
if self.x > player.x {
|
||||
self.direction = Direction::Left;
|
||||
} else {
|
||||
|
@ -48,7 +54,8 @@ impl NPC {
|
|||
if self.action_counter >= 8
|
||||
&& abs(self.x - player.x) < 96 * 0x200
|
||||
&& self.y - 96 * 0x200 < player.y
|
||||
&& self.y + 48 * 0x200 > player.y {
|
||||
&& self.y + 48 * 0x200 > player.y
|
||||
{
|
||||
self.action_num = 2;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 0;
|
||||
|
@ -87,9 +94,9 @@ impl NPC {
|
|||
|
||||
self.action_counter += 1;
|
||||
|
||||
if (self.flags.hit_left_wall()
|
||||
|| self.flags.hit_right_wall()
|
||||
|| self.flags.hit_top_wall()) || self.action_counter > 100 {
|
||||
if (self.flags.hit_left_wall() || self.flags.hit_right_wall() || self.flags.hit_top_wall())
|
||||
|| self.action_counter > 100
|
||||
{
|
||||
self.action_num = 5;
|
||||
self.anim_num = 2;
|
||||
self.vel_x /= 2;
|
||||
|
@ -136,7 +143,11 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n026_bat_flying(&mut self, state: &mut SharedGameState, players: [&mut Player; 2]) -> GameResult {
|
||||
pub(crate) fn tick_n026_bat_flying(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
players: [&mut Player; 2],
|
||||
) -> GameResult {
|
||||
let player = self.get_closest_player_mut(players);
|
||||
|
||||
match self.action_num {
|
||||
|
@ -144,11 +155,13 @@ impl NPC {
|
|||
if self.action_num == 0 {
|
||||
let angle = self.rng.range(0..0xff);
|
||||
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;
|
||||
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 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.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;
|
||||
|
@ -165,9 +178,7 @@ impl NPC {
|
|||
|
||||
if self.action_counter2 < 120 {
|
||||
self.action_counter2 += 1;
|
||||
} else if abs(self.x - player.x) < 8 * 0x200
|
||||
&& self.y < player.y
|
||||
&& self.y + 96 * 0x200 > player.y {
|
||||
} else if abs(self.x - player.x) < 8 * 0x200 && self.y < player.y && self.y + 96 * 0x200 > player.y {
|
||||
self.vel_x /= 2;
|
||||
self.vel_y = 0;
|
||||
self.action_num = 3;
|
||||
|
@ -206,7 +217,11 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n028_flying_critter(&mut self, state: &mut SharedGameState, players: [&mut Player; 2]) -> GameResult {
|
||||
pub(crate) fn tick_n028_flying_critter(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
players: [&mut Player; 2],
|
||||
) -> GameResult {
|
||||
let player = self.get_closest_player_mut(players);
|
||||
|
||||
match self.action_num {
|
||||
|
@ -219,7 +234,8 @@ impl NPC {
|
|||
if self.action_counter >= 8
|
||||
&& abs(self.x - player.x) < 96 * 0x200
|
||||
&& self.y - 128 * 0x200 < player.y
|
||||
&& self.y + 48 * 0x200 > player.y {
|
||||
&& self.y + 48 * 0x200 > player.y
|
||||
{
|
||||
if self.x > player.x {
|
||||
self.direction = Direction::Left;
|
||||
} else {
|
||||
|
@ -244,7 +260,8 @@ impl NPC {
|
|||
if self.action_counter >= 8
|
||||
&& abs(self.x - player.x) < 96 * 0x200
|
||||
&& self.y - 96 * 0x200 < player.y
|
||||
&& self.y + 48 * 0x200 > player.y {
|
||||
&& self.y + 48 * 0x200 > player.y
|
||||
{
|
||||
self.action_num = 2;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 0;
|
||||
|
@ -283,9 +300,9 @@ impl NPC {
|
|||
|
||||
self.action_counter += 1;
|
||||
|
||||
if (self.flags.hit_left_wall()
|
||||
|| self.flags.hit_right_wall()
|
||||
|| self.flags.hit_top_wall()) || self.action_counter > 100 {
|
||||
if (self.flags.hit_left_wall() || self.flags.hit_right_wall() || self.flags.hit_top_wall())
|
||||
|| self.action_counter > 100
|
||||
{
|
||||
self.action_num = 5;
|
||||
self.anim_num = 2;
|
||||
self.vel_x /= 2;
|
||||
|
@ -335,7 +352,11 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n031_bat_hanging(&mut self, state: &mut SharedGameState, players: [&mut Player; 2]) -> GameResult {
|
||||
pub(crate) fn tick_n031_bat_hanging(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
players: [&mut Player; 2],
|
||||
) -> GameResult {
|
||||
let player = self.get_closest_player_mut(players);
|
||||
|
||||
match self.action_num {
|
||||
|
@ -350,9 +371,8 @@ impl NPC {
|
|||
self.anim_num = 1;
|
||||
}
|
||||
|
||||
if abs(self.x - player.x) < 8 * 0x200
|
||||
&& self.y - 8 * 0x200 < player.y
|
||||
&& self.y + 96 * 0x200 > player.y {
|
||||
if abs(self.x - player.x) < 8 * 0x200 && self.y - 8 * 0x200 < player.y && self.y + 96 * 0x200 > player.y
|
||||
{
|
||||
self.action_num = 3;
|
||||
self.anim_num = 0;
|
||||
}
|
||||
|
@ -564,11 +584,7 @@ impl NPC {
|
|||
let player = self.get_closest_player_mut(players);
|
||||
|
||||
self.vel_x2 = 50;
|
||||
self.direction = if self.x > player.x {
|
||||
Direction::Left
|
||||
} else {
|
||||
Direction::Right
|
||||
};
|
||||
self.direction = if self.x > player.x { Direction::Left } else { Direction::Right };
|
||||
}
|
||||
|
||||
self.vel_y += 0x10;
|
||||
|
@ -823,16 +839,14 @@ impl NPC {
|
|||
_ => {}
|
||||
}
|
||||
|
||||
if self.action_num <= 9 && self.action_num != 3 && self.action_counter > 10
|
||||
if self.action_num <= 9
|
||||
&& self.action_num != 3
|
||||
&& self.action_counter > 10
|
||||
&& ((self.shock > 0)
|
||||
|| (abs(self.x - player.x) < 160 * 0x200
|
||||
&& abs(self.y - player.y) < 64 * 0x200)
|
||||
&& self.rng.range(0..50) == 2) {
|
||||
self.direction = if self.x >= player.x {
|
||||
Direction::Left
|
||||
} else {
|
||||
Direction::Right
|
||||
};
|
||||
|| (abs(self.x - player.x) < 160 * 0x200 && abs(self.y - player.y) < 64 * 0x200)
|
||||
&& self.rng.range(0..50) == 2)
|
||||
{
|
||||
self.direction = if self.x >= player.x { Direction::Left } else { Direction::Right };
|
||||
self.action_num = 10;
|
||||
self.anim_num = 2;
|
||||
self.vel_x = self.direction.vector_x() * 0x200;
|
||||
|
@ -1016,7 +1030,12 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n109_malco_powered_on(&mut self, state: &mut SharedGameState, players: [&mut Player; 2], npc_list: &NPCList) -> GameResult {
|
||||
pub(crate) fn tick_n109_malco_powered_on(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
players: [&mut Player; 2],
|
||||
npc_list: &NPCList,
|
||||
) -> GameResult {
|
||||
match self.action_num {
|
||||
0 | 1 => {
|
||||
if self.action_num == 0 {
|
||||
|
@ -1040,7 +1059,8 @@ impl NPC {
|
|||
|
||||
if abs(self.x - player.x) < 32 * 0x200
|
||||
&& self.y - 32 * 0x200 < player.y
|
||||
&& self.y + 16 * 0x200 > player.y {
|
||||
&& self.y + 16 * 0x200 > player.y
|
||||
{
|
||||
self.direction = if self.x > player.x { Direction::Left } else { Direction::Right };
|
||||
}
|
||||
}
|
||||
|
@ -1167,16 +1187,14 @@ impl NPC {
|
|||
_ => {}
|
||||
}
|
||||
|
||||
if self.action_num <= 9 && self.action_num != 3 && self.action_counter > 10
|
||||
if self.action_num <= 9
|
||||
&& self.action_num != 3
|
||||
&& self.action_counter > 10
|
||||
&& ((self.shock > 0)
|
||||
|| (abs(self.x - player.x) < 160 * 0x200
|
||||
&& abs(self.y - player.y) < 64 * 0x200)
|
||||
&& self.rng.range(0..50) == 2) {
|
||||
self.direction = if self.x >= player.x {
|
||||
Direction::Left
|
||||
} else {
|
||||
Direction::Right
|
||||
};
|
||||
|| (abs(self.x - player.x) < 160 * 0x200 && abs(self.y - player.y) < 64 * 0x200)
|
||||
&& self.rng.range(0..50) == 2)
|
||||
{
|
||||
self.direction = if self.x >= player.x { Direction::Left } else { Direction::Right };
|
||||
self.action_num = 10;
|
||||
self.anim_num = 2;
|
||||
self.vel_x = self.direction.vector_x() * 0x100;
|
||||
|
@ -1199,16 +1217,147 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n115_ravil(
|
||||
&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.action_num = 1;
|
||||
self.action_counter = 0;
|
||||
self.action_counter2 = 0;
|
||||
self.vel_x = 0;
|
||||
}
|
||||
|
||||
let player = self.get_closest_player_mut(players);
|
||||
if self.shock != 0
|
||||
|| (player.x < self.x + 0xc000
|
||||
&& player.x > self.x - 0xc000
|
||||
&& player.y < self.y + 0x4000
|
||||
&& player.y > self.y - 0xc000)
|
||||
{
|
||||
self.action_num = 10;
|
||||
}
|
||||
}
|
||||
10 => {
|
||||
let player = self.get_closest_player_mut(players);
|
||||
|
||||
self.anim_num = 1;
|
||||
self.direction = if self.x >= player.x { Direction::Left } else { Direction::Right };
|
||||
|
||||
self.action_counter += 1;
|
||||
if self.action_counter > 20 {
|
||||
self.action_num = 20;
|
||||
self.action_counter = 0;
|
||||
}
|
||||
}
|
||||
20 => {
|
||||
self.damage = 0;
|
||||
self.vel_x = 0;
|
||||
|
||||
self.anim_counter += 1;
|
||||
if self.anim_counter > 2 {
|
||||
self.anim_num += 1;
|
||||
self.anim_counter = 0;
|
||||
if self.anim_num > 2 {
|
||||
let player = self.get_closest_player_mut(players);
|
||||
|
||||
self.direction = if self.x >= player.x { Direction::Left } else { Direction::Right };
|
||||
|
||||
self.vel_x = self.direction.vector_x() * 0x200;
|
||||
self.action_counter2 += 1;
|
||||
self.action_num = 21;
|
||||
self.vel_y = -0x400;
|
||||
|
||||
if self.action_counter2 > 2 {
|
||||
self.action_counter2 = 0;
|
||||
self.anim_num = 4;
|
||||
self.vel_x *= 2;
|
||||
self.damage = 5;
|
||||
|
||||
state.sound_manager.play_sfx(102);
|
||||
} else {
|
||||
state.sound_manager.play_sfx(30);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
21 => {
|
||||
if self.flags.hit_bottom_wall() {
|
||||
self.action_num = 20;
|
||||
self.anim_num = 1;
|
||||
self.anim_counter = 0;
|
||||
self.damage = 0;
|
||||
|
||||
let player = self.get_closest_player_mut(players);
|
||||
if player.x > self.x + 0x12000
|
||||
&& player.x < self.x - 0x12000
|
||||
&& player.y > self.y + 0x6000
|
||||
&& player.y < self.y - 0x12000
|
||||
{
|
||||
self.action_num = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
30 => {
|
||||
let mut npc = NPC::create(4, &state.npc_table);
|
||||
for _ in 0..8 {
|
||||
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());
|
||||
}
|
||||
|
||||
self.anim_num = 0;
|
||||
self.action_num = 0;
|
||||
}
|
||||
50 | 51 => {
|
||||
if self.action_num == 50 {
|
||||
self.action_num = 51;
|
||||
self.anim_num = 4;
|
||||
self.damage = 0;
|
||||
self.vel_y = -0x200;
|
||||
|
||||
self.npc_flags.set_shootable(false);
|
||||
self.npc_flags.set_solid_soft(false);
|
||||
}
|
||||
|
||||
if self.flags.hit_bottom_wall() {
|
||||
self.action_num = 52;
|
||||
self.anim_num = 5;
|
||||
self.vel_x = 0;
|
||||
state.sound_manager.play_sfx(23);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.vel_y += if self.action_num <= 50 { 0x40 } else { 0x20 };
|
||||
|
||||
if self.vel_y > 0x5ff {
|
||||
self.vel_y = 0x5ff;
|
||||
}
|
||||
|
||||
self.x += self.vel_x;
|
||||
self.y += self.vel_y;
|
||||
|
||||
let dir_offset = if self.direction == Direction::Left { 0 } else { 6 };
|
||||
|
||||
self.anim_rect = state.constants.npc.n115_ravil[self.anim_num as usize + dir_offset];
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n192_scooter(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
match self.action_num {
|
||||
0 => {
|
||||
self.action_num = 1;
|
||||
self.display_bounds = Rect {
|
||||
left: 16 * 0x200,
|
||||
top: 8 * 0x200,
|
||||
right: 16 * 0x200,
|
||||
bottom: 8 * 0x200,
|
||||
};
|
||||
self.display_bounds = Rect { left: 16 * 0x200, top: 8 * 0x200, right: 16 * 0x200, bottom: 8 * 0x200 };
|
||||
}
|
||||
10 => {
|
||||
self.action_num = 11;
|
||||
|
@ -1280,9 +1429,12 @@ impl NPC {
|
|||
|
||||
if self.action_counter % 4 == 0 && self.action_num >= 20 {
|
||||
state.sound_manager.play_sfx(34);
|
||||
state.create_caret(self.x + self.direction.vector_x() * 10 * 0x200,
|
||||
self.y + 10 * 0x200,
|
||||
CaretType::Exhaust, self.direction.opposite());
|
||||
state.create_caret(
|
||||
self.x + self.direction.opposite().vector_x() * 10 * 0x200,
|
||||
self.y + 10 * 0x200,
|
||||
CaretType::Exhaust,
|
||||
self.direction.opposite(),
|
||||
);
|
||||
}
|
||||
|
||||
let dir_offset = if self.direction == Direction::Left { 0 } else { 2 };
|
||||
|
|
|
@ -134,11 +134,7 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n015_chest_closed(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
npc_list: &NPCList,
|
||||
) -> GameResult {
|
||||
pub(crate) fn tick_n015_chest_closed(&mut self, state: &mut SharedGameState, npc_list: &NPCList) -> GameResult {
|
||||
match self.action_num {
|
||||
0 | 1 => {
|
||||
if self.action_num == 0 {
|
||||
|
@ -296,11 +292,7 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n018_door(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
npc_list: &NPCList,
|
||||
) -> GameResult {
|
||||
pub(crate) fn tick_n018_door(&mut self, state: &mut SharedGameState, npc_list: &NPCList) -> GameResult {
|
||||
match self.action_num {
|
||||
0 => match self.direction {
|
||||
Direction::Left => self.anim_rect = state.constants.npc.n018_door[0],
|
||||
|
@ -362,24 +354,21 @@ impl NPC {
|
|||
|
||||
pub(crate) fn tick_n022_teleporter(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
match self.action_num {
|
||||
0 if self.anim_counter == 0 => {
|
||||
self.anim_counter = 1;
|
||||
self.anim_rect = state.constants.npc.n022_teleporter[0];
|
||||
0 => {
|
||||
self.anim_num = 0;
|
||||
}
|
||||
1 => {
|
||||
self.anim_num = (self.anim_num + 1) & 1;
|
||||
self.anim_rect = state.constants.npc.n022_teleporter[self.anim_num as usize];
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.anim_rect = state.constants.npc.n022_teleporter[self.anim_num as usize];
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n023_teleporter_lights(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
) -> GameResult {
|
||||
pub(crate) fn tick_n023_teleporter_lights(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
self.anim_counter += 1;
|
||||
if self.anim_counter > 1 {
|
||||
self.anim_counter = 0;
|
||||
|
@ -599,11 +588,7 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n073_water_droplet(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
stage: &Stage,
|
||||
) -> GameResult {
|
||||
pub(crate) fn tick_n073_water_droplet(&mut self, state: &mut SharedGameState, stage: &Stage) -> GameResult {
|
||||
self.vel_y += 0x20;
|
||||
|
||||
self.anim_rect = state.constants.npc.n073_water_droplet[self.rng.range(0..4) as usize];
|
||||
|
@ -666,19 +651,13 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n085_terminal(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
players: [&mut Player; 2],
|
||||
) -> GameResult {
|
||||
pub(crate) fn tick_n085_terminal(&mut self, state: &mut SharedGameState, players: [&mut Player; 2]) -> GameResult {
|
||||
match self.action_num {
|
||||
0 => {
|
||||
self.anim_num = 0;
|
||||
let player = self.get_closest_player_mut(players);
|
||||
|
||||
if abs(player.x - self.x) < 8 * 0x200
|
||||
&& player.y < self.y + 8 * 0x200
|
||||
&& player.y > self.y - 16 * 0x200
|
||||
if abs(player.x - self.x) < 8 * 0x200 && player.y < self.y + 8 * 0x200 && player.y > self.y - 16 * 0x200
|
||||
{
|
||||
state.sound_manager.play_sfx(43);
|
||||
self.action_num = 1;
|
||||
|
@ -693,11 +672,7 @@ impl NPC {
|
|||
_ => {}
|
||||
}
|
||||
|
||||
let dir_offset = if self.direction == Direction::Left {
|
||||
0
|
||||
} else {
|
||||
3
|
||||
};
|
||||
let dir_offset = if self.direction == Direction::Left { 0 } else { 3 };
|
||||
self.anim_rect = state.constants.npc.n085_terminal[self.anim_num as usize + dir_offset];
|
||||
|
||||
Ok(())
|
||||
|
@ -756,10 +731,7 @@ impl NPC {
|
|||
continue;
|
||||
}
|
||||
|
||||
if abs(player.y - self.y) < 8 * 0x200
|
||||
&& player.x < self.x
|
||||
&& player.x > self.x - 96 * 0x200
|
||||
{
|
||||
if abs(player.y - self.y) < 8 * 0x200 && player.x < self.x && player.x > self.x - 96 * 0x200 {
|
||||
player.vel_x -= 0x88;
|
||||
player.cond.set_increase_acceleration(true);
|
||||
}
|
||||
|
@ -819,10 +791,7 @@ impl NPC {
|
|||
continue;
|
||||
}
|
||||
|
||||
if abs(player.x - self.x) < 8 * 0x200
|
||||
&& player.y < self.y
|
||||
&& player.y > self.y - 96 * 0x200
|
||||
{
|
||||
if abs(player.x - self.x) < 8 * 0x200 && player.y < self.y && player.y > self.y - 96 * 0x200 {
|
||||
player.vel_y -= 0x88;
|
||||
}
|
||||
}
|
||||
|
@ -877,10 +846,7 @@ impl NPC {
|
|||
}
|
||||
|
||||
for player in players.iter_mut() {
|
||||
if abs(player.y - self.y) < 8 * 0x200
|
||||
&& player.x > self.x
|
||||
&& player.x < self.x + 96 * 0x200
|
||||
{
|
||||
if abs(player.y - self.y) < 8 * 0x200 && player.x > self.x && player.x < self.x + 96 * 0x200 {
|
||||
player.vel_x += 0x88;
|
||||
player.cond.set_increase_acceleration(true);
|
||||
}
|
||||
|
@ -936,10 +902,7 @@ impl NPC {
|
|||
}
|
||||
|
||||
for player in players.iter_mut() {
|
||||
if abs(player.x - self.x) < 8 * 0x200
|
||||
&& player.y > self.y
|
||||
&& player.y < self.y + 96 * 0x200
|
||||
{
|
||||
if abs(player.x - self.x) < 8 * 0x200 && player.y > self.y && player.y < self.y + 96 * 0x200 {
|
||||
player.vel_y -= 0x88;
|
||||
}
|
||||
}
|
||||
|
@ -968,11 +931,7 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n106_hey_bubble_high(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
npc_list: &NPCList,
|
||||
) -> GameResult {
|
||||
pub(crate) fn tick_n106_hey_bubble_high(&mut self, state: &mut SharedGameState, npc_list: &NPCList) -> GameResult {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
|
||||
|
@ -1084,20 +1043,9 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n125_hidden_item(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
npc_list: &NPCList,
|
||||
) -> GameResult {
|
||||
pub(crate) fn tick_n125_hidden_item(&mut self, state: &mut SharedGameState, npc_list: &NPCList) -> GameResult {
|
||||
if self.life < 990 {
|
||||
npc_list.create_death_smoke(
|
||||
self.x,
|
||||
self.y,
|
||||
self.display_bounds.right,
|
||||
8,
|
||||
state,
|
||||
&self.rng,
|
||||
);
|
||||
npc_list.create_death_smoke(self.x, self.y, self.display_bounds.right, 8, state, &self.rng);
|
||||
self.cond.set_alive(false);
|
||||
state.sound_manager.play_sfx(70);
|
||||
|
||||
|
@ -1155,11 +1103,7 @@ impl NPC {
|
|||
self.npc_flags.set_solid_hard(true);
|
||||
self.vel_x = 0;
|
||||
self.vel_y = 0;
|
||||
self.action_num = if self.direction == Direction::Right {
|
||||
20
|
||||
} else {
|
||||
10
|
||||
};
|
||||
self.action_num = if self.direction == Direction::Right { 20 } else { 10 };
|
||||
}
|
||||
10 => {
|
||||
self.npc_flags.set_rear_and_top_not_hurt(false);
|
||||
|
@ -1284,12 +1228,7 @@ impl NPC {
|
|||
self.y += 0x2000;
|
||||
}
|
||||
|
||||
self.anim_rect = Rect {
|
||||
left: 0,
|
||||
top: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
};
|
||||
self.anim_rect = Rect { left: 0, top: 0, right: 0, bottom: 0 };
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -1308,11 +1247,7 @@ impl NPC {
|
|||
self.npc_flags.set_solid_hard(true);
|
||||
self.vel_x = 0;
|
||||
self.vel_y = 0;
|
||||
self.action_num = if self.direction == Direction::Right {
|
||||
20
|
||||
} else {
|
||||
10
|
||||
};
|
||||
self.action_num = if self.direction == Direction::Right { 20 } else { 10 };
|
||||
}
|
||||
10 => {
|
||||
self.npc_flags.set_rear_and_top_not_hurt(false);
|
||||
|
@ -1429,10 +1364,7 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n194_broken_blue_robot(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
) -> GameResult {
|
||||
pub(crate) fn tick_n194_broken_blue_robot(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
self.y += 4 * 0x200;
|
||||
|
@ -1518,19 +1450,12 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n229_red_flowers_sprouts(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
) -> GameResult {
|
||||
pub(crate) fn tick_n229_red_flowers_sprouts(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
self.y -= 0x2000;
|
||||
|
||||
let anim = if self.direction == Direction::Left {
|
||||
0
|
||||
} else {
|
||||
1
|
||||
};
|
||||
let anim = if self.direction == Direction::Left { 0 } else { 1 };
|
||||
|
||||
self.anim_rect = state.constants.npc.n229_red_flowers_sprouts[anim];
|
||||
}
|
||||
|
@ -1538,20 +1463,13 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n230_red_flowers_blooming(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
) -> GameResult {
|
||||
pub(crate) fn tick_n230_red_flowers_blooming(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
self.x -= 0x2000;
|
||||
self.y -= 0x2000;
|
||||
|
||||
let anim = if self.direction == Direction::Left {
|
||||
0
|
||||
} else {
|
||||
1
|
||||
};
|
||||
let anim = if self.direction == Direction::Left { 0 } else { 1 };
|
||||
|
||||
self.anim_rect = state.constants.npc.n230_red_flowers_blooming[anim];
|
||||
}
|
||||
|
@ -1559,10 +1477,7 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n234_red_flowers_picked(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
) -> GameResult {
|
||||
pub(crate) fn tick_n234_red_flowers_picked(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
self.y += 16 * 0x200;
|
||||
|
@ -1590,11 +1505,7 @@ impl NPC {
|
|||
}
|
||||
}
|
||||
|
||||
let anim = if self.direction == Direction::Left {
|
||||
0
|
||||
} else {
|
||||
1
|
||||
};
|
||||
let anim = if self.direction == Direction::Left { 0 } else { 1 };
|
||||
|
||||
self.anim_rect = state.constants.npc.n239_cage_bars[anim];
|
||||
|
||||
|
@ -1616,11 +1527,7 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n297_sue_dragon_mouth(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
npc_list: &NPCList,
|
||||
) -> GameResult {
|
||||
pub(crate) fn tick_n297_sue_dragon_mouth(&mut self, state: &mut SharedGameState, npc_list: &NPCList) -> GameResult {
|
||||
if let Some(npc) = self.get_parent_ref_mut(npc_list) {
|
||||
self.x = npc.x + 0x2000;
|
||||
self.y = npc.y + 0x1000;
|
||||
|
@ -1686,10 +1593,7 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n328_human_transform_machine(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
) -> GameResult {
|
||||
pub(crate) fn tick_n328_human_transform_machine(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
self.anim_rect = state.constants.npc.n328_human_transform_machine;
|
||||
|
@ -1700,8 +1604,7 @@ impl NPC {
|
|||
|
||||
pub(crate) fn tick_n329_laboratory_fan(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
self.anim_counter = self.anim_counter.wrapping_add(1);
|
||||
self.anim_rect =
|
||||
state.constants.npc.n329_laboratory_fan[(self.anim_counter as usize / 2) & 1];
|
||||
self.anim_rect = state.constants.npc.n329_laboratory_fan[(self.anim_counter as usize / 2) & 1];
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1722,11 +1625,7 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n351_statue_shootable(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
npc_list: &NPCList,
|
||||
) -> GameResult {
|
||||
pub(crate) fn tick_n351_statue_shootable(&mut self, state: &mut SharedGameState, npc_list: &NPCList) -> GameResult {
|
||||
match self.action_num {
|
||||
0 => {
|
||||
self.action_num = 1;
|
||||
|
|
|
@ -257,6 +257,7 @@ impl GameEntity<([&mut Player; 2], &NPCList, &mut Stage, &BulletManager)> for NP
|
|||
112 => self.tick_n112_quote_teleport_in(state, players),
|
||||
113 => self.tick_n113_professor_booster(state),
|
||||
114 => self.tick_n114_press(state, players, npc_list),
|
||||
115 => self.tick_n115_ravil(state, players, npc_list),
|
||||
116 => self.tick_n116_red_petals(state),
|
||||
117 => self.tick_n117_curly(state, players, npc_list),
|
||||
118 => self.tick_n118_curly_boss(state, players, npc_list, bullet_manager),
|
||||
|
|
|
@ -4,7 +4,7 @@ use num_derive::FromPrimitive;
|
|||
use num_traits::clamp;
|
||||
|
||||
use crate::caret::CaretType;
|
||||
use crate::common::{interpolate_fix9_scale, Condition, Direction, Equipment, Flag, Rect};
|
||||
use crate::common::{Condition, Direction, Equipment, Flag, interpolate_fix9_scale, Rect};
|
||||
use crate::entity::GameEntity;
|
||||
use crate::frame::Frame;
|
||||
use crate::framework::context::Context;
|
||||
|
@ -13,8 +13,8 @@ use crate::input::dummy_player_controller::DummyPlayerController;
|
|||
use crate::input::player_controller::PlayerController;
|
||||
use crate::npc::list::NPCList;
|
||||
use crate::npc::NPC;
|
||||
use crate::player::skin::basic::BasicPlayerSkin;
|
||||
use crate::player::skin::{PlayerAnimationState, PlayerAppearanceState, PlayerSkin};
|
||||
use crate::player::skin::basic::BasicPlayerSkin;
|
||||
use crate::rng::RNG;
|
||||
use crate::shared_game_state::SharedGameState;
|
||||
|
||||
|
@ -550,7 +550,8 @@ impl Player {
|
|||
if self.flags.hit_bottom_wall() {
|
||||
if self.cond.interacted() {
|
||||
self.skin.set_state(PlayerAnimationState::Examining);
|
||||
self.anim_num = 11;
|
||||
self.anim_num = 0;
|
||||
self.anim_counter = 0;
|
||||
} else if state.control_flags.control_enabled()
|
||||
&& self.controller.move_up()
|
||||
&& (self.controller.move_left() || self.controller.move_right())
|
||||
|
@ -597,7 +598,8 @@ impl Player {
|
|||
|
||||
self.cond.set_fallen(false);
|
||||
self.skin.set_state(PlayerAnimationState::LookingUp);
|
||||
self.anim_num = 5;
|
||||
self.anim_num = 0;
|
||||
self.anim_counter = 0;
|
||||
} else {
|
||||
if self.cond.fallen() {
|
||||
state.sound_manager.play_sfx(24);
|
||||
|
@ -606,20 +608,24 @@ impl Player {
|
|||
self.cond.set_fallen(false);
|
||||
self.skin.set_state(PlayerAnimationState::Idle);
|
||||
self.anim_num = 0;
|
||||
self.anim_counter = 0;
|
||||
}
|
||||
} else if self.controller.look_up() {
|
||||
self.skin.set_state(PlayerAnimationState::FallingLookingUp);
|
||||
self.anim_num = 6;
|
||||
self.anim_num = 0;
|
||||
self.anim_counter = 0;
|
||||
} else if self.controller.look_down() {
|
||||
self.skin.set_state(PlayerAnimationState::FallingLookingDown);
|
||||
self.anim_num = 10;
|
||||
self.anim_num = 0;
|
||||
self.anim_counter = 0;
|
||||
} else {
|
||||
self.skin.set_state(if self.vel_y > 0 {
|
||||
PlayerAnimationState::Jumping
|
||||
} else {
|
||||
PlayerAnimationState::Falling
|
||||
});
|
||||
self.anim_num = if self.vel_y > 0 { 1 } else { 3 };
|
||||
self.anim_num = 0;
|
||||
self.anim_counter = 0;
|
||||
}
|
||||
|
||||
self.weapon_offset_y = 0;
|
||||
|
@ -628,16 +634,9 @@ impl Player {
|
|||
self.weapon_rect.right = self.weapon_rect.left + 24;
|
||||
self.weapon_rect.bottom = self.weapon_rect.top + 16;
|
||||
|
||||
match self.direction {
|
||||
Direction::Left => {
|
||||
self.anim_rect = state.constants.my_char.frames_left[self.anim_num as usize];
|
||||
}
|
||||
Direction::Right => {
|
||||
self.weapon_rect.top += 16;
|
||||
self.weapon_rect.bottom += 16;
|
||||
self.anim_rect = state.constants.my_char.frames_right[self.anim_num as usize];
|
||||
}
|
||||
_ => {}
|
||||
if self.direction == Direction::Right {
|
||||
self.weapon_rect.top += 16;
|
||||
self.weapon_rect.bottom += 16;
|
||||
}
|
||||
|
||||
if self.up {
|
||||
|
|
|
@ -31,12 +31,12 @@ impl PlayerSkin for BasicPlayerSkin {
|
|||
PlayerAnimationState::Walking => {
|
||||
const WALK_INDEXES: [u16; 4] = [1, 0, 2, 0];
|
||||
|
||||
WALK_INDEXES[(self.tick as usize / 4) % 4]
|
||||
WALK_INDEXES[(tick as usize / 5) % 4]
|
||||
}
|
||||
PlayerAnimationState::WalkingUp => {
|
||||
const WALK_UP_INDEXES: [u16; 4] = [4, 3, 5, 3];
|
||||
|
||||
WALK_UP_INDEXES[(self.tick as usize / 4) % 4]
|
||||
WALK_UP_INDEXES[(tick as usize / 5) % 4]
|
||||
}
|
||||
PlayerAnimationState::LookingUp => 3,
|
||||
PlayerAnimationState::Examining => 7,
|
||||
|
@ -64,7 +64,9 @@ impl PlayerSkin for BasicPlayerSkin {
|
|||
}
|
||||
|
||||
fn tick(&mut self) {
|
||||
self.tick = self.tick.wrapping_add(1);
|
||||
if self.state == PlayerAnimationState::Walking || self.state == PlayerAnimationState::WalkingUp {
|
||||
self.tick = self.tick.wrapping_add(1);
|
||||
}
|
||||
}
|
||||
|
||||
fn set_state(&mut self, state: PlayerAnimationState) {
|
||||
|
|
|
@ -32,6 +32,7 @@ use crate::text_script::{ConfirmSelection, ScriptMode, TextScriptExecutionState,
|
|||
use crate::texture_set::SizedBatch;
|
||||
use crate::weapon::bullet::BulletManager;
|
||||
use crate::weapon::WeaponType;
|
||||
use crate::components::inventory::InventoryUI;
|
||||
|
||||
pub struct GameScene {
|
||||
pub tick: u32,
|
||||
|
@ -39,6 +40,7 @@ pub struct GameScene {
|
|||
pub boss_life_bar: BossLifeBar,
|
||||
pub stage_select: StageSelect,
|
||||
pub flash: Flash,
|
||||
pub inventory_ui: InventoryUI,
|
||||
pub hud_player1: HUD,
|
||||
pub hud_player2: HUD,
|
||||
pub frame: Frame,
|
||||
|
@ -89,6 +91,7 @@ impl GameScene {
|
|||
boss_life_bar: BossLifeBar::new(),
|
||||
stage_select: StageSelect::new(),
|
||||
flash: Flash::new(),
|
||||
inventory_ui: InventoryUI::new(),
|
||||
hud_player1: HUD::new(Alignment::Left),
|
||||
hud_player2: HUD::new(Alignment::Right),
|
||||
frame: Frame {
|
||||
|
@ -1186,21 +1189,16 @@ impl GameScene {
|
|||
self.frame.update(state, &self.stage);
|
||||
|
||||
if state.control_flags.control_enabled() {
|
||||
#[allow(clippy::cast_ref_to_mut)]
|
||||
let inventory = unsafe { &mut *(&self.inventory_player1 as *const Inventory as *mut Inventory) }; // fuck off
|
||||
if let Some(weapon) = self.inventory_player1.get_current_weapon_mut() {
|
||||
weapon.tick(&mut self.player1, TargetPlayer::Player1, inventory, &mut self.bullet_manager, state);
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_ref_to_mut)]
|
||||
let inventory = unsafe { &mut *(&self.inventory_player2 as *const Inventory as *mut Inventory) };
|
||||
if let Some(weapon) = self.inventory_player2.get_current_weapon_mut() {
|
||||
weapon.tick(&mut self.player2, TargetPlayer::Player2, inventory, &mut self.bullet_manager, state);
|
||||
}
|
||||
self.inventory_player1.tick_weapons(state, &mut self.player1, TargetPlayer::Player1, &mut self.bullet_manager);
|
||||
self.inventory_player2.tick_weapons(state, &mut self.player2, TargetPlayer::Player2, &mut self.bullet_manager);
|
||||
|
||||
self.hud_player1.tick(state, (&self.player1, &mut self.inventory_player1))?;
|
||||
self.hud_player2.tick(state, (&self.player2, &mut self.inventory_player2))?;
|
||||
self.boss_life_bar.tick(state, (&self.npc_list, &self.boss))?;
|
||||
|
||||
if self.player1.controller.trigger_inventory() {
|
||||
state.textscript_vm.set_mode(ScriptMode::Inventory);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -1356,6 +1354,7 @@ impl Scene for GameScene {
|
|||
match state.textscript_vm.mode {
|
||||
ScriptMode::Map if state.control_flags.tick_world() => self.tick_world(state)?,
|
||||
ScriptMode::StageSelect => self.stage_select.tick(state, (&self.player1, &self.player2))?,
|
||||
ScriptMode::Inventory => self.inventory_ui.tick(state, &mut self.inventory_player1)?,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,29 +17,16 @@ lazy_static! {
|
|||
let mut random = [0i8; 0x100];
|
||||
|
||||
let ref_data = include_bytes!("pixtone_ref.dat");
|
||||
|
||||
unsafe {
|
||||
sine.copy_from_slice(&*(&ref_data[0..0x100] as *const [u8] as *const [i8]));
|
||||
triangle.copy_from_slice(&*(&ref_data[0x100..0x200] as *const [u8] as *const [i8]));
|
||||
saw_up.copy_from_slice(&*(&ref_data[0x200..0x300] as *const [u8] as *const [i8]));
|
||||
saw_down.copy_from_slice(&*(&ref_data[0x300..0x400] as *const [u8] as *const [i8]));
|
||||
square.copy_from_slice(&*(&ref_data[0x400..0x500] as *const [u8] as *const [i8]));
|
||||
random.copy_from_slice(&*(&ref_data[0x500..0x600] as *const [u8] as *const [i8]));
|
||||
sine.copy_from_slice(std::mem::transmute(&ref_data[0..0x100]));
|
||||
triangle.copy_from_slice(std::mem::transmute(&ref_data[0x100..0x200]));
|
||||
saw_up.copy_from_slice(std::mem::transmute(&ref_data[0x200..0x300]));
|
||||
saw_down.copy_from_slice(std::mem::transmute(&ref_data[0x300..0x400]));
|
||||
square.copy_from_slice(std::mem::transmute(&ref_data[0x400..0x500]));
|
||||
random.copy_from_slice(std::mem::transmute(&ref_data[0x500..0x600]));
|
||||
}
|
||||
|
||||
// todo i can't get this shit right
|
||||
/*
|
||||
let mut seed = 0i32;
|
||||
|
||||
for i in 0..255 {
|
||||
seed = seed.wrapping_mul(214013).wrapping_add(2531011);
|
||||
sine[i] = (64.0 * (i as f64 * std::f64::consts::PI).sin()) as i8;
|
||||
triangle[i] = (if (0x40i32.wrapping_add(i as i32)) & 0x80 != 0 { 0x80i32.wrapping_sub(i as i32) } else { i as i32 }) as i8;
|
||||
saw_up[i] = (-0x40i32).wrapping_add(i as i32 / 2) as i8;
|
||||
saw_down[i] = (0x40i32.wrapping_sub(i as i32 / 2)) as i8;
|
||||
square[i] = (0x40i32.wrapping_sub(i as i32 & 0x80)) as i8;
|
||||
random[i] = (seed >> 16) as i8 / 2;
|
||||
}*/
|
||||
|
||||
[sine, triangle, saw_up, saw_down, square, random]
|
||||
};
|
||||
}
|
||||
|
|
|
@ -2,10 +2,10 @@ use num_derive::FromPrimitive;
|
|||
|
||||
use crate::caret::CaretType;
|
||||
use crate::common::Direction;
|
||||
use crate::inventory::Inventory;
|
||||
use crate::engine_constants::EngineConstants;
|
||||
use crate::player::{Player, TargetPlayer};
|
||||
use crate::shared_game_state::SharedGameState;
|
||||
use crate::weapon::bullet::{Bullet, BulletManager};
|
||||
use crate::weapon::bullet::BulletManager;
|
||||
|
||||
mod blade;
|
||||
mod bubbler;
|
||||
|
@ -101,13 +101,54 @@ impl Weapon {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_max_exp(&self, constants: &EngineConstants) -> (u16, u16, bool) {
|
||||
if self.level == WeaponLevel::None {
|
||||
return (0, 0, false);
|
||||
}
|
||||
|
||||
let level_idx = self.level as usize - 1;
|
||||
let max_exp = constants.weapon.level_table[self.wtype as usize][level_idx];
|
||||
let max = self.level == WeaponLevel::Level3 && self.experience == max_exp;
|
||||
|
||||
(self.experience, max_exp, max)
|
||||
}
|
||||
|
||||
pub fn add_xp(&mut self, exp: u16, player: &mut Player, state: &mut SharedGameState) {
|
||||
let curr_level_idx = self.level as usize - 1;
|
||||
let lvl_table = state.constants.weapon.level_table[self.wtype as usize];
|
||||
|
||||
self.experience = self.experience.saturating_add(exp);
|
||||
|
||||
if self.level == WeaponLevel::Level3 {
|
||||
if self.experience > lvl_table[2] {
|
||||
self.experience = lvl_table[2];
|
||||
|
||||
if player.equip.has_whimsical_star() && player.stars < 3 {
|
||||
player.stars += 1;
|
||||
}
|
||||
}
|
||||
} else if self.experience > lvl_table[curr_level_idx] {
|
||||
self.level = self.level.next();
|
||||
self.experience = 0;
|
||||
|
||||
if self.wtype != WeaponType::Spur {
|
||||
state.sound_manager.play_sfx(27);
|
||||
state.create_caret(player.x, player.y, CaretType::LevelUp, Direction::Left);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset_xp(&mut self) {
|
||||
self.level = WeaponLevel::Level1;
|
||||
self.experience = 0;
|
||||
}
|
||||
|
||||
pub fn tick(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
player: &mut Player,
|
||||
player_id: TargetPlayer,
|
||||
inventory: &mut Inventory,
|
||||
bullet_manager: &mut BulletManager,
|
||||
state: &mut SharedGameState,
|
||||
) {
|
||||
if !player.cond.alive() || player.cond.hidden() {
|
||||
return;
|
||||
|
@ -124,9 +165,11 @@ impl Weapon {
|
|||
WeaponType::MissileLauncher => self.tick_missile_launcher(player, player_id, bullet_manager, state),
|
||||
WeaponType::Bubbler => self.tick_bubbler(player, player_id, bullet_manager, state),
|
||||
WeaponType::Blade => self.tick_blade(player, player_id, bullet_manager, state),
|
||||
WeaponType::SuperMissileLauncher => self.tick_super_missile_launcher(player, player_id, bullet_manager, state),
|
||||
WeaponType::SuperMissileLauncher => {
|
||||
self.tick_super_missile_launcher(player, player_id, bullet_manager, state)
|
||||
}
|
||||
WeaponType::Nemesis => self.tick_nemesis(player, player_id, bullet_manager, state),
|
||||
WeaponType::Spur => self.tick_spur(player, player_id, inventory, bullet_manager, state),
|
||||
WeaponType::Spur => self.tick_spur(player, player_id, bullet_manager, state),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use crate::caret::CaretType;
|
||||
use crate::common::Direction;
|
||||
use crate::inventory::Inventory;
|
||||
use crate::player::{Player, TargetPlayer};
|
||||
use crate::shared_game_state::SharedGameState;
|
||||
use crate::weapon::bullet::BulletManager;
|
||||
|
@ -11,7 +10,6 @@ impl Weapon {
|
|||
&mut self,
|
||||
player: &mut Player,
|
||||
player_id: TargetPlayer,
|
||||
inventory: &mut Inventory,
|
||||
bullet_manager: &mut BulletManager,
|
||||
state: &mut SharedGameState,
|
||||
) {
|
||||
|
@ -21,7 +19,7 @@ impl Weapon {
|
|||
let btype;
|
||||
|
||||
if player.controller.shoot() {
|
||||
inventory.add_xp(if player.equip.has_turbocharge() { 3 } else { 2 }, player, state);
|
||||
self.add_xp(if player.equip.has_turbocharge() { 3 } else { 2 }, player, state);
|
||||
self.counter1 += 1;
|
||||
|
||||
if (self.counter1 / 2 % 2) != 0 {
|
||||
|
@ -33,7 +31,7 @@ impl Weapon {
|
|||
state.sound_manager.play_sfx(60);
|
||||
}
|
||||
WeaponLevel::Level3 => {
|
||||
if let (_, _, false) = inventory.get_current_max_exp(&state.constants) {
|
||||
if let (_, _, false) = self.get_max_exp(&state.constants) {
|
||||
state.sound_manager.play_sfx(61);
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +45,7 @@ impl Weapon {
|
|||
}
|
||||
}
|
||||
|
||||
if let (_, _, true) = inventory.get_current_max_exp(&state.constants) {
|
||||
if let (_, _, true) = self.get_max_exp(&state.constants) {
|
||||
if self.counter2 == 0 {
|
||||
self.counter2 = 1;
|
||||
state.sound_manager.play_sfx(65);
|
||||
|
@ -58,7 +56,7 @@ impl Weapon {
|
|||
|
||||
let level = self.level;
|
||||
if !player.controller.shoot() {
|
||||
inventory.reset_current_weapon_xp();
|
||||
self.reset_xp();
|
||||
}
|
||||
|
||||
match level {
|
||||
|
@ -77,7 +75,8 @@ impl Weapon {
|
|||
WeaponLevel::None => unreachable!(),
|
||||
}
|
||||
|
||||
if bullet_manager.count_bullets_multi(&BULLETS, player_id) > 0 || !(player.controller.trigger_shoot() || shoot) {
|
||||
if bullet_manager.count_bullets_multi(&BULLETS, player_id) > 0 || !(player.controller.trigger_shoot() || shoot)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -86,27 +85,69 @@ impl Weapon {
|
|||
} else {
|
||||
match player.direction {
|
||||
Direction::Left if player.up => {
|
||||
bullet_manager.create_bullet(player.x - 0x200, player.y - 0x1000, btype, player_id, Direction::Up, &state.constants);
|
||||
bullet_manager.create_bullet(
|
||||
player.x - 0x200,
|
||||
player.y - 0x1000,
|
||||
btype,
|
||||
player_id,
|
||||
Direction::Up,
|
||||
&state.constants,
|
||||
);
|
||||
state.create_caret(player.x - 0x200, player.y - 0x1000, CaretType::Shoot, Direction::Left);
|
||||
}
|
||||
Direction::Right if player.up => {
|
||||
bullet_manager.create_bullet(player.x + 0x200, player.y - 0x1000, btype, player_id, Direction::Up, &state.constants);
|
||||
bullet_manager.create_bullet(
|
||||
player.x + 0x200,
|
||||
player.y - 0x1000,
|
||||
btype,
|
||||
player_id,
|
||||
Direction::Up,
|
||||
&state.constants,
|
||||
);
|
||||
state.create_caret(player.x + 0x200, player.y - 0x1000, CaretType::Shoot, Direction::Left);
|
||||
}
|
||||
Direction::Left if player.down => {
|
||||
bullet_manager.create_bullet(player.x - 0x200, player.y + 0x1000, btype, player_id, Direction::Bottom, &state.constants);
|
||||
bullet_manager.create_bullet(
|
||||
player.x - 0x200,
|
||||
player.y + 0x1000,
|
||||
btype,
|
||||
player_id,
|
||||
Direction::Bottom,
|
||||
&state.constants,
|
||||
);
|
||||
state.create_caret(player.x - 0x200, player.y + 0x1000, CaretType::Shoot, Direction::Left);
|
||||
}
|
||||
Direction::Right if player.down => {
|
||||
bullet_manager.create_bullet(player.x + 0x200, player.y + 0x1000, btype, player_id, Direction::Bottom, &state.constants);
|
||||
bullet_manager.create_bullet(
|
||||
player.x + 0x200,
|
||||
player.y + 0x1000,
|
||||
btype,
|
||||
player_id,
|
||||
Direction::Bottom,
|
||||
&state.constants,
|
||||
);
|
||||
state.create_caret(player.x + 0x200, player.y + 0x1000, CaretType::Shoot, Direction::Left);
|
||||
}
|
||||
Direction::Left => {
|
||||
bullet_manager.create_bullet(player.x - 0xc00, player.y + 0x600, btype, player_id, Direction::Left, &state.constants);
|
||||
bullet_manager.create_bullet(
|
||||
player.x - 0xc00,
|
||||
player.y + 0x600,
|
||||
btype,
|
||||
player_id,
|
||||
Direction::Left,
|
||||
&state.constants,
|
||||
);
|
||||
state.create_caret(player.x - 0xc00, player.y + 0x600, CaretType::Shoot, Direction::Left);
|
||||
}
|
||||
Direction::Right => {
|
||||
bullet_manager.create_bullet(player.x + 0xc00, player.y + 0x600, btype, player_id, Direction::Right, &state.constants);
|
||||
bullet_manager.create_bullet(
|
||||
player.x + 0xc00,
|
||||
player.y + 0x600,
|
||||
btype,
|
||||
player_id,
|
||||
Direction::Right,
|
||||
&state.constants,
|
||||
);
|
||||
state.create_caret(player.x + 0xc00, player.y + 0x600, CaretType::Shoot, Direction::Right);
|
||||
}
|
||||
_ => {}
|
||||
|
|
Loading…
Reference in a new issue