Bug fix: level_script_parse (#366)

* Bug fix: level_script_parse

* level_is_vanilla_level
This commit is contained in:
PeachyPeach 2023-04-29 01:55:29 +02:00 committed by GitHub
parent c042ffca02
commit adba0f6de8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 186 additions and 39 deletions

View file

@ -8048,6 +8048,12 @@ function network_discord_id_from_local_index(localIndex)
-- ...
end
--- @param levelNum integer
--- @return boolean
function level_is_vanilla_level(levelNum)
-- ...
end
--- @param scriptEntryName string
--- @param courseNum integer
--- @param fullName string
@ -8308,9 +8314,9 @@ function camera_unfreeze()
-- ...
end
--- @param levelNum integer
--- @param courseNum integer
--- @return boolean
function course_is_main_course(levelNum)
function course_is_main_course(courseNum)
-- ...
end

View file

@ -338,6 +338,7 @@
--- @field public echoLevel3 integer
--- @field public fullName string
--- @field public levelNum integer
--- @field public modIndex integer
--- @field public next CustomLevelInfo
--- @field public script Pointer_LevelScript
--- @field public scriptEntryName string

View file

@ -62,6 +62,8 @@ u64 dynos_level_cmd_get(void *cmd, u64 offset);
void dynos_level_cmd_next(void *cmd, u64 cmdsize);
void dynos_level_parse_script(const void *script, s32 (*aPreprocessFunction)(u8, void *));
void* dynos_level_get_script(s32 level);
s32 dynos_level_get_mod_index(s32 level);
bool dynos_level_is_vanilla_level(s32 level);
// -- behaviors -- //
void dynos_add_behavior(s32 modIndex, const char *filePath, const char *behaviorName);

View file

@ -814,9 +814,11 @@ void *DynOS_Geo_GetGraphNode(const void *aGeoLayout, bool aKeepInMemory);
s32 DynOS_Level_GetCount();
const s32 *DynOS_Level_GetList();
s32 DynOS_Level_GetCourse(s32 aLevel);
void DynOS_Level_Override(void* originalScript, void* newScript);
void DynOS_Level_Override(void* originalScript, void* newScript, s32 modIndex);
void DynOS_Level_Unoverride();
const void *DynOS_Level_GetScript(s32 aLevel);
s32 DynOS_Level_GetModIndex(s32 aLevel);
bool DynOS_Level_IsVanillaLevel(s32 aLevel);
const u8 *DynOS_Level_GetName(s32 aLevel, bool aDecaps, bool aAddCourseNumber);
const u8 *DynOS_Level_GetActName(s32 aLevel, s32 aAct, bool aDecaps, bool aAddStarNumber);
const u8 *DynOS_Level_GetAreaName(s32 aLevel, s32 aArea, bool aDecaps);

View file

@ -200,6 +200,14 @@ void* dynos_level_get_script(s32 level) {
return (void *) DynOS_Level_GetScript(level);
}
s32 dynos_level_get_mod_index(s32 level) {
return DynOS_Level_GetModIndex(level);
}
bool dynos_level_is_vanilla_level(s32 level) {
return DynOS_Level_IsVanillaLevel(level);
}
// -- Behaviors -- //
void dynos_add_behavior(s32 modIndex, const char *filePath, const char *behaviorName) {

View file

@ -46,7 +46,14 @@ struct DynosWarp {
/* 9 */ s16 mDestId = 0;
};
static void *sDynosLevelScripts[LEVEL_COUNT] = { NULL };
struct DynosLevelScript {
void *mLevelScript;
s32 mModIndex;
};
#define DYNOS_LEVEL_MOD_INDEX_VANILLA (-1)
static DynosLevelScript sDynosLevelScripts[LEVEL_COUNT] = { { NULL, DYNOS_LEVEL_MOD_INDEX_VANILLA } };
static void *sDynosLevelScriptsOriginal[LEVEL_COUNT] = { NULL };
static Array<DynosWarp> sDynosLevelWarps[LEVEL_COUNT] = { Array<DynosWarp>() };
static Array<s32> sDynosLevelList = Array<s32>(); // Ordered by Course Id, COURSE_NONE excluded
@ -90,8 +97,9 @@ static s32 DynOS_Level_PreprocessMasterScript(u8 aType, void *aCmd) {
// EXECUTE
if (aType == 0x00) {
void *_Script = (void *) DynOS_Level_CmdGet(aCmd, 0x0C);
if (sDynosLevelNum >= 0 && sDynosLevelNum < LEVEL_COUNT && !sDynosLevelScripts[sDynosLevelNum]) {
sDynosLevelScripts[sDynosLevelNum] = _Script;
if (sDynosLevelNum >= 0 && sDynosLevelNum < LEVEL_COUNT && !sDynosLevelScripts[sDynosLevelNum].mLevelScript) {
sDynosLevelScripts[sDynosLevelNum].mLevelScript = _Script;
sDynosLevelScripts[sDynosLevelNum].mModIndex = DYNOS_LEVEL_MOD_INDEX_VANILLA;
sDynosLevelScriptsOriginal[sDynosLevelNum] = _Script;
}
sDynosLevelNum = -1;
@ -190,8 +198,8 @@ static void DynOS_Level_Init() {
// Level warps
for (sDynosCurrentLevelNum = 0; sDynosCurrentLevelNum != LEVEL_COUNT; ++sDynosCurrentLevelNum) {
if (sDynosLevelScripts[sDynosCurrentLevelNum]) {
DynOS_Level_ParseScript(sDynosLevelScripts[sDynosCurrentLevelNum], DynOS_Level_PreprocessScript);
if (sDynosLevelScripts[sDynosCurrentLevelNum].mLevelScript) {
DynOS_Level_ParseScript(sDynosLevelScripts[sDynosCurrentLevelNum].mLevelScript, DynOS_Level_PreprocessScript);
}
}
@ -228,13 +236,14 @@ s32 DynOS_Level_GetCourse(s32 aLevel) {
return (s32) gLevelToCourseNumTable[aLevel - 1];
}
void DynOS_Level_Override(void* originalScript, void* newScript) {
void DynOS_Level_Override(void* originalScript, void* newScript, s32 modIndex) {
for (s32 i = 0; i < LEVEL_COUNT; i++) {
if (sDynosLevelScripts[i] == originalScript) {
if (sDynosLevelScripts[i].mLevelScript == originalScript) {
sDynosCurrentLevelNum = i;
sDynosLevelWarps[i].Clear();
DynOS_Level_ParseScript(newScript, DynOS_Level_PreprocessScript);
sDynosLevelScripts[i] = newScript;
sDynosLevelScripts[i].mLevelScript = newScript;
sDynosLevelScripts[i].mModIndex = modIndex;
return;
}
}
@ -244,8 +253,9 @@ void DynOS_Level_Unoverride() {
for (s32 i = 0; i < LEVEL_COUNT; i++) {
sDynosCurrentLevelNum = i;
sDynosLevelWarps[i].Clear();
sDynosLevelScripts[i] = sDynosLevelScriptsOriginal[i];
DynOS_Level_ParseScript(sDynosLevelScripts[i], DynOS_Level_PreprocessScript);
sDynosLevelScripts[i].mLevelScript = sDynosLevelScriptsOriginal[i];
sDynosLevelScripts[i].mModIndex = DYNOS_LEVEL_MOD_INDEX_VANILLA;
DynOS_Level_ParseScript(sDynosLevelScripts[i].mLevelScript, DynOS_Level_PreprocessScript);
}
}
@ -257,7 +267,25 @@ const void *DynOS_Level_GetScript(s32 aLevel) {
}
DynOS_Level_Init();
return sDynosLevelScripts[aLevel];
return sDynosLevelScripts[aLevel].mLevelScript;
}
s32 DynOS_Level_GetModIndex(s32 aLevel) {
if (aLevel >= CUSTOM_LEVEL_NUM_START) {
struct CustomLevelInfo* info = smlua_level_util_get_info(aLevel);
if (!info || !info->script) { return DYNOS_LEVEL_MOD_INDEX_VANILLA; }
return info->modIndex;
}
DynOS_Level_Init();
return sDynosLevelScripts[aLevel].mModIndex;
}
bool DynOS_Level_IsVanillaLevel(s32 aLevel) {
if (aLevel >= 0 && aLevel < LEVEL_COUNT) {
return sDynosLevelScripts[aLevel].mLevelScript == sDynosLevelScriptsOriginal[aLevel];
}
return false;
}
//
@ -886,11 +914,11 @@ s16 *DynOS_Level_GetWarpEntry(s32 aLevel, s32 aArea) {
extern const LevelScript level_castle_grounds_entry[];
extern const LevelScript level_castle_inside_entry[];
extern const LevelScript level_castle_courtyard_entry[];
if (sDynosLevelScripts[aLevel] == level_castle_inside_entry) {
if (sDynosLevelScripts[aLevel].mLevelScript == level_castle_inside_entry) {
return DynOS_Level_GetWarp(aLevel, aArea, (aArea == 3) ? 0x00 : 0x01);
} else if (sDynosLevelScripts[aLevel] == level_castle_grounds_entry) {
} else if (sDynosLevelScripts[aLevel].mLevelScript == level_castle_grounds_entry) {
return DynOS_Level_GetWarp(aLevel, aArea, 0x00);
} else if (sDynosLevelScripts[aLevel] == level_castle_courtyard_entry) {
} else if (sDynosLevelScripts[aLevel].mLevelScript == level_castle_courtyard_entry) {
return DynOS_Level_GetWarp(aLevel, aArea, 0x01);
}
}

View file

@ -90,7 +90,7 @@ void DynOS_Lvl_Activate(s32 modIndex, const SysPath &aFilename, const char *aLev
return;
}
DynOS_Level_Override((void*)originalScript, newScriptNode->mData);
DynOS_Level_Override((void*)originalScript, newScriptNode->mData, modIndex);
_OverrideLevelScripts.Add({ originalScript, newScriptNode->mData, _Node});
}

View file

@ -7285,6 +7285,26 @@
<br />
## [level_is_vanilla_level](#level_is_vanilla_level)
### Lua Example
`local booleanValue = level_is_vanilla_level(levelNum)`
### Parameters
| Field | Type |
| ----- | ---- |
| levelNum | `integer` |
### Returns
- `boolean`
### C Prototype
`bool level_is_vanilla_level(s16 levelNum);`
[:arrow_up_small:](#)
<br />
## [level_register](#level_register)
### Lua Example
@ -8133,18 +8153,18 @@
## [course_is_main_course](#course_is_main_course)
### Lua Example
`local booleanValue = course_is_main_course(levelNum)`
`local booleanValue = course_is_main_course(courseNum)`
### Parameters
| Field | Type |
| ----- | ---- |
| levelNum | `integer` |
| courseNum | `integer` |
### Returns
- `boolean`
### C Prototype
`bool course_is_main_course(u16 levelNum);`
`bool course_is_main_course(u16 courseNum);`
[:arrow_up_small:](#)

View file

@ -1498,6 +1498,7 @@
<br />
- smlua_level_utils.h
- [level_is_vanilla_level](functions-4.md#level_is_vanilla_level)
- [level_register](functions-4.md#level_register)
- [smlua_level_util_get_info](functions-4.md#smlua_level_util_get_info)
- [smlua_level_util_get_info_from_short_name](functions-4.md#smlua_level_util_get_info_from_short_name)

View file

@ -538,6 +538,7 @@
| echoLevel3 | `integer` | |
| fullName | `string` | read-only |
| levelNum | `integer` | |
| modIndex | `integer` | |
| next | [CustomLevelInfo](structs.md#CustomLevelInfo) | |
| script | `Pointer` <`LevelScript`> | read-only |
| scriptEntryName | `string` | read-only |

View file

@ -394,7 +394,7 @@ static struct LuaObjectField sControllerFields[LUA_CONTROLLER_FIELD_COUNT] = {
{ "stickY", LVT_F32, offsetof(struct Controller, stickY), false, LOT_NONE },
};
#define LUA_CUSTOM_LEVEL_INFO_FIELD_COUNT 11
#define LUA_CUSTOM_LEVEL_INFO_FIELD_COUNT 12
static struct LuaObjectField sCustomLevelInfoFields[LUA_CUSTOM_LEVEL_INFO_FIELD_COUNT] = {
{ "acousticReach", LVT_U32, offsetof(struct CustomLevelInfo, acousticReach), false, LOT_NONE },
{ "courseNum", LVT_S16, offsetof(struct CustomLevelInfo, courseNum), false, LOT_NONE },
@ -403,6 +403,7 @@ static struct LuaObjectField sCustomLevelInfoFields[LUA_CUSTOM_LEVEL_INFO_FIELD_
{ "echoLevel3", LVT_U32, offsetof(struct CustomLevelInfo, echoLevel3), false, LOT_NONE },
{ "fullName", LVT_STRING_P, offsetof(struct CustomLevelInfo, fullName), true, LOT_NONE },
{ "levelNum", LVT_S16, offsetof(struct CustomLevelInfo, levelNum), false, LOT_NONE },
{ "modIndex", LVT_S32, offsetof(struct CustomLevelInfo, modIndex), false, LOT_NONE },
{ "next", LVT_COBJECT_P, offsetof(struct CustomLevelInfo, next), false, LOT_CUSTOMLEVELINFO },
{ "script", LVT_LEVELSCRIPT_P, offsetof(struct CustomLevelInfo, script), true, LOT_POINTER },
{ "scriptEntryName", LVT_STRING_P, offsetof(struct CustomLevelInfo, scriptEntryName), true, LOT_NONE },

View file

@ -9,6 +9,7 @@
#include "audio/external.h"
#include "object_fields.h"
#include "engine/math_util.h"
#include "engine/level_script.h"
#include "pc/djui/djui_hud_utils.h"
#include "include/level_misc_macros.h"
#include "include/macro_presets.h"
@ -499,23 +500,41 @@ s32 smlua_func_level_script_parse_callback(u8 type, void *cmd) {
// OBJECT_WITH_ACTS_EXT
case 0x3F: {
const char *bhvStr = dynos_level_get_token(dynos_level_cmd_get(cmd, 20));
if (bhvStr) {
bhvId = (u32) smlua_get_any_integer_mod_variable(bhvStr);
bhvArgs = (u32) dynos_level_cmd_get(cmd, 16);
pBhvId = &bhvId;
pBhvArgs = &bhvArgs;
if (gLevelScriptModIndex != -1) {
const char *bhvStr = dynos_level_get_token(dynos_level_cmd_get(cmd, 20));
if (bhvStr) {
gSmLuaConvertSuccess = true;
bhvId = (u32) smlua_get_integer_mod_variable(gLevelScriptModIndex, bhvStr);
if (!gSmLuaConvertSuccess) {
gSmLuaConvertSuccess = true;
bhvId = (u32) smlua_get_any_integer_mod_variable(bhvStr);
}
if (gSmLuaConvertSuccess) {
bhvArgs = (u32) dynos_level_cmd_get(cmd, 16);
pBhvId = &bhvId;
pBhvArgs = &bhvArgs;
}
}
}
} break;
// OBJECT_WITH_ACTS_EXT2
case 0x40: {
const char *bhvStr = dynos_level_get_token(dynos_level_cmd_get(cmd, 24));
if (bhvStr) {
bhvId = (u32) smlua_get_any_integer_mod_variable(bhvStr);
bhvArgs = (u32) dynos_level_cmd_get(cmd, 16);
pBhvId = &bhvId;
pBhvArgs = &bhvArgs;
if (gLevelScriptModIndex != -1) {
const char *bhvStr = dynos_level_get_token(dynos_level_cmd_get(cmd, 24));
if (bhvStr) {
gSmLuaConvertSuccess = true;
bhvId = (u32) smlua_get_integer_mod_variable(gLevelScriptModIndex, bhvStr);
if (!gSmLuaConvertSuccess) {
gSmLuaConvertSuccess = true;
bhvId = (u32) smlua_get_any_integer_mod_variable(bhvStr);
}
if (gSmLuaConvertSuccess) {
bhvArgs = (u32) dynos_level_cmd_get(cmd, 16);
pBhvId = &bhvId;
pBhvArgs = &bhvArgs;
}
}
}
} break;
@ -612,7 +631,20 @@ void smlua_func_level_script_parse(lua_State* L) {
LOG_LUA("Failed to find script: %lld", levelNum);
return;
}
s32 modIndex = dynos_level_get_mod_index(levelNum);
// Back up current values
LevelScript *currLevelScript = gLevelScriptActive;
s32 currModIndex = gLevelScriptModIndex;
// Parse script
gLevelScriptActive = (LevelScript *) script;
gLevelScriptModIndex = modIndex;
dynos_level_parse_script(script, smlua_func_level_script_parse_callback);
// Restore current values
gLevelScriptActive = currLevelScript;
gLevelScriptModIndex = currModIndex;
}
//////////

View file

@ -26369,6 +26369,23 @@ int smlua_func_network_discord_id_from_local_index(lua_State* L) {
// smlua_level_utils.h //
/////////////////////////
int smlua_func_level_is_vanilla_level(lua_State* L) {
if (L == NULL) { return 0; }
int top = lua_gettop(L);
if (top != 1) {
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "level_is_vanilla_level", 1, top);
return 0;
}
s16 levelNum = smlua_to_integer(L, 1);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "level_is_vanilla_level"); return 0; }
lua_pushboolean(L, level_is_vanilla_level(levelNum));
return 1;
}
int smlua_func_level_register(lua_State* L) {
if (L == NULL) { return 0; }
@ -27116,10 +27133,10 @@ int smlua_func_course_is_main_course(lua_State* L) {
return 0;
}
u16 levelNum = smlua_to_integer(L, 1);
u16 courseNum = smlua_to_integer(L, 1);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "course_is_main_course"); return 0; }
lua_pushboolean(L, course_is_main_course(levelNum));
lua_pushboolean(L, course_is_main_course(courseNum));
return 1;
}
@ -30722,6 +30739,7 @@ void smlua_bind_functions_autogen(void) {
smlua_bind_function(L, "network_discord_id_from_local_index", smlua_func_network_discord_id_from_local_index);
// smlua_level_utils.h
smlua_bind_function(L, "level_is_vanilla_level", smlua_func_level_is_vanilla_level);
smlua_bind_function(L, "level_register", smlua_func_level_register);
smlua_bind_function(L, "smlua_level_util_get_info", smlua_func_smlua_level_util_get_info);
smlua_bind_function(L, "smlua_level_util_get_info_from_short_name", smlua_func_smlua_level_util_get_info_from_short_name);

View file

@ -106,6 +106,27 @@ s16 level_register(const char* scriptEntryName, s16 courseNum, const char* fullN
info->echoLevel1 = echoLevel1;
info->echoLevel2 = echoLevel2;
info->echoLevel3 = echoLevel3;
if (gLuaLoadingMod) {
info->modIndex = gLuaLoadingMod->index;
} else if (gLuaActiveMod) {
info->modIndex = gLuaActiveMod->index;
} else {
if (info->scriptEntryName) {
free(info->scriptEntryName);
info->scriptEntryName = NULL;
}
if (info->fullName) {
free(info->fullName);
info->fullName = NULL;
}
if (info->shortName) {
free(info->shortName);
info->shortName = NULL;
}
free(info);
LOG_LUA("Failed to find mod index for level: %s", scriptEntryName);
return 0;
}
// add to list
if (!sCustomLevelHead) {
@ -126,6 +147,10 @@ s16 level_register(const char* scriptEntryName, s16 courseNum, const char* fullN
return 0;
}
bool level_is_vanilla_level(s16 levelNum) {
return dynos_level_is_vanilla_level(levelNum);
}
bool warp_to_warpnode(s32 aLevel, s32 aArea, s32 aAct, s32 aWarpId) {
return dynos_warp_to_warpnode(aLevel, aArea, aAct, aWarpId);
}

View file

@ -12,6 +12,7 @@ struct CustomLevelInfo {
u32 echoLevel1;
u32 echoLevel2;
u32 echoLevel3;
s32 modIndex;
struct CustomLevelInfo* next;
};
@ -21,6 +22,7 @@ void smlua_level_util_reset(void);
struct CustomLevelInfo* smlua_level_util_get_info(s16 levelNum);
struct CustomLevelInfo* smlua_level_util_get_info_from_short_name(char* shortName);
s16 level_register(const char* scriptEntryName, s16 courseNum, const char* fullName, const char* shortName, u32 acousticReach, u32 echoLevel1, u32 echoLevel2, u32 echoLevel3);
bool level_is_vanilla_level(s16 levelNum);
bool warp_to_warpnode(s32 aLevel, s32 aArea, s32 aAct, s32 aWarpId);
bool warp_to_level(s32 aLevel, s32 aArea, s32 aAct);
bool warp_restart_level(void);

View file

@ -448,8 +448,8 @@ void set_override_skybox(s8 background) {
///
bool course_is_main_course(u16 levelNum) {
return COURSE_IS_MAIN_COURSE(levelNum);
bool course_is_main_course(u16 courseNum) {
return COURSE_IS_MAIN_COURSE(courseNum);
}
///

View file

@ -101,7 +101,7 @@ void set_override_skybox(s8 background);
void play_transition(s16 transType, s16 time, u8 red, u8 green, u8 blue);
bool course_is_main_course(u16 levelNum);
bool course_is_main_course(u16 courseNum);
s16 get_ttc_speed_setting();
void set_ttc_speed_setting(s16 speed);