Fix Player gun desync bug and inventory inconsistencies (#245)

* add inventory and player render fixes
This commit is contained in:
Edward Stuckey 2023-11-12 05:02:59 -05:00 committed by GitHub
parent 46710dd31a
commit 3b14adf949
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 46 additions and 29 deletions

View File

@ -140,24 +140,36 @@ impl GameEntity<(&mut Context, &mut Player, &mut Inventory, &mut HUD)> for Inven
InventoryFocus::None => {
self.focus = InventoryFocus::Weapons;
state.control_flags.set_ok_button_disabled(false);
state.textscript_vm.start_script(self.get_weapon_event_number(inventory));
// check weapon count (0 count means we run item script)
let event = if self.weapon_count > 0 {
self.get_weapon_event_number(inventory)
} else {
self.get_item_event_number(inventory)
};
state.textscript_vm.start_script(event);
}
InventoryFocus::Weapons if state.control_flags.control_enabled() => {
if player.controller.trigger_left() {
state.sound_manager.play_sfx(4);
inventory.prev_weapon();
state.control_flags.set_ok_button_disabled(false);
state.textscript_vm.start_script(self.get_weapon_event_number(inventory));
// if we have no weapons, the TSC should not be refreshed with L/R keystrokes
if self.weapon_count > 0
{
if player.controller.trigger_left() {
state.sound_manager.play_sfx(4);
inventory.prev_weapon();
state.control_flags.set_ok_button_disabled(false);
state.textscript_vm.start_script(self.get_weapon_event_number(inventory));
}
if player.controller.trigger_right() {
state.sound_manager.play_sfx(4);
inventory.next_weapon();
state.control_flags.set_ok_button_disabled(false);
state.textscript_vm.start_script(self.get_weapon_event_number(inventory));
}
}
if player.controller.trigger_right() {
state.sound_manager.play_sfx(4);
inventory.next_weapon();
state.control_flags.set_ok_button_disabled(false);
state.textscript_vm.start_script(self.get_weapon_event_number(inventory));
}
if player.controller.trigger_up() || player.controller.trigger_down() {
// we should not move from the weapon row if there are no items
if (player.controller.trigger_up() || player.controller.trigger_down()) && self.item_count > 0 {
self.focus = InventoryFocus::Items;
state.control_flags.set_ok_button_disabled(false);
state.textscript_vm.start_script(self.get_item_event_number(inventory));
@ -310,8 +322,8 @@ impl GameEntity<(&mut Context, &mut Player, &mut Inventory, &mut HUD)> for Inven
let (item_cursor_frame, weapon_cursor_frame) = match self.focus {
InventoryFocus::None => (1, 1),
InventoryFocus::Weapons => (1, self.tick & 1),
InventoryFocus::Items => (self.tick & 1, 1),
InventoryFocus::Weapons => (1, (self.tick / 2) % 2), //every-other frame (& 1): this is not what we want, we want every 2 frames.
InventoryFocus::Items => ((self.tick / 2) % 2, 1),
};
batch.add_rect(

View File

@ -744,15 +744,15 @@ impl Player {
if self.flags.hit_bottom_wall() {
if self.cond.interacted() {
self.skin.set_state(PlayerAnimationState::Examining);
self.anim_num = 11;
self.anim_counter = 0;
self.skin.set_state(PlayerAnimationState::Examining, self.anim_counter);
} else if state.control_flags.control_enabled()
&& (self.controller.move_up() || self.strafe_up)
&& (self.controller.move_left() || self.controller.move_right())
{
self.cond.set_fallen(true);
self.skin.set_state(PlayerAnimationState::WalkingUp);
self.skin.set_state(PlayerAnimationState::WalkingUp, self.anim_counter);
self.anim_counter += 1;
if self.anim_counter > 4 {
@ -771,7 +771,7 @@ impl Player {
&& (self.controller.move_left() || self.controller.move_right())
{
self.cond.set_fallen(true);
self.skin.set_state(PlayerAnimationState::Walking);
self.skin.set_state(PlayerAnimationState::Walking, self.anim_counter);
self.anim_counter += 1;
if self.anim_counter > 4 {
@ -792,7 +792,7 @@ impl Player {
}
self.cond.set_fallen(false);
self.skin.set_state(PlayerAnimationState::LookingUp);
self.skin.set_state(PlayerAnimationState::LookingUp, self.anim_counter);
self.anim_num = 5;
self.anim_counter = 0;
} else {
@ -801,24 +801,24 @@ impl Player {
}
self.cond.set_fallen(false);
self.skin.set_state(PlayerAnimationState::Idle);
self.skin.set_state(PlayerAnimationState::Idle, self.anim_counter);
self.anim_num = 0;
self.anim_counter = 0;
}
} else if self.up {
self.skin.set_state(PlayerAnimationState::FallingLookingUp);
self.skin.set_state(PlayerAnimationState::FallingLookingUp, self.anim_counter);
self.anim_num = 6;
self.anim_counter = 0;
} else if self.down {
self.skin.set_state(PlayerAnimationState::FallingLookingDown);
self.skin.set_state(PlayerAnimationState::FallingLookingDown, self.anim_counter);
self.anim_num = 10;
self.anim_counter = 0;
} else {
if self.vel_y > 0 {
self.skin.set_state(PlayerAnimationState::Falling);
self.skin.set_state(PlayerAnimationState::Falling, self.anim_counter);
self.anim_num = 1;
} else {
self.skin.set_state(PlayerAnimationState::Jumping);
self.skin.set_state(PlayerAnimationState::Jumping, self.anim_counter);
self.anim_num = 3;
}
self.anim_counter = 0;
@ -859,7 +859,7 @@ impl Player {
if state.constants.is_switch && self.air == 0 && self.flags.in_water() && !state.get_flag(4000) {
self.skin.set_appearance(PlayerAppearanceState::Default);
self.skin.set_state(PlayerAnimationState::Drowned);
self.skin.set_state(PlayerAnimationState::Drowned, self.anim_counter);
}
self.anim_rect = self.skin.animation_frame();

View File

@ -179,10 +179,15 @@ impl PlayerSkin for BasicPlayerSkin {
}
}
fn set_state(&mut self, state: PlayerAnimationState) {
fn set_state(&mut self, state: PlayerAnimationState, tick: u16) {
if self.state != state {
self.state = state;
self.tick = 0;
//self.tick = 0; // this should not happen
//self.tick = curr_tick; // this should happen instead, but there's a problem with ticking on 4 that results in an instant 1st frame animation.
// this dirty hack should fix that.
self.tick = if tick % 5 == 4 { u16::MAX } else { tick };
}
}

View File

@ -53,7 +53,7 @@ pub trait PlayerSkin: PlayerSkinClone {
fn tick(&mut self);
/// Sets the current animation state.
fn set_state(&mut self, state: PlayerAnimationState);
fn set_state(&mut self, state: PlayerAnimationState, tick: u16);
/// Returns current animation state.
fn get_state(&self) -> PlayerAnimationState;