From 1c71449ed20b1518437ad0317eb42e3c4232e561 Mon Sep 17 00:00:00 2001 From: Beckowl <68874587+Beckowl@users.noreply.github.com> Date: Sat, 13 Sep 2025 15:36:28 -0300 Subject: [PATCH] Add lua params support to level macros (allocate dialog pt. 2) (#905) * all OBJECT fields are now Lua variables * add lua variable support to SHOW_DIALOG * fix object_with_acts * minor tweak * Peachy review --------- Co-authored-by: PeachyPeachSM64 <72323920+PeachyPeachSM64@users.noreply.github.com> --- data/behavior_table.c | 2 + data/dynos_bin_lvl.cpp | 114 ++++++++++--------- data/dynos_bin_lvl_validate.cpp | 2 + include/level_commands.h | 52 +++++++++ src/engine/level_script.c | 188 +++++++++++++++----------------- src/game/area.h | 6 +- src/pc/lua/smlua_functions.c | 107 ++++++++++-------- 7 files changed, 270 insertions(+), 201 deletions(-) diff --git a/data/behavior_table.c b/data/behavior_table.c index 46c03b76c..6fbdf122b 100644 --- a/data/behavior_table.c +++ b/data/behavior_table.c @@ -558,6 +558,8 @@ const struct BehaviorTableEntry gBehaviorTable[id_bhv_max_count] = { enum BehaviorId get_id_from_behavior(const BehaviorScript* behavior) { if (behavior == NULL) { return id_bhv_max_count; } + if ((behavior[0] >> 24) != 0x00) { return id_bhv_max_count; } // check for BEGIN + if ((behavior[1] >> 24) != 0x39) { return id_bhv_max_count; } // check for ID return (enum BehaviorId)(behavior[1] & 0xFFFF); } diff --git a/data/dynos_bin_lvl.cpp b/data/dynos_bin_lvl.cpp index e3e9a27ed..ff20ede76 100644 --- a/data/dynos_bin_lvl.cpp +++ b/data/dynos_bin_lvl.cpp @@ -641,6 +641,15 @@ static LevelScript ParseLevelScriptSymbolArg(GfxData* aGfxData, DataNode* aNode, u64& aTokenIndex, u32 *luaParams, u32 luaParamFlag) { + bool foundParam = true; + LevelScript value = ParseLevelScriptSymbolArgInternal(aGfxData, aNode, aTokenIndex, &foundParam); + if (!foundParam) { + *luaParams |= luaParamFlag; + } + return value; +} + static void ParseLevelScriptSymbol(GfxData* aGfxData, DataNode* aNode, LevelScript*& aHead, u64& aTokenIndex, Array& aSwitchNodes) { const String& _Symbol = aNode->mTokens[aTokenIndex++]; @@ -711,7 +720,6 @@ static void ParseLevelScriptSymbol(GfxData* aGfxData, DataNode* aNo lvl_symbol_0(CMD2D); lvl_symbol_1(TERRAIN, 1); lvl_symbol_1(ROOMS, 1); - lvl_symbol_2(SHOW_DIALOG, 0, 0); lvl_symbol_1(TERRAIN_TYPE, 0); lvl_symbol_0(NOP); @@ -733,75 +741,75 @@ static void ParseLevelScriptSymbol(GfxData* aGfxData, DataNode* aNo lvl_symbol_0(ADV_DEMO); lvl_symbol_0(CLEAR_DEMO_PTR); - // object - if (_Symbol == "OBJECT") { + // dialog + if (_Symbol == "SHOW_DIALOG") { u64 topTokenIndex = aTokenIndex; + + u32 luaParams = 0; + LevelScript index = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, SHOW_DIALOG_EXT_LUA_INDEX); + LevelScript dialogId = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, SHOW_DIALOG_EXT_LUA_DIALOG); - bool foundModel = true; - bool foundBeh = true; - LevelScript model = ParseLevelScriptSymbolArgInternal(aGfxData, aNode, aTokenIndex, &foundModel); - LevelScript posX = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); - LevelScript posY = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); - LevelScript posZ = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); - LevelScript angleX = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); - LevelScript angleY = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); - LevelScript angleZ = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); - LevelScript behParam = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); - LevelScript beh = ParseLevelScriptSymbolArgInternal(aGfxData, aNode, aTokenIndex, &foundBeh); + if (luaParams != 0) { + LevelScript finalIndex = (luaParams & SHOW_DIALOG_EXT_LUA_INDEX) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 1, aNode->mTokens[topTokenIndex + 0]) : index; + LevelScript finalDialogId = (luaParams & SHOW_DIALOG_EXT_LUA_DIALOG) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 2, aNode->mTokens[topTokenIndex + 1]) : dialogId; - if (foundModel && foundBeh) { - aGfxData->mPointerList.Add(aHead + 5); - LevelScript _Ls[] = { OBJECT(model, posX, posY, posZ, angleX, angleY, angleZ, behParam, beh) }; - memcpy(aHead, _Ls, sizeof(_Ls)); - aHead += (sizeof(_Ls) / sizeof(_Ls[0])); - } else if (foundModel) { - u32 behIndex = DynOS_Lua_RememberVariable(aGfxData, aHead + 5, aNode->mTokens[topTokenIndex + 8]); - LevelScript _Ls[] = { OBJECT_EXT(model, posX, posY, posZ, angleX, angleY, angleZ, behParam, behIndex) }; + LevelScript _Ls[] = { SHOW_DIALOG_EXT(luaParams, finalIndex, finalDialogId) }; memcpy(aHead, _Ls, sizeof(_Ls)); aHead += (sizeof(_Ls) / sizeof(_Ls[0])); } else { - u32 modelIndex = DynOS_Lua_RememberVariable(aGfxData, aHead + 5, aNode->mTokens[topTokenIndex + 0]); - u32 behIndex = DynOS_Lua_RememberVariable(aGfxData, aHead + 6, aNode->mTokens[topTokenIndex + 8]); - LevelScript _Ls[] = { OBJECT_EXT2(modelIndex, posX, posY, posZ, angleX, angleY, angleZ, behParam, behIndex) }; + LevelScript _Ls[] = { SHOW_DIALOG(index, dialogId) }; memcpy(aHead, _Ls, sizeof(_Ls)); aHead += (sizeof(_Ls) / sizeof(_Ls[0])); } return; } - // object with acts - if (_Symbol == "OBJECT_WITH_ACTS") { + // object + if (_Symbol == "OBJECT" || _Symbol == "OBJECT_WITH_ACTS") { u64 topTokenIndex = aTokenIndex; - bool foundModel = true; - bool foundBeh = true; - LevelScript model = ParseLevelScriptSymbolArgInternal(aGfxData, aNode, aTokenIndex, &foundModel); - LevelScript posX = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); - LevelScript posY = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); - LevelScript posZ = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); - LevelScript angleX = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); - LevelScript angleY = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); - LevelScript angleZ = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); - LevelScript behParam = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); - LevelScript beh = ParseLevelScriptSymbolArgInternal(aGfxData, aNode, aTokenIndex, &foundBeh); - LevelScript acts = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); + u32 luaParams = 0; + LevelScript model = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_MODEL); + LevelScript posX = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_POS_X); + LevelScript posY = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_POS_Y); + LevelScript posZ = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_POS_Z); + LevelScript angleX = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_ANGLE_X); + LevelScript angleY = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_ANGLE_Y); + LevelScript angleZ = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_ANGLE_Z); + LevelScript behParam = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_BEH_PARAMS); + LevelScript beh = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_BEHAVIOR); + LevelScript acts = (_Symbol == "OBJECT_WITH_ACTS") ? ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_ACTS) : 0x1F; - if (foundModel && foundBeh) { + // At least one parameter is a Lua variable, use OBJECT_EXT_LUA_PARAMS + if (luaParams != 0) { + + // Remember behavior pointer if it's not a Lua param + if (!(luaParams & OBJECT_EXT_LUA_BEHAVIOR)) { + aGfxData->mPointerList.Add(aHead + 9); + } + + LevelScript finalModel = (luaParams & OBJECT_EXT_LUA_MODEL) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 1, aNode->mTokens[topTokenIndex + 0]) : model; + LevelScript finalPosX = (luaParams & OBJECT_EXT_LUA_POS_X) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 2, aNode->mTokens[topTokenIndex + 1]) : posX; + LevelScript finalPosY = (luaParams & OBJECT_EXT_LUA_POS_Y) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 3, aNode->mTokens[topTokenIndex + 2]) : posY; + LevelScript finalPosZ = (luaParams & OBJECT_EXT_LUA_POS_Z) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 4, aNode->mTokens[topTokenIndex + 3]) : posZ; + LevelScript finalAngleX = (luaParams & OBJECT_EXT_LUA_ANGLE_X) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 5, aNode->mTokens[topTokenIndex + 4]) : angleX; + LevelScript finalAngleY = (luaParams & OBJECT_EXT_LUA_ANGLE_Y) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 6, aNode->mTokens[topTokenIndex + 5]) : angleY; + LevelScript finalAngleZ = (luaParams & OBJECT_EXT_LUA_ANGLE_Z) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 7, aNode->mTokens[topTokenIndex + 6]) : angleZ; + LevelScript finalBehParam = (luaParams & OBJECT_EXT_LUA_BEH_PARAMS) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 8, aNode->mTokens[topTokenIndex + 7]) : behParam; + LevelScript finalBeh = (luaParams & OBJECT_EXT_LUA_BEHAVIOR) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 9, aNode->mTokens[topTokenIndex + 8]) : beh; + LevelScript finalActs = (luaParams & OBJECT_EXT_LUA_ACTS) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 10, aNode->mTokens[topTokenIndex + 9]) : acts; + + LevelScript _Ls[] = { OBJECT_EXT_LUA_PARAMS(luaParams, finalModel, finalPosX, finalPosY, finalPosZ, finalAngleX, finalAngleY, finalAngleZ, finalBehParam, finalBeh, finalActs) }; + memcpy(aHead, _Ls, sizeof(_Ls)); + aHead += (sizeof(_Ls) / sizeof(_Ls[0])); + } + + // No Lua parameter, use OBJECT_WITH_ACTS + else { aGfxData->mPointerList.Add(aHead + 5); LevelScript _Ls[] = { OBJECT_WITH_ACTS(model, posX, posY, posZ, angleX, angleY, angleZ, behParam, beh, acts) }; memcpy(aHead, _Ls, sizeof(_Ls)); aHead += (sizeof(_Ls) / sizeof(_Ls[0])); - } else if (foundModel) { - u32 behIndex = DynOS_Lua_RememberVariable(aGfxData, aHead + 5, aNode->mTokens[topTokenIndex + 8]); - LevelScript _Ls[] = { OBJECT_WITH_ACTS_EXT(model, posX, posY, posZ, angleX, angleY, angleZ, behParam, behIndex, acts) }; - memcpy(aHead, _Ls, sizeof(_Ls)); - aHead += (sizeof(_Ls) / sizeof(_Ls[0])); - } else { - u32 modelIndex = DynOS_Lua_RememberVariable(aGfxData, aHead + 5, aNode->mTokens[topTokenIndex + 0]); - u32 behIndex = DynOS_Lua_RememberVariable(aGfxData, aHead + 6, aNode->mTokens[topTokenIndex + 8]); - LevelScript _Ls[] = { OBJECT_WITH_ACTS_EXT2(modelIndex, posX, posY, posZ, angleX, angleY, angleZ, behParam, behIndex, acts) }; - memcpy(aHead, _Ls, sizeof(_Ls)); - aHead += (sizeof(_Ls) / sizeof(_Ls[0])); } return; } @@ -1063,12 +1071,12 @@ static DataNode* DynOS_Lvl_Load(BinFile *aFile, GfxData *aGfxData) void *_Ptr = DynOS_Pointer_Load(aFile, aGfxData, _Value, FUNCTION_LVL, &_Node->mFlags); if (_Ptr) { - if (!requirePointer) { + if (!requirePointer && _Value != LUA_VAR_CODE) { PrintError("Didn't expect a pointer while reading level script: %s, %u", _Node->mName.begin(), _Value); } _Node->mData[i] = (uintptr_t) _Ptr; } else { - if (requirePointer) { + if (requirePointer && _Value != LUA_VAR_CODE) { PrintError("Expected a pointer while reading level script: %s, %u", _Node->mName.begin(), _Value); _Node->mData[i] = 0; } else { diff --git a/data/dynos_bin_lvl_validate.cpp b/data/dynos_bin_lvl_validate.cpp index 422d26a37..e592036ed 100644 --- a/data/dynos_bin_lvl_validate.cpp +++ b/data/dynos_bin_lvl_validate.cpp @@ -134,6 +134,8 @@ static void LvlCmd_Init() { ADD_COMMAND(OBJECT_EXT2(POINTER, 0, 0, 0, 0, 0, 0, 0, POINTER)); ADD_COMMAND(LOAD_MODEL_FROM_GEO_EXT(0, POINTER)); ADD_COMMAND(JUMP_AREA_EXT(0, 0, POINTER)); + ADD_COMMAND(OBJECT_EXT_LUA_PARAMS(0, 0, 0, 0, 0, 0, 0, 0, 0, POINTER, 0)); + ADD_COMMAND(SHOW_DIALOG_EXT(0, 0, 0)) } void DynOS_Lvl_Validate_Begin() { diff --git a/include/level_commands.h b/include/level_commands.h index 659c94425..b0258661c 100644 --- a/include/level_commands.h +++ b/include/level_commands.h @@ -30,6 +30,34 @@ #define WHIRLPOOL_COND_BOWSER2_BEATEN 2 #define WHIRLPOOL_COND_AT_LEAST_SECOND_STAR 3 +#define OBJECT_EXT_LUA_MODEL (1 << 0) +#define OBJECT_EXT_LUA_POS_X (1 << 1) +#define OBJECT_EXT_LUA_POS_Y (1 << 2) +#define OBJECT_EXT_LUA_POS_Z (1 << 3) +#define OBJECT_EXT_LUA_ANGLE_X (1 << 4) +#define OBJECT_EXT_LUA_ANGLE_Y (1 << 5) +#define OBJECT_EXT_LUA_ANGLE_Z (1 << 6) +#define OBJECT_EXT_LUA_BEH_PARAMS (1 << 7) +#define OBJECT_EXT_LUA_BEHAVIOR (1 << 8) +#define OBJECT_EXT_LUA_ACTS (1 << 9) + +#define OBJECT_EXT_LUA_MODEL_OFFSET(type) (type == 0x3F ? 3 : (type == 0x40 ? 20 : 4)) +#define OBJECT_EXT_LUA_POS_X_OFFSET(type) (type == 0x3F ? 4 : (type == 0x40 ? 4 : 8)) +#define OBJECT_EXT_LUA_POS_Y_OFFSET(type) (type == 0x3F ? 6 : (type == 0x40 ? 6 : 12)) +#define OBJECT_EXT_LUA_POS_Z_OFFSET(type) (type == 0x3F ? 8 : (type == 0x40 ? 8 : 16)) +#define OBJECT_EXT_LUA_ANGLE_X_OFFSET(type) (type == 0x3F ? 10 : (type == 0x40 ? 10 : 20)) +#define OBJECT_EXT_LUA_ANGLE_Y_OFFSET(type) (type == 0x3F ? 12 : (type == 0x40 ? 12 : 24)) +#define OBJECT_EXT_LUA_ANGLE_Z_OFFSET(type) (type == 0x3F ? 14 : (type == 0x40 ? 14 : 28)) +#define OBJECT_EXT_LUA_BEH_PARAMS_OFFSET(type) (type == 0x3F ? 16 : (type == 0x40 ? 16 : 32)) +#define OBJECT_EXT_LUA_BEHAVIOR_OFFSET(type) (type == 0x3F ? 20 : (type == 0x40 ? 24 : 36)) +#define OBJECT_EXT_LUA_ACTS_OFFSET(type) (type == 0x3F ? 2 : (type == 0x40 ? 2 : 40)) + +#define SHOW_DIALOG_EXT_LUA_INDEX (1 << 0) +#define SHOW_DIALOG_EXT_LUA_DIALOG (1 << 1) + +#define SHOW_DIALOG_EXT_LUA_INDEX_OFFSET(type) (4) +#define SHOW_DIALOG_EXT_LUA_DIALOG_OFFSET(type) (8) + // Head defines #define REGULAR_FACE 0x0002 #define DIZZY_FACE 0x0003 @@ -324,6 +352,30 @@ CMD_W(arg), \ CMD_PTR(target) +// This command is used when parameters are Lua variables. +// The flags parameter describes which parameter is a Lua variable. +// See OBJECT_EXT_LUA flags at the top of this file. +#define OBJECT_EXT_LUA_PARAMS(flags, model, posX, posY, posZ, angleX, angleY, angleZ, behParam, beh, acts) \ + CMD_BBH(0x43, 0x2C, flags), \ + CMD_PTR(model), \ + CMD_PTR(posX), \ + CMD_PTR(posY), \ + CMD_PTR(posZ), \ + CMD_PTR(angleX), \ + CMD_PTR(angleY), \ + CMD_PTR(angleZ), \ + CMD_PTR(behParam), \ + CMD_PTR(beh), \ + CMD_PTR(acts) + +// This command is used when parameters are Lua variables. +// The flags parameter describes which parameter is a Lua variable. +// See SHOW_DIALOG_EXT flags at the top of this file. +#define SHOW_DIALOG_EXT(flags, index, dialogId) \ + CMD_BBBB(0x44, 0x0C, flags, 0x00), \ + CMD_PTR(index), \ + CMD_PTR(dialogId) + // README // // README // // README // diff --git a/src/engine/level_script.c b/src/engine/level_script.c index 7d7129cbc..9f739ea69 100644 --- a/src/engine/level_script.c +++ b/src/engine/level_script.c @@ -18,6 +18,7 @@ #include "goddard/renderer.h" #include "geo_layout.h" #include "graph_node.h" +#include "level_commands.h" #include "level_script.h" #include "level_misc_macros.h" #include "macro_presets.h" @@ -918,124 +919,94 @@ static void level_cmd_cleardemoptr(void) sCurrentCmd = CMD_NEXT; } +// // coop -static void level_cmd_place_object_ext(void) { - u8 val7 = 1 << (gCurrActNum - 1); - struct SpawnInfo *spawnInfo; +// - u16 modIndex = gLevelScriptModIndex; - const char* behStr = dynos_level_get_token(CMD_GET(u32, 20)); +static bool find_lua_param(uintptr_t *param, u32 offset, u32 luaParams, u32 luaParamFlag, const char *paramType) { + *param = CMD_GET(uintptr_t, offset); + if (luaParams & luaParamFlag) { + if (gLevelScriptModIndex == -1) { + LOG_ERROR("Could not find level script mod index"); + return false; + } - if (gLevelScriptModIndex == -1) { - LOG_ERROR("Could not find level script mod index"); - sCurrentCmd = CMD_NEXT; - return; - } - - gSmLuaConvertSuccess = true; - enum BehaviorId behId = smlua_get_integer_mod_variable(modIndex, behStr); - - if (!gSmLuaConvertSuccess) { + const char *paramStr = dynos_level_get_token(*param); gSmLuaConvertSuccess = true; - behId = smlua_get_any_integer_mod_variable(behStr); + *param = smlua_get_integer_mod_variable(gLevelScriptModIndex, paramStr); + + if (!gSmLuaConvertSuccess) { + gSmLuaConvertSuccess = true; + *param = smlua_get_any_integer_mod_variable(paramStr); + } + + if (!gSmLuaConvertSuccess) { + LOG_LUA("Failed to execute level command, could not find parameter '%s'", paramStr); + return false; + } } - - if (!gSmLuaConvertSuccess) { - LOG_LUA("Failed to place custom object, could not find behavior '%s'", behStr); - sCurrentCmd = CMD_NEXT; - return; - } - - if (sCurrAreaIndex != -1 && (gLevelValues.disableActs || (CMD_GET(u8, 2) & val7) || CMD_GET(u8, 2) == 0x1F)) { - u16 model = CMD_GET(u8, 3); - spawnInfo = dynamic_pool_alloc(gLevelPool, sizeof(struct SpawnInfo)); - - spawnInfo->startPos[0] = CMD_GET(s16, 4); - spawnInfo->startPos[1] = CMD_GET(s16, 6); - spawnInfo->startPos[2] = CMD_GET(s16, 8); - - spawnInfo->startAngle[0] = CMD_GET(s16, 10) * 0x8000 / 180; - spawnInfo->startAngle[1] = CMD_GET(s16, 12) * 0x8000 / 180; - spawnInfo->startAngle[2] = CMD_GET(s16, 14) * 0x8000 / 180; - - spawnInfo->areaIndex = sCurrAreaIndex; - spawnInfo->activeAreaIndex = sCurrAreaIndex; - - spawnInfo->behaviorArg = CMD_GET(u32, 16); - - spawnInfo->behaviorScript = (BehaviorScript*)get_behavior_from_id(behId); - spawnInfo->unk18 = dynos_model_get_geo(model); - spawnInfo->next = gAreas[sCurrAreaIndex].objectSpawnInfos; - - spawnInfo->syncID = spawnInfo->next - ? spawnInfo->next->syncID + 10 - : 10; - - gAreas[sCurrAreaIndex].objectSpawnInfos = spawnInfo; - area_check_red_coin_or_secret(spawnInfo->behaviorScript, false); - } - - sCurrentCmd = CMD_NEXT; + return true; } -static void level_cmd_place_object_ext2(void) { +#define get_lua_param(name, type, flag) \ + uintptr_t name##Param; \ + if (!find_lua_param(&name##Param, flag##_OFFSET(cmdType), luaParams, flag, #name)) { \ + sCurrentCmd = CMD_NEXT; \ + return; \ + } \ + type name = (type) name##Param; + +static void level_cmd_place_object_ext_lua_params(void) { u8 val7 = 1 << (gCurrActNum - 1); struct SpawnInfo *spawnInfo; - u16 modIndex = gLevelScriptModIndex; - const char* modelStr = dynos_level_get_token(CMD_GET(u32, 20)); - const char* behStr = dynos_level_get_token(CMD_GET(u32, 24)); + u8 cmdType = sCurrentCmd->type; + u16 luaParams = ( + cmdType == 0x3F ? OBJECT_EXT_LUA_BEHAVIOR : ( + cmdType == 0x40 ? OBJECT_EXT_LUA_BEHAVIOR | OBJECT_EXT_LUA_MODEL : ( + CMD_GET(u16, 2) + ))); - if (gLevelScriptModIndex == -1) { - LOG_ERROR("Could not find level script mod index"); - sCurrentCmd = CMD_NEXT; - return; - } + get_lua_param(acts, u8, OBJECT_EXT_LUA_ACTS); - gSmLuaConvertSuccess = true; - enum ModelExtendedId modelId = smlua_get_integer_mod_variable(modIndex, modelStr); - if (!gSmLuaConvertSuccess) { - gSmLuaConvertSuccess = true; - modelId = smlua_get_any_integer_mod_variable(modelStr); - } - if (!gSmLuaConvertSuccess) { - LOG_LUA("Failed to place custom object, could not find model '%s'", modelStr); - sCurrentCmd = CMD_NEXT; - return; - } - - gSmLuaConvertSuccess = true; - enum BehaviorId behId = smlua_get_integer_mod_variable(modIndex, behStr); - if (!gSmLuaConvertSuccess) { - gSmLuaConvertSuccess = true; - behId = smlua_get_any_integer_mod_variable(behStr); - } - - if (!gSmLuaConvertSuccess) { - LOG_LUA("Failed to place custom object, could not find behavior '%s'", behStr); - sCurrentCmd = CMD_NEXT; - return; - } - - if (sCurrAreaIndex != -1 && (gLevelValues.disableActs || (CMD_GET(u8, 2) & val7) || CMD_GET(u8, 2) == 0x1F)) { + if (sCurrAreaIndex != -1 && (gLevelValues.disableActs || (acts & val7) || acts == 0x1F)) { spawnInfo = dynamic_pool_alloc(gLevelPool, sizeof(struct SpawnInfo)); - spawnInfo->startPos[0] = CMD_GET(s16, 4); - spawnInfo->startPos[1] = CMD_GET(s16, 6); - spawnInfo->startPos[2] = CMD_GET(s16, 8); + get_lua_param(modelId, u32, OBJECT_EXT_LUA_MODEL); + get_lua_param(posX, s16, OBJECT_EXT_LUA_POS_X); + get_lua_param(posY, s16, OBJECT_EXT_LUA_POS_Y); + get_lua_param(posZ, s16, OBJECT_EXT_LUA_POS_Z); + get_lua_param(angleX, s16, OBJECT_EXT_LUA_ANGLE_X); + get_lua_param(angleY, s16, OBJECT_EXT_LUA_ANGLE_Y); + get_lua_param(angleZ, s16, OBJECT_EXT_LUA_ANGLE_Z); + get_lua_param(behParam, u32, OBJECT_EXT_LUA_BEH_PARAMS); + get_lua_param(behavior, uintptr_t, OBJECT_EXT_LUA_BEHAVIOR); - spawnInfo->startAngle[0] = CMD_GET(s16, 10) * 0x8000 / 180; - spawnInfo->startAngle[1] = CMD_GET(s16, 12) * 0x8000 / 180; - spawnInfo->startAngle[2] = CMD_GET(s16, 14) * 0x8000 / 180; + spawnInfo->startPos[0] = posX; + spawnInfo->startPos[1] = posY; + spawnInfo->startPos[2] = posZ; + spawnInfo->startAngle[0] = (angleX * 0x8000) / 180; + spawnInfo->startAngle[1] = (angleY * 0x8000) / 180; + spawnInfo->startAngle[2] = (angleZ * 0x8000) / 180; spawnInfo->areaIndex = sCurrAreaIndex; spawnInfo->activeAreaIndex = sCurrAreaIndex; - spawnInfo->behaviorArg = CMD_GET(u32, 16); + spawnInfo->behaviorArg = behParam; + + if (luaParams & OBJECT_EXT_LUA_MODEL) { + u16 slot = smlua_model_util_load((enum ModelExtendedId) modelId); + spawnInfo->unk18 = dynos_model_get_geo(slot); + } else { + spawnInfo->unk18 = dynos_model_get_geo(modelId); + } + + if (luaParams & OBJECT_EXT_LUA_BEHAVIOR) { + spawnInfo->behaviorScript = (BehaviorScript *) get_behavior_from_id((enum BehaviorId) behavior); + } else { + spawnInfo->behaviorScript = (BehaviorScript *) behavior; + } - spawnInfo->behaviorScript = (BehaviorScript*)get_behavior_from_id(behId); - u16 slot = smlua_model_util_load(modelId); - spawnInfo->unk18 = dynos_model_get_geo(slot); spawnInfo->next = gAreas[sCurrAreaIndex].objectSpawnInfos; spawnInfo->syncID = spawnInfo->next @@ -1064,6 +1035,21 @@ static void level_cmd_jump_area_ext(void) { } } +static void level_cmd_show_dialog_ext(void) { + if (sCurrAreaIndex != -1 && !gDjuiInMainMenu) { + u8 luaParams = CMD_GET(u8, 2); + + get_lua_param(index, u8, SHOW_DIALOG_EXT_LUA_INDEX); + get_lua_param(dialogId, s32, SHOW_DIALOG_EXT_LUA_DIALOG); + + if (index < 2) { + gAreas[sCurrAreaIndex].dialog[index] = dialogId; + } + } + + sCurrentCmd = CMD_NEXT; +} + static void (*LevelScriptJumpTable[])(void) = { /*00*/ level_cmd_load_and_execute, /*01*/ level_cmd_exit_and_execute, @@ -1130,10 +1116,12 @@ static void (*LevelScriptJumpTable[])(void) = { /*3E*/ level_cmd_cleardemoptr, // coop - /*3F*/ level_cmd_place_object_ext, - /*40*/ level_cmd_place_object_ext2, + /*3F*/ level_cmd_place_object_ext_lua_params, + /*40*/ level_cmd_place_object_ext_lua_params, /*41*/ level_cmd_load_model_from_geo_ext, /*42*/ level_cmd_jump_area_ext, + /*43*/ level_cmd_place_object_ext_lua_params, + /*44*/ level_cmd_show_dialog_ext }; struct LevelCommand *level_script_execute(struct LevelCommand *cmd) { diff --git a/src/game/area.h b/src/game/area.h index 0fe0b45c6..d5340fdee 100644 --- a/src/game/area.h +++ b/src/game/area.h @@ -79,9 +79,9 @@ struct Area /*0x24*/ struct Camera *camera; /*0x28*/ struct UnusedArea28 *unused28; // Filled by level script 0x3A, but is unused. /*0x2C*/ struct Whirlpool *whirlpools[2]; - /*0x34*/ u8 dialog[2]; // Level start dialog number (set by level script cmd 0x30) - /*0x36*/ u16 musicParam; - /*0x38*/ u16 musicParam2; + /*0x34*/ s32 dialog[2]; // Level start dialog number (set by level script cmd 0x30 and 0x44) + /*0x3C*/ u16 musicParam; + /*0x40*/ u16 musicParam2; /*????*/ u32 localAreaTimer; /*????*/ u8 *macroObjectsAltered; /*????*/ u8 numRedCoins; diff --git a/src/pc/lua/smlua_functions.c b/src/pc/lua/smlua_functions.c index 1aba4cb47..9e931fba5 100644 --- a/src/pc/lua/smlua_functions.c +++ b/src/pc/lua/smlua_functions.c @@ -10,6 +10,7 @@ #include "game/mario_actions_stationary.h" #include "audio/external.h" #include "object_fields.h" +#include "level_commands.h" #include "engine/math_util.h" #include "engine/level_script.h" #include "pc/djui/djui_hud_utils.h" @@ -492,6 +493,30 @@ struct LuaLevelScriptParse { struct LuaLevelScriptParse sLevelScriptParse = { 0 }; +static bool smlua_func_level_find_lua_param(u64 *param, void *cmd, u32 offset, u32 luaParams, u32 luaParamFlag) { + *param = dynos_level_cmd_get(cmd, offset); + if (luaParams & luaParamFlag) { + const char *paramStr = dynos_level_get_token(*param); + gSmLuaConvertSuccess = true; + *param = smlua_get_integer_mod_variable(gLevelScriptModIndex, paramStr); + if (!gSmLuaConvertSuccess) { + gSmLuaConvertSuccess = true; + *param = smlua_get_any_integer_mod_variable(paramStr); + } + if (!gSmLuaConvertSuccess) { + return false; + } + } + return true; +} + +#define smlua_func_level_get_lua_param(name, ptype, flag) \ + u64 name##Param; \ + if (!smlua_func_level_find_lua_param(&name##Param, cmd, flag##_OFFSET(type), luaParams, flag)) { \ + break; \ + } \ + ptype name = (ptype) name##Param; + s32 smlua_func_level_script_parse_callback(u8 type, void *cmd) { u32 areaIndex, bhvId, bhvArgs, bhvModelId; s16 bhvPosX, bhvPosY, bhvPosZ; @@ -513,7 +538,7 @@ s32 smlua_func_level_script_parse_callback(u8 type, void *cmd) { const BehaviorScript *bhvPtr = (const BehaviorScript *) dynos_level_cmd_get(cmd, 20); if (bhvPtr) { bhvId = get_id_from_behavior(bhvPtr); - if (bhvId == id_bhv1Up) { + if (bhvId == id_bhv_max_count) { bhvId = get_id_from_vanilla_behavior(bhvPtr); // for behaviors with no id in the script (e.g. bhvInstantActiveWarp) } bhvArgs = dynos_level_cmd_get(cmd, 16); @@ -529,54 +554,46 @@ s32 smlua_func_level_script_parse_callback(u8 type, void *cmd) { } break; // OBJECT_EXT, OBJECT_WITH_ACTS_EXT - case 0x3F: { - if (gLevelScriptModIndex != -1) { - const char *bhvStr = dynos_level_get_token(dynos_level_cmd_get(cmd, 20)); - if (bhvStr) { - gSmLuaConvertSuccess = true; - bhvId = smlua_get_integer_mod_variable(gLevelScriptModIndex, bhvStr); - if (!gSmLuaConvertSuccess) { - gSmLuaConvertSuccess = true; - bhvId = smlua_get_any_integer_mod_variable(bhvStr); - } - if (gSmLuaConvertSuccess) { - bhvArgs = dynos_level_cmd_get(cmd, 16); - bhvModelId = dynos_level_cmd_get(cmd, 3); - bhvPosX = dynos_level_cmd_get(cmd, 4); - bhvPosY = dynos_level_cmd_get(cmd, 6); - bhvPosZ = dynos_level_cmd_get(cmd, 8); - bhvPitch = (dynos_level_cmd_get(cmd, 10) * 0x8000) / 180; - bhvYaw = (dynos_level_cmd_get(cmd, 12) * 0x8000) / 180; - bhvRoll = (dynos_level_cmd_get(cmd, 14) * 0x8000) / 180; - bhv = true; - } - } - } - } break; - // OBJECT_EXT2, OBJECT_WITH_ACTS_EXT2 - case 0x40: { + // OBJECT_EXT_LUA_PARAMS + case 0x3F: + case 0x40: + case 0x43: { if (gLevelScriptModIndex != -1) { - const char *bhvStr = dynos_level_get_token(dynos_level_cmd_get(cmd, 24)); - if (bhvStr) { - gSmLuaConvertSuccess = true; - bhvId = smlua_get_integer_mod_variable(gLevelScriptModIndex, bhvStr); - if (!gSmLuaConvertSuccess) { - gSmLuaConvertSuccess = true; - bhvId = smlua_get_any_integer_mod_variable(bhvStr); - } - if (gSmLuaConvertSuccess) { - bhvArgs = dynos_level_cmd_get(cmd, 16); - bhvModelId = dynos_level_cmd_get(cmd, 3); - bhvPosX = dynos_level_cmd_get(cmd, 4); - bhvPosY = dynos_level_cmd_get(cmd, 6); - bhvPosZ = dynos_level_cmd_get(cmd, 8); - bhvPitch = (dynos_level_cmd_get(cmd, 10) * 0x8000) / 180; - bhvYaw = (dynos_level_cmd_get(cmd, 12) * 0x8000) / 180; - bhvRoll = (dynos_level_cmd_get(cmd, 14) * 0x8000) / 180; - bhv = true; + u16 luaParams = ( + type == 0x3F ? OBJECT_EXT_LUA_BEHAVIOR : ( + type == 0x40 ? OBJECT_EXT_LUA_BEHAVIOR | OBJECT_EXT_LUA_MODEL : ( + dynos_level_cmd_get(cmd, 2) + ))); + + smlua_func_level_get_lua_param(modelId, u32, OBJECT_EXT_LUA_MODEL); + smlua_func_level_get_lua_param(posX, s16, OBJECT_EXT_LUA_POS_X); + smlua_func_level_get_lua_param(posY, s16, OBJECT_EXT_LUA_POS_Y); + smlua_func_level_get_lua_param(posZ, s16, OBJECT_EXT_LUA_POS_Z); + smlua_func_level_get_lua_param(angleX, s16, OBJECT_EXT_LUA_ANGLE_X); + smlua_func_level_get_lua_param(angleY, s16, OBJECT_EXT_LUA_ANGLE_Y); + smlua_func_level_get_lua_param(angleZ, s16, OBJECT_EXT_LUA_ANGLE_Z); + smlua_func_level_get_lua_param(behParam, u32, OBJECT_EXT_LUA_BEH_PARAMS); + smlua_func_level_get_lua_param(behavior, uintptr_t, OBJECT_EXT_LUA_BEHAVIOR); + + bhvArgs = behParam; + bhvModelId = modelId; + bhvPosX = posX; + bhvPosY = posY; + bhvPosZ = posZ; + bhvPitch = angleX; + bhvYaw = angleY; + bhvRoll = angleZ; + if (luaParams & OBJECT_EXT_LUA_BEHAVIOR) { + bhvId = (u32) behavior; + } else { + bhvId = get_id_from_behavior((const BehaviorScript *) behavior); + if (bhvId == id_bhv_max_count) { + bhvId = get_id_from_vanilla_behavior((const BehaviorScript *) behavior); } } + + bhv = true; } } break;