1
0
Fork 0
mirror of https://github.com/doukutsu-rs/doukutsu-rs synced 2025-05-21 14:21:06 +00:00

various tweaks

This commit is contained in:
Alula 2020-09-29 02:43:55 +02:00
parent e54901077c
commit ac8d27197c
No known key found for this signature in database
GPG key ID: 3E00485503A1D8BA
8 changed files with 100 additions and 69 deletions

View file

@ -44,6 +44,7 @@ impl LiveDebugger {
} }
Window::new(im_str!("Debugger")) Window::new(im_str!("Debugger"))
.collapsed(true, Condition::FirstUseEver)
.position([5.0, 5.0], Condition::FirstUseEver) .position([5.0, 5.0], Condition::FirstUseEver)
.size([300.0, 120.0], Condition::FirstUseEver) .size([300.0, 120.0], Condition::FirstUseEver)
.build(ui, || { .build(ui, || {

View file

@ -101,14 +101,14 @@ impl Game {
for _ in 0..self.loops { for _ in 0..self.loops {
scene.tick(&mut self.state, ctx)?; scene.tick(&mut self.state, ctx)?;
if self.state.speed_hack { if self.state.settings.speed_hack {
scene.tick(&mut self.state, ctx)?; scene.tick(&mut self.state, ctx)?;
} }
} }
} }
TimingMode::FrameSynchronized => { TimingMode::FrameSynchronized => {
scene.tick(&mut self.state, ctx)?; scene.tick(&mut self.state, ctx)?;
if self.state.speed_hack { if self.state.settings.speed_hack {
scene.tick(&mut self.state, ctx)?; scene.tick(&mut self.state, ctx)?;
} }
} }
@ -151,8 +151,8 @@ impl Game {
KeyCode::X => { state.key_state.set_fire(true) } KeyCode::X => { state.key_state.set_fire(true) }
KeyCode::A => { state.key_state.set_weapon_prev(true) } KeyCode::A => { state.key_state.set_weapon_prev(true) }
KeyCode::S => { state.key_state.set_weapon_next(true) } KeyCode::S => { state.key_state.set_weapon_next(true) }
KeyCode::F11 => { state.god_mode = !state.god_mode } KeyCode::F11 => { state.settings.god_mode = !state.settings.god_mode }
KeyCode::F12 => { state.set_speed_hack(!state.speed_hack) } KeyCode::F12 => { state.set_speed_hack(!state.settings.speed_hack) }
_ => {} _ => {}
} }
} }

View file

