mirror of
https://github.com/doukutsu-rs/doukutsu-rs
synced 2025-05-21 06:11:11 +00:00
various tweaks
This commit is contained in:
parent
e54901077c
commit
ac8d27197c
|
@ -44,6 +44,7 @@ impl LiveDebugger {
|
|||
}
|
||||
|
||||
Window::new(im_str!("Debugger"))
|
||||
.collapsed(true, Condition::FirstUseEver)
|
||||
.position([5.0, 5.0], Condition::FirstUseEver)
|
||||
.size([300.0, 120.0], Condition::FirstUseEver)
|
||||
.build(ui, || {
|
||||
|
|
|
@ -101,14 +101,14 @@ impl Game {
|
|||
|
||||
for _ in 0..self.loops {
|
||||
scene.tick(&mut self.state, ctx)?;
|
||||
if self.state.speed_hack {
|
||||
if self.state.settings.speed_hack {
|
||||
scene.tick(&mut self.state, ctx)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
TimingMode::FrameSynchronized => {
|
||||
scene.tick(&mut self.state, ctx)?;
|
||||
if self.state.speed_hack {
|
||||
if self.state.settings.speed_hack {
|
||||
scene.tick(&mut self.state, ctx)?;
|
||||
}
|
||||
}
|
||||
|
@ -151,8 +151,8 @@ impl Game {
|
|||
KeyCode::X => { state.key_state.set_fire(true) }
|
||||
KeyCode::A => { state.key_state.set_weapon_prev(true) }
|
||||
KeyCode::S => { state.key_state.set_weapon_next(true) }
|
||||
KeyCode::F11 => { state.god_mode = !state.god_mode }
|
||||
KeyCode::F12 => { state.set_speed_hack(!state.speed_hack) }
|
||||
KeyCode::F11 => { state.settings.god_mode = !state.settings.god_mode }
|
||||
KeyCode::F12 => { state.set_speed_hack(!state.settings.speed_hack) }
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -537,7 +537,7 @@ impl Player {
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -557,26 +557,14 @@ impl GameScene {
|
|||
|
||||
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")?;
|
||||
|
||||
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() {
|
||||
self.draw_light(((bullet.x - self.frame.x) / 0x200) as f32,
|
||||
((bullet.y - self.frame.y) / 0x200) as f32,
|
||||
|
@ -588,17 +576,7 @@ impl GameScene {
|
|||
CaretType::ProjectileDissipation | CaretType::Shoot => {
|
||||
self.draw_light(((caret.x - self.frame.x) / 0x200) as f32,
|
||||
((caret.y - self.frame.y) / 0x200) as f32,
|
||||
1.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);
|
||||
4.0, (200, 200, 200), batch);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -1007,7 +985,7 @@ impl Scene for GameScene {
|
|||
fn draw(&self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
||||
self.draw_background(state, ctx)?;
|
||||
self.draw_tiles(state, ctx, TileLayer::Background)?;
|
||||
if state.enhanced_graphics {
|
||||
if state.settings.enhanced_graphics {
|
||||
self.draw_light_map(state, ctx)?;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,14 @@ impl Scene for LoadingScene {
|
|||
let head_script = TextScript::load_from(head_tsc, &state.constants)?;
|
||||
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()));
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ use crate::ggez::graphics::{Color, FilterMode};
|
|||
use crate::menu::{Menu, MenuEntry, MenuSelectionResult};
|
||||
use crate::scene::Scene;
|
||||
use crate::shared_game_state::{SharedGameState, TimingMode};
|
||||
use crate::texture_set::TextureSet;
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone)]
|
||||
#[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("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("2x Speed hack".to_string(), state.speed_hack));
|
||||
self.option_menu.push_entry(MenuEntry::Toggle("Enhanced graphics".to_string(), state.settings.enhanced_graphics));
|
||||
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::Disabled(DISCORD_LINK.to_owned()));
|
||||
self.option_menu.push_entry(MenuEntry::Active("Back".to_string()));
|
||||
|
@ -155,24 +161,38 @@ impl Scene for TitleScene {
|
|||
}
|
||||
MenuSelectionResult::Selected(2, 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) => {
|
||||
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) {
|
||||
log::warn!("Error opening web browser: {}", e);
|
||||
}
|
||||
}
|
||||
MenuSelectionResult::Selected(6, _) | MenuSelectionResult::Canceled => {
|
||||
MenuSelectionResult::Selected(7, _) | MenuSelectionResult::Canceled => {
|
||||
self.current_menu = CurrentMenu::MainMenu;
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
@ -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 timing_mode: TimingMode,
|
||||
pub control_flags: ControlFlags,
|
||||
|
@ -54,12 +61,10 @@ pub struct SharedGameState {
|
|||
pub npc_table: NPCTable,
|
||||
pub stages: Vec<StageData>,
|
||||
pub sound_manager: SoundManager,
|
||||
pub settings: Settings,
|
||||
pub constants: EngineConstants,
|
||||
pub new_npcs: Vec<NPC>,
|
||||
pub scale: f32,
|
||||
pub god_mode: bool,
|
||||
pub speed_hack: bool,
|
||||
pub enhanced_graphics: bool,
|
||||
pub lightmap_canvas: Canvas,
|
||||
pub canvas_size: (f32, f32),
|
||||
pub screen_size: (f32, f32),
|
||||
|
@ -113,12 +118,15 @@ impl SharedGameState {
|
|||
npc_table: NPCTable::new(),
|
||||
stages: Vec::with_capacity(96),
|
||||
sound_manager: SoundManager::new(ctx)?,
|
||||
settings: Settings {
|
||||
god_mode: false,
|
||||
speed_hack: false,
|
||||
original_textures: false,
|
||||
enhanced_graphics: true,
|
||||
},
|
||||
constants,
|
||||
new_npcs: Vec::with_capacity(8),
|
||||
scale,
|
||||
god_mode: false,
|
||||
speed_hack: false,
|
||||
enhanced_graphics: true,
|
||||
lightmap_canvas: Canvas::with_window_size(ctx)?,
|
||||
screen_size,
|
||||
canvas_size,
|
||||
|
@ -209,7 +217,7 @@ impl SharedGameState {
|
|||
}
|
||||
|
||||
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 }) {
|
||||
log::error!("Error while sending a message to sound manager: {}", err);
|
||||
|
|
|
@ -279,6 +279,10 @@ pub enum OpCode {
|
|||
PSH,
|
||||
/// <POP, Restores text script state from stack and resumes previous event.
|
||||
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 ----
|
||||
}
|
||||
|
@ -315,6 +319,14 @@ pub enum ConfirmSelection {
|
|||
No,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||
#[repr(u8)]
|
||||
pub enum ScriptMode {
|
||||
Map,
|
||||
Inventory,
|
||||
StageSelect,
|
||||
}
|
||||
|
||||
impl Not for ConfirmSelection {
|
||||
type Output = ConfirmSelection;
|
||||
|
||||
|
@ -342,10 +354,11 @@ pub enum TextScriptExecutionState {
|
|||
}
|
||||
|
||||
pub struct TextScriptVM {
|
||||
pub scripts: TextScriptVMScripts,
|
||||
pub scripts: Scripts,
|
||||
pub state: TextScriptExecutionState,
|
||||
pub stack: Vec<TextScriptExecutionState>,
|
||||
pub flags: TextScriptFlags,
|
||||
pub mode: ScriptMode,
|
||||
/// 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
|
||||
/// 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,
|
||||
/// <Map>.tsc - map script
|
||||
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>> {
|
||||
if let Some(tsc) = self.scene_script.event_map.get(&event_num) {
|
||||
return Some(tsc);
|
||||
|
@ -400,9 +419,11 @@ fn read_cur_varint(cursor: &mut Cursor<&Vec<u8>>) -> GameResult<i32> {
|
|||
impl TextScriptVM {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
scripts: TextScriptVMScripts {
|
||||
scripts: Scripts {
|
||||
global_script: TextScript::new(),
|
||||
scene_script: TextScript::new(),
|
||||
inventory_script: TextScript::new(),
|
||||
stage_select_script: TextScript::new(),
|
||||
},
|
||||
state: TextScriptExecutionState::Ended,
|
||||
stack: Vec::with_capacity(6),
|
||||
|
@ -415,6 +436,7 @@ impl TextScriptVM {
|
|||
line_1: Vec::with_capacity(24),
|
||||
line_2: Vec::with_capacity(24),
|
||||
line_3: Vec::with_capacity(24),
|
||||
mode: ScriptMode::Map,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -428,20 +450,12 @@ impl TextScriptVM {
|
|||
if !self.suspend { self.reset(); }
|
||||
}
|
||||
|
||||
pub fn append_global_script(&mut self, script: TextScript) {
|
||||
for (key, val) in script.event_map {
|
||||
self.scripts.global_script.event_map.insert(key, val);
|
||||
pub fn set_inventory_script(&mut self, script: TextScript) {
|
||||
self.scripts.inventory_script = script;
|
||||
}
|
||||
|
||||
if !self.suspend { self.reset(); }
|
||||
}
|
||||
|
||||
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 set_stage_select_script(&mut self, script: TextScript) {
|
||||
self.scripts.stage_select_script = script;
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
|
@ -459,6 +473,8 @@ impl TextScriptVM {
|
|||
self.line_3.clear();
|
||||
}
|
||||
|
||||
pub fn set_mode(&mut self, mode: ScriptMode) {}
|
||||
|
||||
pub fn start_script(&mut self, event_num: u16) {
|
||||
self.reset();
|
||||
self.state = TextScriptExecutionState::Running(event_num, 0);
|
||||
|
@ -1232,9 +1248,9 @@ impl TextScriptVM {
|
|||
}
|
||||
// unimplemented opcodes
|
||||
// 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::SAT | OpCode::SLP | OpCode::SPS |
|
||||
OpCode::SAT | OpCode::SLP | OpCode::SPS | OpCode::FR2 |
|
||||
OpCode::STC | OpCode::SVP | OpCode::TUR | OpCode::HM2 => {
|
||||
log::warn!("unimplemented opcode: {:?}", op);
|
||||
|
||||
|
@ -1513,7 +1529,7 @@ impl TextScript {
|
|||
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::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);
|
||||
}
|
||||
// One operand codes
|
||||
|
|
Loading…
Reference in a new issue