lua api for lighting

This commit is contained in:
Alula 2021-08-16 19:12:00 +02:00
parent 55afe1292f
commit e80673ecb5
No known key found for this signature in database
GPG Key ID: 3E00485503A1D8BA
4 changed files with 139 additions and 14 deletions

View File

@ -57,6 +57,7 @@ pub struct GameScene {
pub npc_list: NPCList,
pub boss: BossNPC,
pub bullet_manager: BulletManager,
pub lighting_mode: LightingMode,
pub intro_mode: bool,
tex_background_name: String,
tex_tileset_name: String,
@ -75,6 +76,14 @@ pub enum TileLayer {
Snack,
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum LightingMode {
None,
BackgroundOnly,
Ambient,
}
const FACE_TEX: &str = "Face";
const SWITCH_FACE_TEX: [&str; 4] = ["Face1", "Face2", "Face3", "Face4"];
const P2_LEFT_TEXT: &str = "< P2";
@ -141,6 +150,7 @@ impl GameScene {
npc_list: NPCList::new(),
boss: BossNPC::new(),
bullet_manager: BulletManager::new(),
lighting_mode: LightingMode::None,
intro_mode: false,
tex_background_name,
tex_tileset_name,
@ -1779,6 +1789,19 @@ impl Scene for GameScene {
self.frame.target_y = self.player1.y;
self.frame.immediate_update(state, &self.stage);
self.lighting_mode = match () {
_ if self.intro_mode => LightingMode::None,
_ if !state.constants.is_switch && (self.stage.data.background_type == BackgroundType::Black
|| self.stage.data.background.name() == "bkBlack") => LightingMode::Ambient,
_ if state.constants.is_switch && (self.stage.data.background_type == BackgroundType::Black
|| self.stage.data.background.name() == "bkBlack") => LightingMode::None,
_ if self.stage.data.background_type != BackgroundType::Black
&& self.stage.data.background_type != BackgroundType::Outside
&& self.stage.data.background_type != BackgroundType::OutsideWind
&& self.stage.data.background.name() != "bkBlack" => LightingMode::BackgroundOnly,
_ => LightingMode::None,
};
Ok(())
}
@ -1925,12 +1948,7 @@ impl Scene for GameScene {
self.draw_npc_layer(state, ctx, NPCLayer::Background)?;
self.draw_tiles(state, ctx, TileLayer::Middleground)?;
if state.settings.shader_effects
&& self.stage.data.background_type != BackgroundType::Black
&& self.stage.data.background_type != BackgroundType::Outside
&& self.stage.data.background_type != BackgroundType::OutsideWind
&& self.stage.data.background.name() != "bkBlack"
{
if state.settings.shader_effects && self.lighting_mode == LightingMode::BackgroundOnly {
self.draw_light_map(state, ctx)?;
}
@ -1947,18 +1965,11 @@ impl Scene for GameScene {
self.player1.popup.draw(state, ctx, &self.frame)?;
self.player2.popup.draw(state, ctx, &self.frame)?;
if !self.intro_mode
&& state.settings.shader_effects
&& (self.stage.data.background_type == BackgroundType::Black
|| self.stage.data.background.name() == "bkBlack")
{
if state.settings.shader_effects && self.lighting_mode == LightingMode::Ambient {
self.draw_light_map(state, ctx)?;
}
self.flash.draw(state, ctx, &self.frame)?;
/*graphics::set_canvas(ctx, None);
state.game_canvas.draw(ctx, DrawParam::new()
.scale(Vector2::new(1.0 / state.scale, 1.0 / state.scale)))?;*/
self.draw_black_bars(state, ctx)?;
match state.textscript_vm.mode {

View File

@ -49,6 +49,16 @@ ModCS = {
Sound = {},
}
__doukutsu_rs_runtime_dont_touch._known_settings = {
["doukutsu-rs.intro.event_id"] = 0x1000,
["doukutsu-rs.intro.stage_id"] = 0x1001,
["doukutsu-rs.intro.pos"] = 0x1002,
["doukutsu-rs.new_game.event_id"] = 0x1003,
["doukutsu-rs.new_game.stage_id"] = 0x1004,
["doukutsu-rs.new_game.pos"] = 0x1005,
["doukutsu-rs.font_scale"] = 0x2000,
}
__doukutsu_rs_runtime_dont_touch._requires = {}
require = function(modname)
@ -332,6 +342,26 @@ end
__doukutsu_rs_runtime_dont_touch._playerRef0 = __doukutsu_rs_runtime_dont_touch._createPlayerRef(0)
__doukutsu_rs_runtime_dont_touch._playerRef1 = __doukutsu_rs_runtime_dont_touch._createPlayerRef(1)
doukutsu.rs = {}
setmetatable(doukutsu.rs, {
__index = function(self, property)
if property == "lightingMode" then
return __doukutsu_rs:stageCommand(0x01)
elseif property == "lightingEnabled" then
return __doukutsu_rs:stageCommand(0x02)
else
return nil
end
end,
__newindex = function(self, property, val)
if property == "lightingMode" then
__doukutsu_rs:stageCommand(0x101, val)
end
return nil
end,
})
doukutsu.player = __doukutsu_rs_runtime_dont_touch._playerRef0
function doukutsu.playSfx(id)
@ -350,6 +380,15 @@ function doukutsu.players()
return { __doukutsu_rs_runtime_dont_touch._playerRef0, __doukutsu_rs_runtime_dont_touch._playerRef1 }
end
function doukutsu.setSetting(key, value)
assert(type(key) == "string", "key must be a string.")
local id = __doukutsu_rs_runtime_dont_touch._known_settings[key]
if id ~= nil then
__doukutsu_rs:setEngineConstant(id, value)
end
end
function doukutsu.setNPCHandler(npc_type, handler)
assert(type(npc_type) == "number", "npc type must be an integer.")

View File

@ -181,6 +181,21 @@ declare interface DoukutsuPlayer {
damage(value: number): void;
}
declare interface DoukutsuRSApi {
/**
* Lighting mode of current stage.
* "none" - no lighting, similar to vanilla.
* "backgroundOnly" - lighting only affects background layer, similar to Switch version.
* "ambient" - lighting affects everything.
*/
lightingMode: "none" | "backgroundOnly" | "ambient";
/**
* This property is true if lighting is enabled in settings.
*/
readonly lightingEnabled: boolean;
}
declare namespace doukutsu {
/**
* A reference to main locally controlled player.
@ -188,6 +203,11 @@ declare namespace doukutsu {
*/
const player: DoukutsuPlayer;
/**
* Helper property for doukutsu-rs specific APIs.
*/
const rs: DoukutsuRSApi;
/**
* Plays a sound effect with specified ID.
*/
@ -248,6 +268,13 @@ declare namespace doukutsu {
*/
function setSetting(name: string, value: any): void;
/**
* Sets an implementation-defined stage parameter.
* @param name
* @param value
*/
function setStageParam(name: string, value: any): void;
/**
* Sets the handler override for specified NPC type. Passing a null removes the handler.
* @param npcType

View File

@ -7,6 +7,7 @@ use crate::common::{Direction, Rect};
use crate::framework::filesystem;
use crate::rng::RNG;
use crate::scripting::{check_status, LuaScriptingState, DRS_RUNTIME_GLOBAL};
use crate::scene::game_scene::LightingMode;
pub struct Doukutsu {
pub ptr: *mut LuaScriptingState,
@ -153,6 +154,14 @@ impl Doukutsu {
game_state.constants.game.new_game_player_pos = (ng_x as i16, ng_y as i16);
}
}
0x2000 => {
// font scale
if let Some(font_scale) = state.to_float(3) {
if font_scale > 0.0 {
game_state.constants.font_scale = font_scale;
}
}
}
_ => {}
}
}
@ -414,6 +423,44 @@ impl Doukutsu {
1
}
unsafe fn lua_stage_command(&self, state: &mut State) -> c_int {
if (*self.ptr).game_scene.is_null() {
state.push_nil();
return 1;
}
if let Some(param_type) = state.to_int(2) {
let game_scene = &mut *(*self.ptr).game_scene;
let game_state = &mut *(*self.ptr).state_ptr;
match param_type {
0x01 => state.push(match game_scene.lighting_mode {
LightingMode::None => "none",
LightingMode::BackgroundOnly => "backgroundOnly",
LightingMode::Ambient => "ambient",
}),
0x02 => state.push(game_state.settings.shader_effects),
0x101 => {
if let Some(v) = state.to_str(4) {
game_scene.lighting_mode = match v {
"none" => LightingMode::None,
"backgroundOnly" => LightingMode::BackgroundOnly,
"ambient" => LightingMode::Ambient,
_ => game_scene.lighting_mode,
};
}
state.push_nil();
}
_ => state.push_nil(),
}
} else {
state.push_nil()
}
1
}
unsafe fn lua_load_script(&mut self, state: &mut State) -> c_int {
let lua_state = &mut (*self.ptr);
@ -478,6 +525,7 @@ impl LuaObject for Doukutsu {
lua_method!("setEngineConstant", Doukutsu, Doukutsu::lua_set_engine_constant),
lua_method!("playerCommand", Doukutsu, Doukutsu::lua_player_command),
lua_method!("npcCommand", Doukutsu, Doukutsu::lua_npc_command),
lua_method!("stageCommand", Doukutsu, Doukutsu::lua_stage_command),
lua_method!("loadScript", Doukutsu, Doukutsu::lua_load_script),
]
}