@ -537,7 +537,7 @@ impl Player {
} }
pub fn damage(&mut self, hp: isize, state: &mut SharedGameState) { pub fn damage(&mut self, hp: isize, state: &mut SharedGameState) {
if state.god_mode || self.shock_counter > 0 { if state.settings.god_mode || self.shock_counter > 0 {
return; return;
} }

View file

@ -557,26 +557,14 @@ impl GameScene {
graphics::clear(ctx, Color::from_rgb(150, 150, 150)); graphics::clear(ctx, Color::from_rgb(150, 150, 150));
{ {
if !self.player.cond.hidden() && self.inventory.get_current_weapon().is_some() {
let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "builtin/lightmap/direct")?;
let direction = if self.player.up {
Direction::Up
} else if self.player.down {
Direction::Bottom
} else {
self.player.direction
};
self.draw_directional_light(((self.player.x - self.frame.x) / 0x200) as f32,
((self.player.y - self.frame.y) / 0x200) as f32,
3.0, direction, (255, 255, 255), batch);
batch.draw_filtered(FilterMode::Linear, ctx)?;
}
let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "builtin/lightmap/spot")?; let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "builtin/lightmap/spot")?;
if !self.player.cond.hidden() && self.inventory.get_current_weapon().is_some() {
self.draw_light(((self.player.x - self.frame.x) / 0x200) as f32,
((self.player.y - self.frame.y) / 0x200) as f32,
2.5, (255, 255, 255), batch);
}
for bullet in self.bullet_manager.bullets.iter() { for bullet in self.bullet_manager.bullets.iter() {
self.draw_light(((bullet.x - self.frame.x) / 0x200) as f32, self.draw_light(((bullet.x - self.frame.x) / 0x200) as f32,
((bullet.y - self.frame.y) / 0x200) as f32, ((bullet.y - self.frame.y) / 0x200) as f32,
@ -588,17 +576,7 @@ impl GameScene {
CaretType::ProjectileDissipation | CaretType::Shoot => { CaretType::ProjectileDissipation | CaretType::Shoot => {
self.draw_light(((caret.x - self.frame.x) / 0x200) as f32, self.draw_light(((caret.x - self.frame.x) / 0x200) as f32,
((caret.y - self.frame.y) / 0x200) as f32, ((caret.y - self.frame.y) / 0x200) as f32,
1.0, (200, 200, 200), batch); 4.0, (200, 200, 200), batch);
}
CaretType::LevelUp if caret.direction == Direction::Left => {
self.draw_light(((caret.x - self.frame.x) / 0x200) as f32,
((caret.y - self.frame.y) / 0x200) as f32,
2.0, (0, 100, 160), batch);
}
CaretType::LevelUp if caret.direction == Direction::Right => {
self.draw_light(((caret.x - self.frame.x) / 0x200) as f32,
((caret.y - self.frame.y) / 0x200) as f32,
2.0, (255, 30, 30), batch);
} }
_ => {} _ => {}
} }
@ -1007,7 +985,7 @@ impl Scene for GameScene {
fn draw(&self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult { fn draw(&self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
self.draw_background(state, ctx)?; self.draw_background(state, ctx)?;
self.draw_tiles(state, ctx, TileLayer::Background)?; self.draw_tiles(state, ctx, TileLayer::Background)?;
if state.enhanced_graphics { if state.settings.enhanced_graphics {
self.draw_light_map(state, ctx)?; self.draw_light_map(state, ctx)?;
} }

View file

@ -31,6 +31,14 @@ impl Scene for LoadingScene {
let head_script = TextScript::load_from(head_tsc, &state.constants)?; let head_script = TextScript::load_from(head_tsc, &state.constants)?;
state.textscript_vm.set_global_script(head_script); state.textscript_vm.set_global_script(head_script);
let arms_item_tsc = filesystem::open(ctx, [&state.base_path, "/ArmsItem.tsc"].join(""))?;
let arms_item_script = TextScript::load_from(arms_item_tsc, &state.constants)?;
state.textscript_vm.set_inventory_script(arms_item_script);
let stage_select_tsc = filesystem::open(ctx, [&state.base_path, "/StageSelect.tsc"].join(""))?;
let stage_select_script = TextScript::load_from(stage_select_tsc, &state.constants)?;
state.textscript_vm.set_stage_select_script(stage_select_script);
state.next_scene = Some(Box::new(TitleScene::new())); state.next_scene = Some(Box::new(TitleScene::new()));
} }

View file

@ -4,6 +4,7 @@ use crate::ggez::graphics::{Color, FilterMode};
use crate::menu::{Menu, MenuEntry, MenuSelectionResult}; use crate::menu::{Menu, MenuEntry, MenuSelectionResult};
use crate::scene::Scene; use crate::scene::Scene;
use crate::shared_game_state::{SharedGameState, TimingMode}; use crate::shared_game_state::{SharedGameState, TimingMode};
use crate::texture_set::TextureSet;
#[derive(PartialEq, Eq, Copy, Clone)] #[derive(PartialEq, Eq, Copy, Clone)]
#[repr(u8)] #[repr(u8)]
@ -93,8 +94,13 @@ impl Scene for TitleScene {
self.option_menu.push_entry(MenuEntry::Toggle("50 FPS timing".to_string(), state.timing_mode == TimingMode::_50Hz)); self.option_menu.push_entry(MenuEntry::Toggle("50 FPS timing".to_string(), state.timing_mode == TimingMode::_50Hz));
self.option_menu.push_entry(MenuEntry::Toggle("Linear scaling".to_string(), ctx.filter_mode == FilterMode::Linear)); self.option_menu.push_entry(MenuEntry::Toggle("Linear scaling".to_string(), ctx.filter_mode == FilterMode::Linear));
self.option_menu.push_entry(MenuEntry::Toggle("Enhanced graphics".to_string(), state.enhanced_graphics)); self.option_menu.push_entry(MenuEntry::Toggle("Enhanced graphics".to_string(), state.settings.enhanced_graphics));
self.option_menu.push_entry(MenuEntry::Toggle("2x Speed hack".to_string(), state.speed_hack)); if state.constants.is_cs_plus {
self.option_menu.push_entry(MenuEntry::Toggle("Original textures".to_string(), state.settings.original_textures));
} else {
self.option_menu.push_entry(MenuEntry::Disabled("Original textures".to_string()));
}
self.option_menu.push_entry(MenuEntry::Toggle("2x Speed hack".to_string(), state.settings.speed_hack));
self.option_menu.push_entry(MenuEntry::Active("Join our Discord".to_string())); self.option_menu.push_entry(MenuEntry::Active("Join our Discord".to_string()));
self.option_menu.push_entry(MenuEntry::Disabled(DISCORD_LINK.to_owned())); self.option_menu.push_entry(MenuEntry::Disabled(DISCORD_LINK.to_owned()));
self.option_menu.push_entry(MenuEntry::Active("Back".to_string())); self.option_menu.push_entry(MenuEntry::Active("Back".to_string()));
@ -155,24 +161,38 @@ impl Scene for TitleScene {
} }
MenuSelectionResult::Selected(2, toggle) => { MenuSelectionResult::Selected(2, toggle) => {
if let MenuEntry::Toggle(_, value) = toggle { if let MenuEntry::Toggle(_, value) = toggle {
state.enhanced_graphics = !state.enhanced_graphics; state.settings.enhanced_graphics = !state.settings.enhanced_graphics;
*value = state.enhanced_graphics; *value = state.settings.enhanced_graphics;
} }
} }
MenuSelectionResult::Selected(3, toggle) => { MenuSelectionResult::Selected(3, toggle) => {
if let MenuEntry::Toggle(_, value) = toggle { if let MenuEntry::Toggle(_, value) = toggle {
state.set_speed_hack(!state.speed_hack); state.settings.original_textures = !state.settings.original_textures;
*value = state.speed_hack; let path = if state.settings.original_textures {
"/base/ogph/"
} else {
"/base/"
};
state.texture_set = TextureSet::new(path);
*value = state.settings.original_textures;
} }
} }
MenuSelectionResult::Selected(4, _) => { MenuSelectionResult::Selected(4, toggle) => {
if let MenuEntry::Toggle(_, value) = toggle {
state.set_speed_hack(!state.settings.speed_hack);
*value = state.settings.speed_hack;
}
}
MenuSelectionResult::Selected(5, _) => {
if let Err(e) = webbrowser::open(DISCORD_LINK) { if let Err(e) = webbrowser::open(DISCORD_LINK) {
log::warn!("Error opening web browser: {}", e); log::warn!("Error opening web browser: {}", e);
} }
} }
MenuSelectionResult::Selected(6, _) | MenuSelectionResult::Canceled => { MenuSelectionResult::Selected(7, _) | MenuSelectionResult::Canceled => {
self.current_menu = CurrentMenu::MainMenu; self.current_menu = CurrentMenu::MainMenu;
} }
_ => {} _ => {}

View file

@ -37,6 +37,13 @@ impl TimingMode {
} }
} }
pub struct Settings {
pub god_mode: bool,
pub speed_hack: bool,
pub original_textures: bool,
pub enhanced_graphics: bool,
}
pub struct SharedGameState { pub struct SharedGameState {
pub timing_mode: TimingMode, pub timing_mode: TimingMode,
pub control_flags: ControlFlags, pub control_flags: ControlFlags,
@ -54,12 +61,10 @@ pub struct SharedGameState {
pub npc_table: NPCTable, pub npc_table: NPCTable,
pub stages: Vec<StageData>, pub stages: Vec<StageData>,
pub sound_manager: SoundManager, pub sound_manager: SoundManager,
pub settings: Settings,
pub constants: EngineConstants, pub constants: EngineConstants,
pub new_npcs: Vec<NPC>, pub new_npcs: Vec<NPC>,
pub scale: f32, pub scale: f32,
pub god_mode: bool,
pub speed_hack: bool,
pub enhanced_graphics: bool,
pub lightmap_canvas: Canvas, pub lightmap_canvas: Canvas,
pub canvas_size: (f32, f32), pub canvas_size: (f32, f32),
pub screen_size: (f32, f32), pub screen_size: (f32, f32),
@ -113,12 +118,15 @@ impl SharedGameState {
npc_table: NPCTable::new(), npc_table: NPCTable::new(),
stages: Vec::with_capacity(96), stages: Vec::with_capacity(96),
sound_manager: SoundManager::new(ctx)?, sound_manager: SoundManager::new(ctx)?,
settings: Settings {
god_mode: false,
speed_hack: false,
original_textures: false,
enhanced_graphics: true,
},
constants, constants,
new_npcs: Vec::with_capacity(8), new_npcs: Vec::with_capacity(8),
scale, scale,
god_mode: false,
speed_hack: false,
enhanced_graphics: true,
lightmap_canvas: Canvas::with_window_size(ctx)?, lightmap_canvas: Canvas::with_window_size(ctx)?,
screen_size, screen_size,
canvas_size, canvas_size,
@ -209,7 +217,7 @@ impl SharedGameState {
} }
pub fn set_speed_hack(&mut self, toggle: bool) { pub fn set_speed_hack(&mut self, toggle: bool) {
self.speed_hack = toggle; self.settings.speed_hack = toggle;
if let Err(err) = self.sound_manager.set_speed(if toggle { 2.0 } else { 1.0 }) { if let Err(err) = self.sound_manager.set_speed(if toggle { 2.0 } else { 1.0 }) {
log::error!("Error while sending a message to sound manager: {}", err); log::error!("Error while sending a message to sound manager: {}", err);

View file

@ -279,6 +279,10 @@ pub enum OpCode {
PSH, PSH,
/// <POP, Restores text script state from stack and resumes previous event. /// <POP, Restores text script state from stack and resumes previous event.
POP, POP,
/// <KE2, Seen in ArmsItem.tsc, unknown purpose, related to puppies
KE2,
/// <FR2, likely related to <KE2, seen at end of events using it
FR2,
// ---- Custom opcodes, for use by modders ---- // ---- Custom opcodes, for use by modders ----
} }
@ -315,6 +319,14 @@ pub enum ConfirmSelection {
No, No,
} }
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
#[repr(u8)]
pub enum ScriptMode {
Map,
Inventory,
StageSelect,
}
impl Not for ConfirmSelection { impl Not for ConfirmSelection {
type Output = ConfirmSelection; type Output = ConfirmSelection;
@ -342,10 +354,11 @@ pub enum TextScriptExecutionState {
} }
pub struct TextScriptVM { pub struct TextScriptVM {
pub scripts: TextScriptVMScripts, pub scripts: Scripts,
pub state: TextScriptExecutionState, pub state: TextScriptExecutionState,
pub stack: Vec<TextScriptExecutionState>, pub stack: Vec<TextScriptExecutionState>,
pub flags: TextScriptFlags, pub flags: TextScriptFlags,
pub mode: ScriptMode,
/// Toggle for non-strict TSC parsing because English versions of CS+ (both AG and Nicalis release) /// Toggle for non-strict TSC parsing because English versions of CS+ (both AG and Nicalis release)
/// modified the events carelessly and since original Pixel's engine hasn't enforced constraints /// modified the events carelessly and since original Pixel's engine hasn't enforced constraints
/// while parsing no one noticed them. /// while parsing no one noticed them.
@ -365,12 +378,18 @@ impl Default for TextScriptVM {
} }
} }
pub struct TextScriptVMScripts { pub struct Scripts {
/// Head.tsc - shared part of map scripts
pub global_script: TextScript, pub global_script: TextScript,
/// <Map>.tsc - map script
pub scene_script: TextScript, pub scene_script: TextScript,
/// ArmsItem.tsc - used by inventory
pub inventory_script: TextScript,
/// StageSelect.tsc - used by teleport target selector
pub stage_select_script: TextScript,
} }
impl TextScriptVMScripts { impl Scripts {
pub fn find_script(&self, event_num: u16) -> Option<&Vec<u8>> { pub fn find_script(&self, event_num: u16) -> Option<&Vec<u8>> {
if let Some(tsc) = self.scene_script.event_map.get(&event_num) { if let Some(tsc) = self.scene_script.event_map.get(&event_num) {
return Some(tsc); return Some(tsc);
@ -400,9 +419,11 @@ fn read_cur_varint(cursor: &mut Cursor<&Vec<u8>>) -> GameResult<i32> {
impl TextScriptVM { impl TextScriptVM {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
scripts: TextScriptVMScripts { scripts: Scripts {
global_script: TextScript::new(), global_script: TextScript::new(),
scene_script: TextScript::new(), scene_script: TextScript::new(),
inventory_script: TextScript::new(),
stage_select_script: TextScript::new(),
}, },
state: TextScriptExecutionState::Ended, state: TextScriptExecutionState::Ended,
stack: Vec::with_capacity(6), stack: Vec::with_capacity(6),
@ -415,6 +436,7 @@ impl TextScriptVM {
line_1: Vec::with_capacity(24), line_1: Vec::with_capacity(24),
line_2: Vec::with_capacity(24), line_2: Vec::with_capacity(24),
line_3: Vec::with_capacity(24), line_3: Vec::with_capacity(24),
mode: ScriptMode::Map,
} }
} }
@ -428,20 +450,12 @@ impl TextScriptVM {
if !self.suspend { self.reset(); } if !self.suspend { self.reset(); }
} }
pub fn append_global_script(&mut self, script: TextScript) { pub fn set_inventory_script(&mut self, script: TextScript) {
for (key, val) in script.event_map { self.scripts.inventory_script = script;
self.scripts.global_script.event_map.insert(key, val);
} }
if !self.suspend { self.reset(); } pub fn set_stage_select_script(&mut self, script: TextScript) {
} self.scripts.stage_select_script = script;
pub fn append_scene_script(&mut self, script: TextScript) {
for (key, val) in script.event_map {
self.scripts.scene_script.event_map.insert(key, val);
}
if !self.suspend { self.reset(); }
} }
pub fn reset(&mut self) { pub fn reset(&mut self) {
@ -459,6 +473,8 @@ impl TextScriptVM {
self.line_3.clear(); self.line_3.clear();
} }
pub fn set_mode(&mut self, mode: ScriptMode) {}
pub fn start_script(&mut self, event_num: u16) { pub fn start_script(&mut self, event_num: u16) {
self.reset(); self.reset();
self.state = TextScriptExecutionState::Running(event_num, 0); self.state = TextScriptExecutionState::Running(event_num, 0);
@ -1232,9 +1248,9 @@ impl TextScriptVM {
} }
// unimplemented opcodes // unimplemented opcodes
// Zero operands // Zero operands
OpCode::CAT | OpCode::CIL | OpCode::CPS | OpCode::CAT | OpCode::CIL | OpCode::CPS | OpCode::KE2 |
OpCode::CRE | OpCode::CSS | OpCode::FLA | OpCode::MLP | OpCode::CRE | OpCode::CSS | OpCode::FLA | OpCode::MLP |
OpCode::SAT | OpCode::SLP | OpCode::SPS | OpCode::SAT | OpCode::SLP | OpCode::SPS | OpCode::FR2 |
OpCode::STC | OpCode::SVP | OpCode::TUR | OpCode::HM2 => { OpCode::STC | OpCode::SVP | OpCode::TUR | OpCode::HM2 => {
log::warn!("unimplemented opcode: {:?}", op); log::warn!("unimplemented opcode: {:?}", op);
@ -1513,7 +1529,7 @@ impl TextScript {
OpCode::MM0 | OpCode::MNA | OpCode::MS2 | OpCode::MS3 | OpCode::MSG | OpCode::NOD | OpCode::MM0 | OpCode::MNA | OpCode::MS2 | OpCode::MS3 | OpCode::MSG | OpCode::NOD |
OpCode::PRI | OpCode::RMU | OpCode::SAT | OpCode::SLP | OpCode::SMC | OpCode::SPS | OpCode::PRI | OpCode::RMU | OpCode::SAT | OpCode::SLP | OpCode::SMC | OpCode::SPS |
OpCode::STC | OpCode::SVP | OpCode::TUR | OpCode::WAS | OpCode::ZAM | OpCode::HM2 | OpCode::STC | OpCode::SVP | OpCode::TUR | OpCode::WAS | OpCode::ZAM | OpCode::HM2 |
OpCode::POP => { OpCode::POP | OpCode::KE2 | OpCode::FR2 => {
TextScript::put_varint(instr as i32, out); TextScript::put_varint(instr as i32, out);
} }
// One operand codes // One operand codes