mirror of
https://github.com/doukutsu-rs/doukutsu-rs
synced 2025-12-01 17:00:43 +00:00
add gamepad rumble
This commit is contained in:
parent
7b359ae4c1
commit
290068dd37
|
|
@ -3,8 +3,16 @@ use std::collections::{HashMap, HashSet};
|
||||||
use sdl2::controller::GameController;
|
use sdl2::controller::GameController;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::shared_game_state::SharedGameState;
|
||||||
use crate::{common::Rect, engine_constants::EngineConstants, framework::context::Context};
|
use crate::{common::Rect, engine_constants::EngineConstants, framework::context::Context};
|
||||||
|
|
||||||
|
use crate::framework::error::GameResult;
|
||||||
|
|
||||||
|
const QUAKE_RUMBLE_LOW_FREQ: u16 = 0x3000;
|
||||||
|
const QUAKE_RUMBLE_HI_FREQ: u16 = 0;
|
||||||
|
const SUPER_QUAKE_RUMBLE_LOW_FREQ: u16 = 0x5000;
|
||||||
|
const SUPER_QUAKE_RUMBLE_HI_FREQ: u16 = 0;
|
||||||
|
|
||||||
#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
|
#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
pub enum Axis {
|
pub enum Axis {
|
||||||
|
|
@ -186,6 +194,12 @@ impl GamepadData {
|
||||||
|
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_rumble(&mut self, state: &SharedGameState, low_freq: u16, hi_freq: u16, ticks: u32) -> GameResult {
|
||||||
|
let duration_ms = (ticks as f32 / state.settings.timing_mode.get_tps() as f32 * 1000.0) as u32;
|
||||||
|
self.controller.set_rumble(low_freq, hi_freq, duration_ms);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GamepadContext {
|
pub struct GamepadContext {
|
||||||
|
|
@ -209,6 +223,10 @@ impl GamepadContext {
|
||||||
self.gamepads.iter_mut().find(|gamepad| gamepad.controller.instance_id() == gamepad_id)
|
self.gamepads.iter_mut().find(|gamepad| gamepad.controller.instance_id() == gamepad_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_gamepad_by_index_mut(&mut self, gamepad_index: usize) -> Option<&mut GamepadData> {
|
||||||
|
self.gamepads.get_mut(gamepad_index)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn add_gamepad(&mut self, game_controller: GameController, axis_sensitivity: f64) {
|
pub(crate) fn add_gamepad(&mut self, game_controller: GameController, axis_sensitivity: f64) {
|
||||||
self.gamepads.push(GamepadData::new(game_controller, axis_sensitivity));
|
self.gamepads.push(GamepadData::new(game_controller, axis_sensitivity));
|
||||||
}
|
}
|
||||||
|
|
@ -323,6 +341,35 @@ impl GamepadContext {
|
||||||
|
|
||||||
HashMap::new()
|
HashMap::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn set_rumble(
|
||||||
|
&mut self,
|
||||||
|
gamepad_index: u32,
|
||||||
|
state: &SharedGameState,
|
||||||
|
low_freq: u16,
|
||||||
|
hi_freq: u16,
|
||||||
|
ticks: u32,
|
||||||
|
) -> GameResult {
|
||||||
|
if let Some(gamepad) = self.get_gamepad_by_index_mut(gamepad_index as usize) {
|
||||||
|
gamepad.set_rumble(state, low_freq, hi_freq, ticks)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn set_rumble_all(
|
||||||
|
&mut self,
|
||||||
|
state: &SharedGameState,
|
||||||
|
low_freq: u16,
|
||||||
|
hi_freq: u16,
|
||||||
|
ticks: u32,
|
||||||
|
) -> GameResult {
|
||||||
|
for gamepad in self.gamepads.iter_mut() {
|
||||||
|
gamepad.set_rumble(state, low_freq, hi_freq, ticks)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for GamepadContext {
|
impl Default for GamepadContext {
|
||||||
|
|
@ -370,3 +417,45 @@ pub fn pressed_buttons(ctx: &Context, gamepad_index: u32) -> HashSet<Button> {
|
||||||
pub fn active_axes(ctx: &Context, gamepad_index: u32) -> HashMap<Axis, f64> {
|
pub fn active_axes(ctx: &Context, gamepad_index: u32) -> HashMap<Axis, f64> {
|
||||||
ctx.gamepad_context.active_axes(gamepad_index)
|
ctx.gamepad_context.active_axes(gamepad_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_rumble(
|
||||||
|
ctx: &mut Context,
|
||||||
|
state: &SharedGameState,
|
||||||
|
gamepad_index: u32,
|
||||||
|
low_freq: u16,
|
||||||
|
hi_freq: u16,
|
||||||
|
ticks: u32,
|
||||||
|
) -> GameResult {
|
||||||
|
ctx.gamepad_context.set_rumble(gamepad_index, state, low_freq, hi_freq, ticks)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_rumble_all(
|
||||||
|
ctx: &mut Context,
|
||||||
|
state: &SharedGameState,
|
||||||
|
low_freq: u16,
|
||||||
|
hi_freq: u16,
|
||||||
|
ticks: u32,
|
||||||
|
) -> GameResult {
|
||||||
|
ctx.gamepad_context.set_rumble_all(state, low_freq, hi_freq, ticks)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_quake_rumble(ctx: &mut Context, state: &SharedGameState, gamepad_index: u32, ticks: u32) -> GameResult {
|
||||||
|
set_rumble(ctx, state, gamepad_index, QUAKE_RUMBLE_LOW_FREQ, QUAKE_RUMBLE_HI_FREQ, ticks)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_quake_rumble_all(ctx: &mut Context, state: &SharedGameState, ticks: u32) -> GameResult {
|
||||||
|
set_rumble_all(ctx, state, QUAKE_RUMBLE_LOW_FREQ, QUAKE_RUMBLE_LOW_FREQ, ticks)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_super_quake_rumble(
|
||||||
|
ctx: &mut Context,
|
||||||
|
state: &SharedGameState,
|
||||||
|
gamepad_index: u32,
|
||||||
|
ticks: u32,
|
||||||
|
) -> GameResult {
|
||||||
|
set_rumble(ctx, state, gamepad_index, SUPER_QUAKE_RUMBLE_LOW_FREQ, SUPER_QUAKE_RUMBLE_HI_FREQ, ticks)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_super_quake_rumble_all(ctx: &mut Context, state: &SharedGameState, ticks: u32) -> GameResult {
|
||||||
|
set_rumble_all(ctx, state, SUPER_QUAKE_RUMBLE_LOW_FREQ, SUPER_QUAKE_RUMBLE_LOW_FREQ, ticks)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -166,4 +166,10 @@ impl PlayerController for CombinedPlayerController {
|
||||||
fn move_analog_y(&self) -> f64 {
|
fn move_analog_y(&self) -> f64 {
|
||||||
self.controllers.iter().fold(0.0, |acc, cont| acc + cont.move_analog_y()) / self.controllers.len() as f64
|
self.controllers.iter().fold(0.0, |acc, cont| acc + cont.move_analog_y()) / self.controllers.len() as f64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_rumble(&mut self, low_freq: u16, hi_freq: u16, ticks: u32) {
|
||||||
|
for cont in &mut self.controllers {
|
||||||
|
cont.set_rumble(low_freq, hi_freq, ticks);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -151,4 +151,6 @@ impl PlayerController for DummyPlayerController {
|
||||||
fn move_analog_y(&self) -> f64 {
|
fn move_analog_y(&self) -> f64 {
|
||||||
0.0
|
0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_rumble(&mut self, _low_freq: u16, _hi_freq: u16, _ticks: u32) {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,11 +35,32 @@ pub struct GamepadController {
|
||||||
state: KeyState,
|
state: KeyState,
|
||||||
old_state: KeyState,
|
old_state: KeyState,
|
||||||
trigger: KeyState,
|
trigger: KeyState,
|
||||||
|
rumble_state: Option<RumbleState>,
|
||||||
|
rumble_enabled: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct RumbleState {
|
||||||
|
pub low_freq: u16,
|
||||||
|
pub hi_freq: u16,
|
||||||
|
pub ticks: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GamepadController {
|
impl GamepadController {
|
||||||
pub fn new(gamepad_id: u32, target: TargetPlayer) -> GamepadController {
|
pub fn new(gamepad_id: u32, target: TargetPlayer) -> GamepadController {
|
||||||
GamepadController { gamepad_id, target, state: KeyState(0), old_state: KeyState(0), trigger: KeyState(0) }
|
GamepadController {
|
||||||
|
gamepad_id,
|
||||||
|
target,
|
||||||
|
state: KeyState(0),
|
||||||
|
old_state: KeyState(0),
|
||||||
|
trigger: KeyState(0),
|
||||||
|
rumble_state: None,
|
||||||
|
rumble_enabled: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_rumble_enabled(&mut self, enabled: bool) {
|
||||||
|
self.rumble_enabled = enabled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -70,6 +91,18 @@ impl PlayerController for GamepadController {
|
||||||
self.state.set_menu_ok(gamepad::is_active(ctx, self.gamepad_id, &button_map.menu_ok));
|
self.state.set_menu_ok(gamepad::is_active(ctx, self.gamepad_id, &button_map.menu_ok));
|
||||||
self.state.set_menu_back(gamepad::is_active(ctx, self.gamepad_id, &button_map.menu_back));
|
self.state.set_menu_back(gamepad::is_active(ctx, self.gamepad_id, &button_map.menu_back));
|
||||||
|
|
||||||
|
if let Some(rumble_data) = &self.rumble_state {
|
||||||
|
gamepad::set_rumble(
|
||||||
|
ctx,
|
||||||
|
state,
|
||||||
|
self.gamepad_id,
|
||||||
|
rumble_data.low_freq,
|
||||||
|
rumble_data.hi_freq,
|
||||||
|
rumble_data.ticks,
|
||||||
|
)?;
|
||||||
|
self.rumble_state = None;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -227,4 +260,16 @@ impl PlayerController for GamepadController {
|
||||||
0.0
|
0.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_rumble(&mut self, low_freq: u16, hi_freq: u16, ticks: u32) {
|
||||||
|
if !self.rumble_enabled {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.rumble_state.is_none() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.rumble_state = Some(RumbleState { low_freq, hi_freq, ticks });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -225,4 +225,6 @@ impl PlayerController for KeyboardController {
|
||||||
0.0
|
0.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_rumble(&mut self, _low_freq: u16, _hi_freq: u16, _ticks: u32) {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,9 @@ pub trait PlayerController: PlayerControllerClone {
|
||||||
/// Returns movement analog stick state in Y axis within (-1.0..=1.0) range
|
/// Returns movement analog stick state in Y axis within (-1.0..=1.0) range
|
||||||
/// In case of non-analog controllers this should return -1.0, 0.0 or 1.0, depending on keys pressed.
|
/// In case of non-analog controllers this should return -1.0, 0.0 or 1.0, depending on keys pressed.
|
||||||
fn move_analog_y(&self) -> f64;
|
fn move_analog_y(&self) -> f64;
|
||||||
|
|
||||||
|
/// Activates the rumble motors to the specified intensities for a given amount of time (in millis).
|
||||||
|
fn set_rumble(&mut self, low_freq: u16, hi_freq: u16, ticks: u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait PlayerControllerClone {
|
pub trait PlayerControllerClone {
|
||||||
|
|
|
||||||
|
|
@ -206,4 +206,6 @@ impl PlayerController for ReplayController {
|
||||||
0.0
|
0.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_rumble(&mut self, _low_freq: u16, _hi_freq: u16, _ticks: u32) {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -401,4 +401,8 @@ impl PlayerController for TouchPlayerController {
|
||||||
0.0
|
0.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_rumble(&mut self, _low_freq: u16, _hi_freq: u16, _ticks: u32) {
|
||||||
|
// we could probably vibrate the phone? do mobile games do that?
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ enum MainMenuEntry {
|
||||||
SelectedPlayer,
|
SelectedPlayer,
|
||||||
Controller,
|
Controller,
|
||||||
Rebind,
|
Rebind,
|
||||||
|
Rumble,
|
||||||
Back,
|
Back,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -210,6 +211,7 @@ impl ControlsMenu {
|
||||||
self.main
|
self.main
|
||||||
.push_entry(MainMenuEntry::Controller, MenuEntry::Active(state.t("menus.controls_menu.controller.entry")));
|
.push_entry(MainMenuEntry::Controller, MenuEntry::Active(state.t("menus.controls_menu.controller.entry")));
|
||||||
self.main.push_entry(MainMenuEntry::Rebind, MenuEntry::Active(state.t("menus.controls_menu.rebind")));
|
self.main.push_entry(MainMenuEntry::Rebind, MenuEntry::Active(state.t("menus.controls_menu.rebind")));
|
||||||
|
self.main.push_entry(MainMenuEntry::Rumble, MenuEntry::Hidden);
|
||||||
self.main.push_entry(MainMenuEntry::Back, MenuEntry::Active(state.t("common.back")));
|
self.main.push_entry(MainMenuEntry::Back, MenuEntry::Active(state.t("common.back")));
|
||||||
|
|
||||||
self.confirm_reset.push_entry(
|
self.confirm_reset.push_entry(
|
||||||
|
|
@ -417,14 +419,22 @@ impl ControlsMenu {
|
||||||
Player::Player2 => state.settings.player2_controller_type,
|
Player::Player2 => state.settings.player2_controller_type,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let rumble = match self.selected_player {
|
||||||
|
Player::Player1 => state.settings.player1_rumble,
|
||||||
|
Player::Player2 => state.settings.player2_rumble,
|
||||||
|
};
|
||||||
|
|
||||||
if let ControllerType::Gamepad(index) = controller_type {
|
if let ControllerType::Gamepad(index) = controller_type {
|
||||||
if index as usize >= available_gamepads {
|
if index as usize >= available_gamepads {
|
||||||
self.selected_controller = ControllerType::Keyboard;
|
self.selected_controller = ControllerType::Keyboard;
|
||||||
|
self.main.set_entry(MainMenuEntry::Rumble, MenuEntry::Hidden);
|
||||||
} else {
|
} else {
|
||||||
self.selected_controller = controller_type;
|
self.selected_controller = controller_type;
|
||||||
|
self.main.set_entry(MainMenuEntry::Rumble, MenuEntry::Toggle("Rumble".to_string(), rumble));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.selected_controller = controller_type;
|
self.selected_controller = controller_type;
|
||||||
|
self.main.set_entry(MainMenuEntry::Rumble, MenuEntry::Hidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.selected_controller {
|
match self.selected_controller {
|
||||||
|
|
@ -887,6 +897,50 @@ impl ControlsMenu {
|
||||||
MenuSelectionResult::Selected(MainMenuEntry::Rebind, _) => {
|
MenuSelectionResult::Selected(MainMenuEntry::Rebind, _) => {
|
||||||
self.current = CurrentMenu::RebindMenu;
|
self.current = CurrentMenu::RebindMenu;
|
||||||
}
|
}
|
||||||
|
MenuSelectionResult::Selected(MainMenuEntry::Rumble, toggle) => {
|
||||||
|
if let MenuEntry::Toggle(_, value) = toggle {
|
||||||
|
match self.selected_player {
|
||||||
|
Player::Player1 => {
|
||||||
|
state.settings.player1_rumble = !state.settings.player1_rumble;
|
||||||
|
|
||||||
|
if state.settings.player1_rumble {
|
||||||
|
if let ControllerType::Gamepad(idx) = self.selected_controller {
|
||||||
|
gamepad::set_rumble(
|
||||||
|
ctx,
|
||||||
|
state,
|
||||||
|
idx,
|
||||||
|
0,
|
||||||
|
0x5000,
|
||||||
|
(state.settings.timing_mode.get_tps() / 2) as u32,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*value = state.settings.player1_rumble;
|
||||||
|
}
|
||||||
|
Player::Player2 => {
|
||||||
|
state.settings.player2_rumble = !state.settings.player2_rumble;
|
||||||
|
|
||||||
|
if state.settings.player2_rumble {
|
||||||
|
if let ControllerType::Gamepad(idx) = self.selected_controller {
|
||||||
|
gamepad::set_rumble(
|
||||||
|
ctx,
|
||||||
|
state,
|
||||||
|
idx,
|
||||||
|
0,
|
||||||
|
0x5000,
|
||||||
|
(state.settings.timing_mode.get_tps() / 2) as u32,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*value = state.settings.player2_rumble;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state.settings.save(ctx)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
MenuSelectionResult::Selected(MainMenuEntry::Back, _) | MenuSelectionResult::Canceled => exit_action(),
|
MenuSelectionResult::Selected(MainMenuEntry::Back, _) | MenuSelectionResult::Canceled => exit_action(),
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ impl NPC {
|
||||||
|
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
state.quake_counter = 30;
|
state.quake_counter = 30;
|
||||||
|
state.quake_rumble_counter = 30;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
|
|
@ -151,6 +152,7 @@ impl NPC {
|
||||||
|
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
state.quake_counter = 30;
|
state.quake_counter = 30;
|
||||||
|
state.quake_rumble_counter = 30;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
5 => {
|
5 => {
|
||||||
|
|
@ -276,6 +278,7 @@ impl NPC {
|
||||||
self.spritesheet_id = 20; // NpcSym
|
self.spritesheet_id = 20; // NpcSym
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
state.quake_counter = 30;
|
state.quake_counter = 30;
|
||||||
|
state.quake_rumble_counter = 30;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
20 | 21 => {
|
20 | 21 => {
|
||||||
|
|
@ -474,6 +477,7 @@ impl NPC {
|
||||||
if y <= 34 && stage.change_tile(x, y, 0) {
|
if y <= 34 && stage.change_tile(x, y, 0) {
|
||||||
state.sound_manager.play_sfx(44);
|
state.sound_manager.play_sfx(44);
|
||||||
state.super_quake_counter = 10;
|
state.super_quake_counter = 10;
|
||||||
|
state.super_quake_rumble_counter = 10;
|
||||||
|
|
||||||
let mut npc = NPC::create(4, &state.npc_table);
|
let mut npc = NPC::create(4, &state.npc_table);
|
||||||
npc.cond.set_alive(true);
|
npc.cond.set_alive(true);
|
||||||
|
|
@ -499,6 +503,7 @@ impl NPC {
|
||||||
if self.y < -32 * 0x200 {
|
if self.y < -32 * 0x200 {
|
||||||
self.npc_type = 0;
|
self.npc_type = 0;
|
||||||
state.quake_counter = 30;
|
state.quake_counter = 30;
|
||||||
|
state.quake_rumble_counter = 30;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
|
|
@ -555,6 +560,7 @@ impl NPC {
|
||||||
state.sound_manager.play_sfx(12);
|
state.sound_manager.play_sfx(12);
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
state.quake_counter = 30;
|
state.quake_counter = 30;
|
||||||
|
state.quake_rumble_counter = 30;
|
||||||
|
|
||||||
self.y += 0x1400;
|
self.y += 0x1400;
|
||||||
self.action_num = 1;
|
self.action_num = 1;
|
||||||
|
|
@ -571,6 +577,7 @@ impl NPC {
|
||||||
|
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
state.quake_counter = 30;
|
state.quake_counter = 30;
|
||||||
|
state.quake_rumble_counter = 30;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
|
|
@ -751,6 +758,7 @@ impl NPC {
|
||||||
state.sound_manager.play_sfx(25);
|
state.sound_manager.play_sfx(25);
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
state.quake_counter = 30;
|
state.quake_counter = 30;
|
||||||
|
state.quake_rumble_counter = 30;
|
||||||
|
|
||||||
let mut npc_smoke = NPC::create(4, &state.npc_table);
|
let mut npc_smoke = NPC::create(4, &state.npc_table);
|
||||||
npc_smoke.cond.set_alive(true);
|
npc_smoke.cond.set_alive(true);
|
||||||
|
|
@ -887,6 +895,7 @@ impl NPC {
|
||||||
self.action_num = 9;
|
self.action_num = 9;
|
||||||
self.anim_num = 8;
|
self.anim_num = 8;
|
||||||
state.quake_counter = 30;
|
state.quake_counter = 30;
|
||||||
|
state.quake_rumble_counter = 30;
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1107,6 +1116,7 @@ impl NPC {
|
||||||
self.action_num = 9;
|
self.action_num = 9;
|
||||||
self.anim_num = 8;
|
self.anim_num = 8;
|
||||||
state.quake_counter = 30;
|
state.quake_counter = 30;
|
||||||
|
state.quake_rumble_counter = 30;
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
}
|
}
|
||||||
if self.action_counter > 7
|
if self.action_counter > 7
|
||||||
|
|
|
||||||
|
|
@ -658,6 +658,7 @@ impl NPC {
|
||||||
{
|
{
|
||||||
self.anim_num = 6;
|
self.anim_num = 6;
|
||||||
state.quake_counter = 10;
|
state.quake_counter = 10;
|
||||||
|
state.quake_rumble_counter = 10;
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
|
|
||||||
player.damage(5, state, npc_list);
|
player.damage(5, state, npc_list);
|
||||||
|
|
@ -741,6 +742,7 @@ impl NPC {
|
||||||
self.action_counter = 0;
|
self.action_counter = 0;
|
||||||
|
|
||||||
state.quake_counter = 10;
|
state.quake_counter = 10;
|
||||||
|
state.quake_rumble_counter = 10;
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -938,6 +940,7 @@ impl NPC {
|
||||||
}
|
}
|
||||||
|
|
||||||
state.quake_counter = 2;
|
state.quake_counter = 2;
|
||||||
|
state.quake_rumble_counter = 2;
|
||||||
self.action_counter += 1;
|
self.action_counter += 1;
|
||||||
if self.action_counter % 6 == 3 {
|
if self.action_counter % 6 == 3 {
|
||||||
state.sound_manager.play_sfx(25);
|
state.sound_manager.play_sfx(25);
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ impl NPC {
|
||||||
if self.anim_num > 6 {
|
if self.anim_num > 6 {
|
||||||
self.anim_num = 5;
|
self.anim_num = 5;
|
||||||
state.quake_counter = 8;
|
state.quake_counter = 8;
|
||||||
|
state.quake_rumble_counter = 8;
|
||||||
|
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
|
|
||||||
|
|
@ -1069,6 +1070,7 @@ impl NPC {
|
||||||
self.cond.set_explode_die(true);
|
self.cond.set_explode_die(true);
|
||||||
|
|
||||||
state.quake_counter = 20;
|
state.quake_counter = 20;
|
||||||
|
state.quake_rumble_counter = 20;
|
||||||
state.sound_manager.play_sfx(35);
|
state.sound_manager.play_sfx(35);
|
||||||
npc_list.create_death_smoke(self.x, self.y, 0x10000, 100 as usize, state, &self.rng);
|
npc_list.create_death_smoke(self.x, self.y, 0x10000, 100 as usize, state, &self.rng);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,7 @@ impl NPC {
|
||||||
|
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
state.quake_counter = 30;
|
state.quake_counter = 30;
|
||||||
|
state.quake_rumble_counter = 30;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
|
|
|
||||||
|
|
@ -809,6 +809,7 @@ impl NPC {
|
||||||
self.cond.set_explode_die(true);
|
self.cond.set_explode_die(true);
|
||||||
|
|
||||||
state.quake_counter = 10;
|
state.quake_counter = 10;
|
||||||
|
state.quake_rumble_counter = 10;
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
npc_list.create_death_smoke(self.x, self.y, 0x6000, 40 as usize, state, &self.rng);
|
npc_list.create_death_smoke(self.x, self.y, 0x6000, 40 as usize, state, &self.rng);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -188,6 +188,7 @@ impl NPC {
|
||||||
|
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
state.quake_counter = 30;
|
state.quake_counter = 30;
|
||||||
|
state.quake_rumble_counter = 30;
|
||||||
|
|
||||||
let mut npc = NPC::create(4, &state.npc_table);
|
let mut npc = NPC::create(4, &state.npc_table);
|
||||||
npc.cond.set_alive(true);
|
npc.cond.set_alive(true);
|
||||||
|
|
@ -459,6 +460,7 @@ impl NPC {
|
||||||
self.action_num = 40;
|
self.action_num = 40;
|
||||||
self.action_counter = 0;
|
self.action_counter = 0;
|
||||||
state.quake_counter = 20;
|
state.quake_counter = 20;
|
||||||
|
state.quake_rumble_counter = 20;
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -376,6 +376,7 @@ impl NPC {
|
||||||
self.action_counter = 0;
|
self.action_counter = 0;
|
||||||
self.anim_num = 2;
|
self.anim_num = 2;
|
||||||
state.quake_counter = 10;
|
state.quake_counter = 10;
|
||||||
|
state.quake_rumble_counter = 10;
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -396,6 +397,7 @@ impl NPC {
|
||||||
self.action_counter = 0;
|
self.action_counter = 0;
|
||||||
self.anim_num = 2;
|
self.anim_num = 2;
|
||||||
state.quake_counter = 10;
|
state.quake_counter = 10;
|
||||||
|
state.quake_rumble_counter = 10;
|
||||||
state.sound_manager.play_sfx(72);
|
state.sound_manager.play_sfx(72);
|
||||||
self.create_xp_drop_custom(self.x, self.y, 19, state, npc_list);
|
self.create_xp_drop_custom(self.x, self.y, 19, state, npc_list);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -554,6 +554,7 @@ impl NPC {
|
||||||
self.action_num = 3;
|
self.action_num = 3;
|
||||||
self.action_counter = 0;
|
self.action_counter = 0;
|
||||||
state.quake_counter = 30;
|
state.quake_counter = 30;
|
||||||
|
state.quake_rumble_counter = 30;
|
||||||
|
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
state.sound_manager.play_sfx(72);
|
state.sound_manager.play_sfx(72);
|
||||||
|
|
@ -747,6 +748,7 @@ impl NPC {
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
state.quake_counter = 2;
|
state.quake_counter = 2;
|
||||||
|
state.quake_rumble_counter = 2;
|
||||||
self.action_counter3 += 1;
|
self.action_counter3 += 1;
|
||||||
if self.action_counter3 > 240 {
|
if self.action_counter3 > 240 {
|
||||||
self.anim_num = 2;
|
self.anim_num = 2;
|
||||||
|
|
@ -891,6 +893,7 @@ impl NPC {
|
||||||
if self.action_counter != 0 && self.flags.hit_bottom_wall() {
|
if self.action_counter != 0 && self.flags.hit_bottom_wall() {
|
||||||
state.sound_manager.play_sfx(35);
|
state.sound_manager.play_sfx(35);
|
||||||
state.quake_counter = 40;
|
state.quake_counter = 40;
|
||||||
|
state.quake_rumble_counter = 40;
|
||||||
self.action_num = 0;
|
self.action_num = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1403,6 +1406,7 @@ impl NPC {
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
}
|
}
|
||||||
state.quake_counter = 20;
|
state.quake_counter = 20;
|
||||||
|
state.quake_rumble_counter = 20;
|
||||||
}
|
}
|
||||||
20 => {
|
20 => {
|
||||||
let mut npc = NPC::create(4, &state.npc_table);
|
let mut npc = NPC::create(4, &state.npc_table);
|
||||||
|
|
|
||||||
|
|
@ -569,6 +569,7 @@ impl NPC {
|
||||||
self.action_num = 221;
|
self.action_num = 221;
|
||||||
self.action_counter = 0;
|
self.action_counter = 0;
|
||||||
state.quake_counter = 16;
|
state.quake_counter = 16;
|
||||||
|
state.quake_rumble_counter = 16;
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
self.damage = 4
|
self.damage = 4
|
||||||
}
|
}
|
||||||
|
|
@ -639,6 +640,7 @@ impl NPC {
|
||||||
self.action_num = 331;
|
self.action_num = 331;
|
||||||
self.action_counter = 0;
|
self.action_counter = 0;
|
||||||
state.quake_counter = 16;
|
state.quake_counter = 16;
|
||||||
|
state.quake_rumble_counter = 16;
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -740,6 +742,7 @@ impl NPC {
|
||||||
self.npc_flags.set_ignore_solidity(true);
|
self.npc_flags.set_ignore_solidity(true);
|
||||||
state.sound_manager.play_sfx(12);
|
state.sound_manager.play_sfx(12);
|
||||||
state.quake_counter = 10;
|
state.quake_counter = 10;
|
||||||
|
state.quake_rumble_counter = 10;
|
||||||
|
|
||||||
let mut npc = NPC::create(4, &state.npc_table);
|
let mut npc = NPC::create(4, &state.npc_table);
|
||||||
npc.cond.set_alive(true);
|
npc.cond.set_alive(true);
|
||||||
|
|
|
||||||
|
|
@ -1013,6 +1013,7 @@ impl NPC {
|
||||||
}
|
}
|
||||||
|
|
||||||
state.quake_counter = 10;
|
state.quake_counter = 10;
|
||||||
|
state.quake_rumble_counter = 10;
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1185,6 +1186,7 @@ impl NPC {
|
||||||
self.action_num = 20;
|
self.action_num = 20;
|
||||||
|
|
||||||
state.quake_counter = 10;
|
state.quake_counter = 10;
|
||||||
|
state.quake_rumble_counter = 10;
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
|
|
||||||
let mut npc = NPC::create(4, &state.npc_table);
|
let mut npc = NPC::create(4, &state.npc_table);
|
||||||
|
|
@ -1236,6 +1238,7 @@ impl NPC {
|
||||||
self.action_num = 10;
|
self.action_num = 10;
|
||||||
|
|
||||||
state.quake_counter = 10;
|
state.quake_counter = 10;
|
||||||
|
state.quake_rumble_counter = 10;
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
|
|
||||||
let mut npc = NPC::create(4, &state.npc_table);
|
let mut npc = NPC::create(4, &state.npc_table);
|
||||||
|
|
@ -1329,6 +1332,7 @@ impl NPC {
|
||||||
self.action_num = 20;
|
self.action_num = 20;
|
||||||
|
|
||||||
state.quake_counter = 10;
|
state.quake_counter = 10;
|
||||||
|
state.quake_rumble_counter = 10;
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
|
|
||||||
let mut npc = NPC::create(4, &state.npc_table);
|
let mut npc = NPC::create(4, &state.npc_table);
|
||||||
|
|
@ -1380,6 +1384,7 @@ impl NPC {
|
||||||
self.action_num = 10;
|
self.action_num = 10;
|
||||||
|
|
||||||
state.quake_counter = 10;
|
state.quake_counter = 10;
|
||||||
|
state.quake_rumble_counter = 10;
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
|
|
||||||
let mut npc = NPC::create(4, &state.npc_table);
|
let mut npc = NPC::create(4, &state.npc_table);
|
||||||
|
|
@ -1880,6 +1885,7 @@ impl NPC {
|
||||||
}
|
}
|
||||||
|
|
||||||
state.quake_counter = 10;
|
state.quake_counter = 10;
|
||||||
|
state.quake_rumble_counter = 10;
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2085,6 +2091,7 @@ impl NPC {
|
||||||
self.npc_flags.set_ignore_solidity(true);
|
self.npc_flags.set_ignore_solidity(true);
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
state.quake_counter = 10;
|
state.quake_counter = 10;
|
||||||
|
state.quake_rumble_counter = 10;
|
||||||
|
|
||||||
let mut npc = NPC::create(4, &state.npc_table);
|
let mut npc = NPC::create(4, &state.npc_table);
|
||||||
npc.cond.set_alive(true);
|
npc.cond.set_alive(true);
|
||||||
|
|
|
||||||
|
|
@ -1061,6 +1061,7 @@ impl NPC {
|
||||||
}
|
}
|
||||||
|
|
||||||
state.quake_counter = 20;
|
state.quake_counter = 20;
|
||||||
|
state.quake_rumble_counter = 20;
|
||||||
if self.action_counter % 8 == 0 {
|
if self.action_counter % 8 == 0 {
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -410,6 +410,7 @@ impl NPC {
|
||||||
self.anim_num = 2;
|
self.anim_num = 2;
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
state.quake_counter = 20;
|
state.quake_counter = 20;
|
||||||
|
state.quake_rumble_counter = 20;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
26 => {
|
26 => {
|
||||||
|
|
@ -479,6 +480,7 @@ impl NPC {
|
||||||
self.anim_num = 2;
|
self.anim_num = 2;
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
state.quake_counter = 20;
|
state.quake_counter = 20;
|
||||||
|
state.quake_rumble_counter = 20;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
102 => {
|
102 => {
|
||||||
|
|
|
||||||
|
|
@ -592,6 +592,7 @@ impl NPC {
|
||||||
}
|
}
|
||||||
|
|
||||||
state.quake_counter = 2;
|
state.quake_counter = 2;
|
||||||
|
state.quake_rumble_counter = 2;
|
||||||
|
|
||||||
self.action_counter += 1;
|
self.action_counter += 1;
|
||||||
if self.action_counter % 20 == 0 {
|
if self.action_counter % 20 == 0 {
|
||||||
|
|
|
||||||
|
|
@ -177,6 +177,7 @@ impl BossNPC {
|
||||||
}
|
}
|
||||||
|
|
||||||
state.quake_counter = 30;
|
state.quake_counter = 30;
|
||||||
|
state.quake_rumble_counter = 30;
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -357,6 +358,7 @@ impl BossNPC {
|
||||||
|
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
state.quake_counter = 60;
|
state.quake_counter = 60;
|
||||||
|
state.quake_rumble_counter = 60;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
130 | 131 => {
|
130 | 131 => {
|
||||||
|
|
@ -457,6 +459,7 @@ impl BossNPC {
|
||||||
|
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
state.quake_counter = 30;
|
state.quake_counter = 30;
|
||||||
|
state.quake_rumble_counter = 30;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
||||||
|
|
@ -321,6 +321,7 @@ impl NPC {
|
||||||
self.action_counter = 0;
|
self.action_counter = 0;
|
||||||
self.damage = 3;
|
self.damage = 3;
|
||||||
state.super_quake_counter = 10;
|
state.super_quake_counter = 10;
|
||||||
|
state.super_quake_rumble_counter = 10;
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -392,6 +393,7 @@ impl NPC {
|
||||||
let _ = npc_list.spawn(0x100, npc);
|
let _ = npc_list.spawn(0x100, npc);
|
||||||
|
|
||||||
state.super_quake_counter = 10;
|
state.super_quake_counter = 10;
|
||||||
|
state.super_quake_rumble_counter = 10;
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -950,6 +952,7 @@ impl NPC {
|
||||||
self.npc_flags.set_ignore_solidity(true);
|
self.npc_flags.set_ignore_solidity(true);
|
||||||
state.sound_manager.play_sfx(12);
|
state.sound_manager.play_sfx(12);
|
||||||
state.quake_counter = 10;
|
state.quake_counter = 10;
|
||||||
|
state.quake_rumble_counter = 10;
|
||||||
|
|
||||||
for _ in 0..4 {
|
for _ in 0..4 {
|
||||||
let mut npc = NPC::create(4, &state.npc_table);
|
let mut npc = NPC::create(4, &state.npc_table);
|
||||||
|
|
@ -1361,6 +1364,7 @@ impl NPC {
|
||||||
if self.action_counter > 100 {
|
if self.action_counter > 100 {
|
||||||
self.action_counter = 0;
|
self.action_counter = 0;
|
||||||
state.quake_counter = 20;
|
state.quake_counter = 20;
|
||||||
|
state.quake_rumble_counter = 20;
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
state.sound_manager.play_sfx(12);
|
state.sound_manager.play_sfx(12);
|
||||||
|
|
||||||
|
|
@ -1481,6 +1485,7 @@ impl BossNPC {
|
||||||
self.parts[0].action_num = 103;
|
self.parts[0].action_num = 103;
|
||||||
self.parts[0].action_counter = 0;
|
self.parts[0].action_counter = 0;
|
||||||
state.super_quake_counter = 30;
|
state.super_quake_counter = 30;
|
||||||
|
state.super_quake_rumble_counter = 30;
|
||||||
state.sound_manager.play_sfx(44);
|
state.sound_manager.play_sfx(44);
|
||||||
|
|
||||||
if player.y > self.parts[0].y + 0x6000
|
if player.y > self.parts[0].y + 0x6000
|
||||||
|
|
@ -1563,6 +1568,7 @@ impl BossNPC {
|
||||||
self.parts[0].action_num = 201;
|
self.parts[0].action_num = 201;
|
||||||
self.parts[0].action_counter = 0;
|
self.parts[0].action_counter = 0;
|
||||||
state.super_quake_counter = 30;
|
state.super_quake_counter = 30;
|
||||||
|
state.super_quake_rumble_counter = 30;
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
state.sound_manager.play_sfx(44);
|
state.sound_manager.play_sfx(44);
|
||||||
|
|
||||||
|
|
@ -1619,6 +1625,7 @@ impl BossNPC {
|
||||||
self.parts[0].action_num = 222;
|
self.parts[0].action_num = 222;
|
||||||
self.parts[0].action_counter = 0;
|
self.parts[0].action_counter = 0;
|
||||||
state.super_quake_counter = 30;
|
state.super_quake_counter = 30;
|
||||||
|
state.super_quake_rumble_counter = 30;
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
|
|
||||||
for _ in 0..16 {
|
for _ in 0..16 {
|
||||||
|
|
@ -1807,6 +1814,7 @@ impl BossNPC {
|
||||||
self.parts[0].action_counter = 0;
|
self.parts[0].action_counter = 0;
|
||||||
self.parts[0].anim_counter = 0;
|
self.parts[0].anim_counter = 0;
|
||||||
state.super_quake_counter = 30;
|
state.super_quake_counter = 30;
|
||||||
|
state.super_quake_rumble_counter = 30;
|
||||||
state.sound_manager.play_sfx(35);
|
state.sound_manager.play_sfx(35);
|
||||||
|
|
||||||
self.parts[1].action_num = 102;
|
self.parts[1].action_num = 102;
|
||||||
|
|
@ -1873,6 +1881,7 @@ impl BossNPC {
|
||||||
}
|
}
|
||||||
1002 => {
|
1002 => {
|
||||||
state.super_quake_counter = 40;
|
state.super_quake_counter = 40;
|
||||||
|
state.super_quake_rumble_counter = 30;
|
||||||
|
|
||||||
self.parts[0].action_counter += 1;
|
self.parts[0].action_counter += 1;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -279,6 +279,7 @@ impl BossNPC {
|
||||||
state.sound_manager.loop_sfx_freq(40, 1000.0 / 2205.0);
|
state.sound_manager.loop_sfx_freq(40, 1000.0 / 2205.0);
|
||||||
state.sound_manager.loop_sfx_freq(41, 1100.0 / 2205.0);
|
state.sound_manager.loop_sfx_freq(41, 1100.0 / 2205.0);
|
||||||
state.quake_counter = 100;
|
state.quake_counter = 100;
|
||||||
|
state.quake_rumble_counter = 100;
|
||||||
state.npc_super_pos.1 = 1;
|
state.npc_super_pos.1 = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -347,6 +348,7 @@ impl BossNPC {
|
||||||
self.parts[7].action_num = 200;
|
self.parts[7].action_num = 200;
|
||||||
|
|
||||||
state.quake_counter = 20;
|
state.quake_counter = 20;
|
||||||
|
state.quake_rumble_counter = 20;
|
||||||
|
|
||||||
state.sound_manager.stop_sfx(40);
|
state.sound_manager.stop_sfx(40);
|
||||||
state.sound_manager.stop_sfx(41);
|
state.sound_manager.stop_sfx(41);
|
||||||
|
|
@ -406,6 +408,7 @@ impl BossNPC {
|
||||||
|
|
||||||
if flag {
|
if flag {
|
||||||
state.quake_counter = 20;
|
state.quake_counter = 20;
|
||||||
|
state.quake_rumble_counter = 20;
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
|
|
||||||
self.parts[1].action_num = 100;
|
self.parts[1].action_num = 100;
|
||||||
|
|
|
||||||
|
|
@ -295,6 +295,7 @@ impl BossNPC {
|
||||||
self.parts[0].target_x = self.parts[0].x;
|
self.parts[0].target_x = self.parts[0].x;
|
||||||
self.parts[0].target_y = self.parts[0].y;
|
self.parts[0].target_y = self.parts[0].y;
|
||||||
state.quake_counter = 20;
|
state.quake_counter = 20;
|
||||||
|
state.quake_rumble_counter = 20;
|
||||||
for _ in 0..32 {
|
for _ in 0..32 {
|
||||||
let mut npc = NPC::create(4, &state.npc_table);
|
let mut npc = NPC::create(4, &state.npc_table);
|
||||||
npc.cond.set_alive(true);
|
npc.cond.set_alive(true);
|
||||||
|
|
|
||||||
|
|
@ -456,6 +456,7 @@ impl BossNPC {
|
||||||
}
|
}
|
||||||
1000 => {
|
1000 => {
|
||||||
state.quake_counter = 2;
|
state.quake_counter = 2;
|
||||||
|
state.quake_rumble_counter = 2;
|
||||||
|
|
||||||
self.parts[0].action_counter += 1;
|
self.parts[0].action_counter += 1;
|
||||||
if self.parts[0].action_counter % 8 == 0 {
|
if self.parts[0].action_counter % 8 == 0 {
|
||||||
|
|
@ -477,6 +478,7 @@ impl BossNPC {
|
||||||
}
|
}
|
||||||
1001 => {
|
1001 => {
|
||||||
state.quake_counter = 40;
|
state.quake_counter = 40;
|
||||||
|
state.quake_rumble_counter = 40;
|
||||||
self.parts[0].action_counter += 1;
|
self.parts[0].action_counter += 1;
|
||||||
|
|
||||||
if self.parts[0].action_counter > 50 {
|
if self.parts[0].action_counter > 50 {
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,7 @@ impl BossNPC {
|
||||||
self.parts[0].y -= 0x200;
|
self.parts[0].y -= 0x200;
|
||||||
self.parts[0].action_counter += 1;
|
self.parts[0].action_counter += 1;
|
||||||
state.quake_counter = 2;
|
state.quake_counter = 2;
|
||||||
|
state.quake_rumble_counter = 2;
|
||||||
|
|
||||||
if self.parts[0].action_counter % 4 == 0 {
|
if self.parts[0].action_counter % 4 == 0 {
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
|
|
@ -215,6 +216,8 @@ impl BossNPC {
|
||||||
}
|
}
|
||||||
90 => {
|
90 => {
|
||||||
state.quake_counter = 2;
|
state.quake_counter = 2;
|
||||||
|
state.quake_rumble_counter = 2;
|
||||||
|
|
||||||
self.parts[0].y += 0x200;
|
self.parts[0].y += 0x200;
|
||||||
self.parts[0].action_counter += 1;
|
self.parts[0].action_counter += 1;
|
||||||
|
|
||||||
|
|
@ -321,10 +324,12 @@ impl BossNPC {
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
state.sound_manager.play_sfx(12);
|
state.sound_manager.play_sfx(12);
|
||||||
state.quake_counter = 30;
|
state.quake_counter = 30;
|
||||||
|
state.quake_rumble_counter = 30;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
150 => {
|
150 => {
|
||||||
state.quake_counter = 2;
|
state.quake_counter = 2;
|
||||||
|
state.quake_rumble_counter = 2;
|
||||||
|
|
||||||
self.parts[0].action_counter += 1;
|
self.parts[0].action_counter += 1;
|
||||||
if self.parts[0].action_counter % 12 == 0 {
|
if self.parts[0].action_counter % 12 == 0 {
|
||||||
|
|
@ -345,6 +350,7 @@ impl BossNPC {
|
||||||
}
|
}
|
||||||
160 => {
|
160 => {
|
||||||
state.quake_counter = 40;
|
state.quake_counter = 40;
|
||||||
|
state.quake_rumble_counter = 40;
|
||||||
|
|
||||||
self.parts[0].action_counter += 1;
|
self.parts[0].action_counter += 1;
|
||||||
if self.parts[0].action_counter > 50 {
|
if self.parts[0].action_counter > 50 {
|
||||||
|
|
|
||||||
|
|
@ -526,6 +526,7 @@ impl BossNPC {
|
||||||
self.parts[19].action_counter = self.parts[0].life;
|
self.parts[19].action_counter = self.parts[0].life;
|
||||||
|
|
||||||
state.quake_counter = 100;
|
state.quake_counter = 100;
|
||||||
|
state.quake_rumble_counter = 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.parts[0].action_counter += 1;
|
self.parts[0].action_counter += 1;
|
||||||
|
|
@ -665,6 +666,7 @@ impl BossNPC {
|
||||||
self.parts[7].action_num = 5;
|
self.parts[7].action_num = 5;
|
||||||
|
|
||||||
state.quake_counter = 20;
|
state.quake_counter = 20;
|
||||||
|
state.quake_rumble_counter = 20;
|
||||||
|
|
||||||
let mut npc = NPC::create(4, &state.npc_table);
|
let mut npc = NPC::create(4, &state.npc_table);
|
||||||
npc.cond.set_alive(true);
|
npc.cond.set_alive(true);
|
||||||
|
|
@ -709,6 +711,7 @@ impl BossNPC {
|
||||||
}
|
}
|
||||||
1000 => {
|
1000 => {
|
||||||
state.quake_counter = 100;
|
state.quake_counter = 100;
|
||||||
|
state.quake_rumble_counter = 100;
|
||||||
|
|
||||||
self.parts[0].action_counter += 1;
|
self.parts[0].action_counter += 1;
|
||||||
if self.parts[0].action_counter % 8 == 0 {
|
if self.parts[0].action_counter % 8 == 0 {
|
||||||
|
|
@ -734,6 +737,8 @@ impl BossNPC {
|
||||||
}
|
}
|
||||||
1001 => {
|
1001 => {
|
||||||
state.quake_counter = 40;
|
state.quake_counter = 40;
|
||||||
|
state.quake_rumble_counter = 40;
|
||||||
|
|
||||||
self.parts[0].action_counter += 1;
|
self.parts[0].action_counter += 1;
|
||||||
if self.parts[0].action_counter > 50 {
|
if self.parts[0].action_counter > 50 {
|
||||||
for i in 0..20 {
|
for i in 0..20 {
|
||||||
|
|
@ -749,6 +754,8 @@ impl BossNPC {
|
||||||
|
|
||||||
if v19 {
|
if v19 {
|
||||||
state.quake_counter = 20;
|
state.quake_counter = 20;
|
||||||
|
state.quake_rumble_counter = 20;
|
||||||
|
|
||||||
state.sound_manager.play_sfx(26);
|
state.sound_manager.play_sfx(26);
|
||||||
|
|
||||||
if self.parts[0].action_num == 201 {
|
if self.parts[0].action_num == 201 {
|
||||||
|
|
|
||||||
|
|
@ -889,6 +889,10 @@ impl Player {
|
||||||
self.stars -= 1;
|
self.stars -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let rumble_intensity =
|
||||||
|
(0x4000 + ((1.0 - (self.life as f32 / self.max_life as f32)) * 0x2000 as f32) as i32).min(0xFFFF) as u16;
|
||||||
|
self.controller.set_rumble(rumble_intensity, rumble_intensity, 20);
|
||||||
|
|
||||||
self.damage = self.damage.saturating_add(final_hp as u16);
|
self.damage = self.damage.saturating_add(final_hp as u16);
|
||||||
if self.popup.value > 0 {
|
if self.popup.value > 0 {
|
||||||
self.popup.set_value(-(self.damage as i16));
|
self.popup.set_value(-(self.damage as i16));
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ use crate::framework::context::Context;
|
||||||
use crate::framework::error::GameResult;
|
use crate::framework::error::GameResult;
|
||||||
use crate::framework::graphics::{draw_rect, BlendMode, FilterMode};
|
use crate::framework::graphics::{draw_rect, BlendMode, FilterMode};
|
||||||
use crate::framework::ui::Components;
|
use crate::framework::ui::Components;
|
||||||
use crate::framework::{filesystem, graphics};
|
use crate::framework::{filesystem, gamepad, graphics};
|
||||||
use crate::input::touch_controls::TouchControlType;
|
use crate::input::touch_controls::TouchControlType;
|
||||||
use crate::inventory::{Inventory, TakeExperienceResult};
|
use crate::inventory::{Inventory, TakeExperienceResult};
|
||||||
use crate::map::WaterParams;
|
use crate::map::WaterParams;
|
||||||
|
|
@ -1846,6 +1846,16 @@ impl Scene for GameScene {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if state.quake_rumble_counter > 0 {
|
||||||
|
gamepad::set_quake_rumble_all(ctx, state, state.quake_rumble_counter)?;
|
||||||
|
state.quake_rumble_counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if state.super_quake_rumble_counter > 0 {
|
||||||
|
gamepad::set_super_quake_rumble_all(ctx, state, state.super_quake_rumble_counter)?;
|
||||||
|
state.super_quake_rumble_counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1260,6 +1260,7 @@ impl TextScriptVM {
|
||||||
let count = read_cur_varint(&mut cursor)? as u16;
|
let count = read_cur_varint(&mut cursor)? as u16;
|
||||||
|
|
||||||
state.quake_counter = count;
|
state.quake_counter = count;
|
||||||
|
state.quake_rumble_counter = count as u32;
|
||||||
|
|
||||||
exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32);
|
exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,10 @@ pub struct Settings {
|
||||||
pub player1_controller_axis_sensitivity: f64,
|
pub player1_controller_axis_sensitivity: f64,
|
||||||
#[serde(default = "default_controller_axis_sensitivity")]
|
#[serde(default = "default_controller_axis_sensitivity")]
|
||||||
pub player2_controller_axis_sensitivity: f64,
|
pub player2_controller_axis_sensitivity: f64,
|
||||||
|
#[serde(default = "default_rumble")]
|
||||||
|
pub player1_rumble: bool,
|
||||||
|
#[serde(default = "default_rumble")]
|
||||||
|
pub player2_rumble: bool,
|
||||||
#[serde(skip, default = "default_speed")]
|
#[serde(skip, default = "default_speed")]
|
||||||
pub speed: f64,
|
pub speed: f64,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
|
|
@ -82,7 +86,7 @@ fn default_true() -> bool {
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn current_version() -> u32 {
|
fn current_version() -> u32 {
|
||||||
17
|
18
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
|
@ -135,6 +139,11 @@ fn default_pause_on_focus_loss() -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn default_rumble() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
impl Settings {
|
impl Settings {
|
||||||
pub fn load(ctx: &Context) -> GameResult<Settings> {
|
pub fn load(ctx: &Context) -> GameResult<Settings> {
|
||||||
if let Ok(file) = user_open(ctx, "/settings.json") {
|
if let Ok(file) = user_open(ctx, "/settings.json") {
|
||||||
|
|
@ -270,6 +279,12 @@ impl Settings {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.version == 17 {
|
||||||
|
self.version = 18;
|
||||||
|
self.player1_rumble = default_rumble();
|
||||||
|
self.player2_rumble = default_rumble();
|
||||||
|
}
|
||||||
|
|
||||||
if self.version != initial_version {
|
if self.version != initial_version {
|
||||||
log::info!("Upgraded configuration file from version {} to {}.", initial_version, self.version);
|
log::info!("Upgraded configuration file from version {} to {}.", initial_version, self.version);
|
||||||
}
|
}
|
||||||
|
|
@ -293,7 +308,9 @@ impl Settings {
|
||||||
ControllerType::Keyboard => Box::new(KeyboardController::new(TargetPlayer::Player1)),
|
ControllerType::Keyboard => Box::new(KeyboardController::new(TargetPlayer::Player1)),
|
||||||
ControllerType::Gamepad(index) => {
|
ControllerType::Gamepad(index) => {
|
||||||
let keyboard_controller = Box::new(KeyboardController::new(TargetPlayer::Player1));
|
let keyboard_controller = Box::new(KeyboardController::new(TargetPlayer::Player1));
|
||||||
let gamepad_controller = Box::new(GamepadController::new(index, TargetPlayer::Player1));
|
|
||||||
|
let mut gamepad_controller = Box::new(GamepadController::new(index, TargetPlayer::Player1));
|
||||||
|
gamepad_controller.set_rumble_enabled(self.player1_rumble);
|
||||||
|
|
||||||
let mut combined_player_controller = CombinedPlayerController::new();
|
let mut combined_player_controller = CombinedPlayerController::new();
|
||||||
combined_player_controller.add(keyboard_controller);
|
combined_player_controller.add(keyboard_controller);
|
||||||
|
|
@ -309,7 +326,9 @@ impl Settings {
|
||||||
ControllerType::Keyboard => Box::new(KeyboardController::new(TargetPlayer::Player2)),
|
ControllerType::Keyboard => Box::new(KeyboardController::new(TargetPlayer::Player2)),
|
||||||
ControllerType::Gamepad(index) => {
|
ControllerType::Gamepad(index) => {
|
||||||
let keyboard_controller = Box::new(KeyboardController::new(TargetPlayer::Player2));
|
let keyboard_controller = Box::new(KeyboardController::new(TargetPlayer::Player2));
|
||||||
let gamepad_controller = Box::new(GamepadController::new(index, TargetPlayer::Player2));
|
|
||||||
|
let mut gamepad_controller = Box::new(GamepadController::new(index, TargetPlayer::Player2));
|
||||||
|
gamepad_controller.set_rumble_enabled(self.player2_rumble);
|
||||||
|
|
||||||
let mut combined_player_controller = CombinedPlayerController::new();
|
let mut combined_player_controller = CombinedPlayerController::new();
|
||||||
combined_player_controller.add(keyboard_controller);
|
combined_player_controller.add(keyboard_controller);
|
||||||
|
|
@ -356,6 +375,8 @@ impl Default for Settings {
|
||||||
player2_controller_button_map: player_default_controller_button_map(),
|
player2_controller_button_map: player_default_controller_button_map(),
|
||||||
player1_controller_axis_sensitivity: default_controller_axis_sensitivity(),
|
player1_controller_axis_sensitivity: default_controller_axis_sensitivity(),
|
||||||
player2_controller_axis_sensitivity: default_controller_axis_sensitivity(),
|
player2_controller_axis_sensitivity: default_controller_axis_sensitivity(),
|
||||||
|
player1_rumble: default_rumble(),
|
||||||
|
player2_rumble: default_rumble(),
|
||||||
speed: 1.0,
|
speed: 1.0,
|
||||||
god_mode: false,
|
god_mode: false,
|
||||||
infinite_booster: false,
|
infinite_booster: false,
|
||||||
|
|
|
||||||
|
|
@ -285,6 +285,8 @@ pub struct SharedGameState {
|
||||||
pub tile_size: TileSize,
|
pub tile_size: TileSize,
|
||||||
pub quake_counter: u16,
|
pub quake_counter: u16,
|
||||||
pub super_quake_counter: u16,
|
pub super_quake_counter: u16,
|
||||||
|
pub quake_rumble_counter: u32,
|
||||||
|
pub super_quake_rumble_counter: u32,
|
||||||
pub teleporter_slots: Vec<(u16, u16)>,
|
pub teleporter_slots: Vec<(u16, u16)>,
|
||||||
pub carets: Vec<Caret>,
|
pub carets: Vec<Caret>,
|
||||||
pub touch_controls: TouchControls,
|
pub touch_controls: TouchControls,
|
||||||
|
|
@ -422,6 +424,8 @@ impl SharedGameState {
|
||||||
tile_size: TileSize::Tile16x16,
|
tile_size: TileSize::Tile16x16,
|
||||||
quake_counter: 0,
|
quake_counter: 0,
|
||||||
super_quake_counter: 0,
|
super_quake_counter: 0,
|
||||||
|
quake_rumble_counter: 0,
|
||||||
|
super_quake_rumble_counter: 0,
|
||||||
teleporter_slots: Vec::with_capacity(8),
|
teleporter_slots: Vec::with_capacity(8),
|
||||||
carets: Vec::with_capacity(32),
|
carets: Vec::with_capacity(32),
|
||||||
touch_controls: TouchControls::new(),
|
touch_controls: TouchControls::new(),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue