1
0
Fork 0
mirror of https://github.com/doukutsu-rs/doukutsu-rs synced 2025-12-02 01:18:37 +00:00

fix TSC handling certain weapon opcodes improperly

This commit is contained in:
Alula 2021-03-22 09:01:52 +01:00
parent 36fd5f8879
commit 8a64cfc180
No known key found for this signature in database
GPG key ID: 3E00485503A1D8BA
3 changed files with 83 additions and 31 deletions

View file

@ -84,24 +84,46 @@ impl Inventory {
result result
} }
pub fn add_weapon(&mut self, weapon_id: WeaponType, max_ammo: u16) -> &mut Weapon { pub fn add_weapon_data(&mut self, weapon_id: WeaponType, ammo: u16, max_ammo: u16, experience: u16, level: WeaponLevel) {
let weapon = Weapon::new(
weapon_id,
level,
experience,
ammo,
max_ammo,
);
if !self.has_weapon(weapon_id) { if !self.has_weapon(weapon_id) {
self.weapons.push(weapon);
} else {
let w = self.get_weapon_by_type_mut(weapon_id);
if let Some(w) = w {
*w = weapon
}
}
}
pub fn add_weapon(&mut self, weapon_id: WeaponType, ammo: u16) {
let w = self.get_weapon_by_type_mut(weapon_id);
if let Some(w) = w {
w.ammo += ammo;
w.max_ammo += ammo;
} else {
self.weapons.push(Weapon::new( self.weapons.push(Weapon::new(
weapon_id, weapon_id,
WeaponLevel::Level1, WeaponLevel::Level1,
0, 0,
max_ammo, ammo,
max_ammo, ammo,
)); ));
} }
self.weapons.iter_mut().find(|w| w.wtype == weapon_id).unwrap()
} }
pub fn trade_weapon(&mut self, old: Option<WeaponType>, new: WeaponType, max_ammo: u16) { pub fn trade_weapon(&mut self, old: Option<WeaponType>, new: WeaponType, max_ammo: u16) {
if let Some(wtype) = old { if let Some(wtype) = old {
if let Some(weapon) = self.get_weapon_by_type_mut(wtype) { if let Some(weapon) = self.get_weapon_by_type_mut(wtype) {
*weapon = Weapon::new(new, WeaponLevel::Level1, 0, max_ammo, max_ammo); let ammo = if max_ammo == 0 { weapon.max_ammo } else { max_ammo };
*weapon = Weapon::new(new, WeaponLevel::Level1, 0, ammo, ammo);
} else { } else {
self.add_weapon(new, max_ammo); self.add_weapon(new, max_ammo);
} }

View file

@ -1,18 +1,17 @@
use std::io; use std::io;
use byteorder::{BE, LE, ReadBytesExt, WriteBytesExt}; use byteorder::{ReadBytesExt, WriteBytesExt, BE, LE};
use num_traits::{clamp, FromPrimitive}; use num_traits::{clamp, FromPrimitive};
use crate::common::{Direction, FadeState}; use crate::common::{Direction, FadeState};
use crate::framework::context::Context; use crate::framework::context::Context;
use crate::framework::error::GameError::ResourceLoadError;
use crate::framework::error::GameResult; use crate::framework::error::GameResult;
use crate::player::ControlMode; use crate::player::ControlMode;
use crate::scene::game_scene::GameScene; use crate::scene::game_scene::GameScene;
use crate::shared_game_state::SharedGameState; use crate::shared_game_state::SharedGameState;
use crate::str; use crate::str;
use crate::weapon::{WeaponLevel, WeaponType}; use crate::weapon::{WeaponLevel, WeaponType};
use crate::framework::error::GameError::ResourceLoadError;
pub struct WeaponData { pub struct WeaponData {
pub weapon_id: u32, pub weapon_id: u32,
@ -58,42 +57,67 @@ impl GameProfile {
game_scene.inventory_player1.current_weapon = self.current_weapon as u16; game_scene.inventory_player1.current_weapon = self.current_weapon as u16;
game_scene.inventory_player1.current_item = self.current_item as u16; game_scene.inventory_player1.current_item = self.current_item as u16;
for weapon in self.weapon_data.iter() { for weapon in self.weapon_data.iter() {
if weapon.weapon_id == 0 { continue; } if weapon.weapon_id == 0 {
continue;
}
let weapon_type: Option<WeaponType> = FromPrimitive::from_u8(weapon.weapon_id as u8); let weapon_type: Option<WeaponType> = FromPrimitive::from_u8(weapon.weapon_id as u8);
if let Some(wtype) = weapon_type { if let Some(wtype) = weapon_type {
let w = game_scene.inventory_player1.add_weapon(wtype, weapon.max_ammo as u16); let w = game_scene.inventory_player1.add_weapon_data(
w.ammo = weapon.ammo as u16; wtype,
w.level = match weapon.level { weapon.ammo as u16,
2 => { WeaponLevel::Level2 } weapon.max_ammo as u16,
3 => { WeaponLevel::Level3 } weapon.exp as u16,
_ => { WeaponLevel::Level1 } match weapon.level {
}; 2 => WeaponLevel::Level2,
w.experience = weapon.exp as u16; 3 => WeaponLevel::Level3,
_ => WeaponLevel::Level1,
},
);
} }
} }
for item in self.items.iter().copied() { for item in self.items.iter().copied() {
if item == 0 { break; } if item == 0 {
break;
}
game_scene.inventory_player1.add_item(item as u16); game_scene.inventory_player1.add_item(item as u16);
} }
for slot in self.teleporter_slots.iter() { for slot in self.teleporter_slots.iter() {
if slot.event_num == 0 { break; } if slot.event_num == 0 {
break;
}
state.teleporter_slots.push((slot.index as u16, slot.event_num as u16)); state.teleporter_slots.push((slot.index as u16, slot.event_num as u16));
} }
for (idx, &flags) in self.flags.iter().enumerate() { for (idx, &flags) in self.flags.iter().enumerate() {
if flags & 0b00000001 != 0 { state.game_flags.set(idx * 8, true); } if flags & 0b00000001 != 0 {
if flags & 0b00000010 != 0 { state.game_flags.set(idx * 8 + 1, true); } state.game_flags.set(idx * 8, true);
if flags & 0b00000100 != 0 { state.game_flags.set(idx * 8 + 2, true); } }
if flags & 0b00001000 != 0 { state.game_flags.set(idx * 8 + 3, true); } if flags & 0b00000010 != 0 {
if flags & 0b00010000 != 0 { state.game_flags.set(idx * 8 + 4, true); } state.game_flags.set(idx * 8 + 1, true);
if flags & 0b00100000 != 0 { state.game_flags.set(idx * 8 + 5, true); } }
if flags & 0b01000000 != 0 { state.game_flags.set(idx * 8 + 6, true); } if flags & 0b00000100 != 0 {
if flags & 0b10000000 != 0 { state.game_flags.set(idx * 8 + 7, true); } state.game_flags.set(idx * 8 + 2, true);
}
if flags & 0b00001000 != 0 {
state.game_flags.set(idx * 8 + 3, true);
}
if flags & 0b00010000 != 0 {
state.game_flags.set(idx * 8 + 4, true);
}
if flags & 0b00100000 != 0 {
state.game_flags.set(idx * 8 + 5, true);
}
if flags & 0b01000000 != 0 {
state.game_flags.set(idx * 8 + 6, true);
}
if flags & 0b10000000 != 0 {
state.game_flags.set(idx * 8 + 7, true);
}
} }
game_scene.player1.equip.0 = self.equipment as u16; game_scene.player1.equip.0 = self.equipment as u16;
@ -101,7 +125,8 @@ impl GameProfile {
game_scene.player1.x = self.pos_x; game_scene.player1.x = self.pos_x;
game_scene.player1.y = self.pos_y; game_scene.player1.y = self.pos_y;
game_scene.player1.control_mode = if self.control_mode == 1 { ControlMode::IronHead } else { ControlMode::Normal }; game_scene.player1.control_mode =
if self.control_mode == 1 { ControlMode::IronHead } else { ControlMode::Normal };
game_scene.player1.direction = self.direction; game_scene.player1.direction = self.direction;
game_scene.player1.life = self.life; game_scene.player1.life = self.life;
game_scene.player1.max_life = self.max_life; game_scene.player1.max_life = self.max_life;

View file

@ -626,9 +626,11 @@ impl TextScriptVM {
TextScriptExecutionState::WaitTicks(event, ip, ticks) => { TextScriptExecutionState::WaitTicks(event, ip, ticks) => {
if ticks == 0 { if ticks == 0 {
state.textscript_vm.state = TextScriptExecutionState::Running(event, ip); state.textscript_vm.state = TextScriptExecutionState::Running(event, ip);
} else { } else if ticks != 9999 {
state.textscript_vm.state = TextScriptExecutionState::WaitTicks(event, ip, ticks - 1); state.textscript_vm.state = TextScriptExecutionState::WaitTicks(event, ip, ticks - 1);
break; break;
} else {
break;
} }
} }
TextScriptExecutionState::WaitConfirmation(event, ip, no_event, wait, selection) => { TextScriptExecutionState::WaitConfirmation(event, ip, no_event, wait, selection) => {
@ -891,7 +893,10 @@ impl TextScriptVM {
if flag_to >= flag_from { if flag_to >= flag_from {
for flag in flag_from..=flag_to { for flag in flag_from..=flag_to {
if state.get_flag(flag) {
state.game_flags.set(flag, false); state.game_flags.set(flag, false);
break;
}
} }
} }