Add lua params support to level macros (allocate dialog pt. 2) (#905)
Some checks are pending
Build coop / build-linux (push) Waiting to run
Build coop / build-steamos (push) Waiting to run
Build coop / build-windows-opengl (push) Waiting to run
Build coop / build-windows-directx (push) Waiting to run
Build coop / build-macos-arm (push) Waiting to run
Build coop / build-macos-intel (push) Waiting to run

* 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>
This commit is contained in:
Beckowl 2025-09-13 15:36:28 -03:00 committed by GitHub
parent 6524e709a3
commit 1c71449ed2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 270 additions and 201 deletions

View file

@ -558,6 +558,8 @@ const struct BehaviorTableEntry gBehaviorTable[id_bhv_max_count] = {
enum BehaviorId get_id_from_behavior(const BehaviorScript* behavior) { enum BehaviorId get_id_from_behavior(const BehaviorScript* behavior) {
if (behavior == NULL) { return id_bhv_max_count; } 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); return (enum BehaviorId)(behavior[1] & 0xFFFF);
} }

View file

@ -641,6 +641,15 @@ static LevelScript ParseLevelScriptSymbolArg(GfxData* aGfxData, DataNode<LevelSc
return; \ return; \
} }
static LevelScript ParseLevelScriptObjectSymbolArgInternal(GfxData* aGfxData, DataNode<LevelScript>* 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<LevelScript>* aNode, LevelScript*& aHead, u64& aTokenIndex, Array<u64>& aSwitchNodes) { static void ParseLevelScriptSymbol(GfxData* aGfxData, DataNode<LevelScript>* aNode, LevelScript*& aHead, u64& aTokenIndex, Array<u64>& aSwitchNodes) {
const String& _Symbol = aNode->mTokens[aTokenIndex++]; const String& _Symbol = aNode->mTokens[aTokenIndex++];
@ -711,7 +720,6 @@ static void ParseLevelScriptSymbol(GfxData* aGfxData, DataNode<LevelScript>* aNo
lvl_symbol_0(CMD2D); lvl_symbol_0(CMD2D);
lvl_symbol_1(TERRAIN, 1); lvl_symbol_1(TERRAIN, 1);
lvl_symbol_1(ROOMS, 1); lvl_symbol_1(ROOMS, 1);
lvl_symbol_2(SHOW_DIALOG, 0, 0);
lvl_symbol_1(TERRAIN_TYPE, 0); lvl_symbol_1(TERRAIN_TYPE, 0);
lvl_symbol_0(NOP); lvl_symbol_0(NOP);
@ -733,75 +741,75 @@ static void ParseLevelScriptSymbol(GfxData* aGfxData, DataNode<LevelScript>* aNo
lvl_symbol_0(ADV_DEMO); lvl_symbol_0(ADV_DEMO);
lvl_symbol_0(CLEAR_DEMO_PTR); lvl_symbol_0(CLEAR_DEMO_PTR);
// object // dialog
if (_Symbol == "OBJECT") { if (_Symbol == "SHOW_DIALOG") {
u64 topTokenIndex = aTokenIndex; 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; if (luaParams != 0) {
bool foundBeh = true; LevelScript finalIndex = (luaParams & SHOW_DIALOG_EXT_LUA_INDEX) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 1, aNode->mTokens[topTokenIndex + 0]) : index;
LevelScript model = ParseLevelScriptSymbolArgInternal(aGfxData, aNode, aTokenIndex, &foundModel); LevelScript finalDialogId = (luaParams & SHOW_DIALOG_EXT_LUA_DIALOG) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 2, aNode->mTokens[topTokenIndex + 1]) : dialogId;
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 (foundModel && foundBeh) { LevelScript _Ls[] = { SHOW_DIALOG_EXT(luaParams, finalIndex, finalDialogId) };
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) };
memcpy(aHead, _Ls, sizeof(_Ls)); memcpy(aHead, _Ls, sizeof(_Ls));
aHead += (sizeof(_Ls) / sizeof(_Ls[0])); aHead += (sizeof(_Ls) / sizeof(_Ls[0]));
} else { } else {
u32 modelIndex = DynOS_Lua_RememberVariable(aGfxData, aHead + 5, aNode->mTokens[topTokenIndex + 0]); LevelScript _Ls[] = { SHOW_DIALOG(index, dialogId) };
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) };
memcpy(aHead, _Ls, sizeof(_Ls)); memcpy(aHead, _Ls, sizeof(_Ls));
aHead += (sizeof(_Ls) / sizeof(_Ls[0])); aHead += (sizeof(_Ls) / sizeof(_Ls[0]));
} }
return; return;
} }
// object with acts // object
if (_Symbol == "OBJECT_WITH_ACTS") { if (_Symbol == "OBJECT" || _Symbol == "OBJECT_WITH_ACTS") {
u64 topTokenIndex = aTokenIndex; u64 topTokenIndex = aTokenIndex;
bool foundModel = true; u32 luaParams = 0;
bool foundBeh = true; LevelScript model = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_MODEL);
LevelScript model = ParseLevelScriptSymbolArgInternal(aGfxData, aNode, aTokenIndex, &foundModel); LevelScript posX = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_POS_X);
LevelScript posX = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); LevelScript posY = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_POS_Y);
LevelScript posY = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); LevelScript posZ = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_POS_Z);
LevelScript posZ = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); LevelScript angleX = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_ANGLE_X);
LevelScript angleX = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); LevelScript angleY = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_ANGLE_Y);
LevelScript angleY = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); LevelScript angleZ = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_ANGLE_Z);
LevelScript angleZ = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); LevelScript behParam = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_BEH_PARAMS);
LevelScript behParam = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); LevelScript beh = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_BEHAVIOR);
LevelScript beh = ParseLevelScriptSymbolArgInternal(aGfxData, aNode, aTokenIndex, &foundBeh); LevelScript acts = (_Symbol == "OBJECT_WITH_ACTS") ? ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_ACTS) : 0x1F;
LevelScript acts = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
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); aGfxData->mPointerList.Add(aHead + 5);
LevelScript _Ls[] = { OBJECT_WITH_ACTS(model, posX, posY, posZ, angleX, angleY, angleZ, behParam, beh, acts) }; LevelScript _Ls[] = { OBJECT_WITH_ACTS(model, posX, posY, posZ, angleX, angleY, angleZ, behParam, beh, acts) };
memcpy(aHead, _Ls, sizeof(_Ls)); memcpy(aHead, _Ls, sizeof(_Ls));
aHead += (sizeof(_Ls) / sizeof(_Ls[0])); 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; return;
} }
@ -1063,12 +1071,12 @@ static DataNode<LevelScript>* DynOS_Lvl_Load(BinFile *aFile, GfxData *aGfxData)
void *_Ptr = DynOS_Pointer_Load(aFile, aGfxData, _Value, FUNCTION_LVL, &_Node->mFlags); void *_Ptr = DynOS_Pointer_Load(aFile, aGfxData, _Value, FUNCTION_LVL, &_Node->mFlags);
if (_Ptr) { 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); PrintError("Didn't expect a pointer while reading level script: %s, %u", _Node->mName.begin(), _Value);
} }
_Node->mData[i] = (uintptr_t) _Ptr; _Node->mData[i] = (uintptr_t) _Ptr;
} else { } else {
if (requirePointer) { if (requirePointer && _Value != LUA_VAR_CODE) {
PrintError("Expected a pointer while reading level script: %s, %u", _Node->mName.begin(), _Value); PrintError("Expected a pointer while reading level script: %s, %u", _Node->mName.begin(), _Value);
_Node->mData[i] = 0; _Node->mData[i] = 0;
} else { } else {

View file

@ -134,6 +134,8 @@ static void LvlCmd_Init() {
ADD_COMMAND(OBJECT_EXT2(POINTER, 0, 0, 0, 0, 0, 0, 0, POINTER)); ADD_COMMAND(OBJECT_EXT2(POINTER, 0, 0, 0, 0, 0, 0, 0, POINTER));
ADD_COMMAND(LOAD_MODEL_FROM_GEO_EXT(0, POINTER)); ADD_COMMAND(LOAD_MODEL_FROM_GEO_EXT(0, POINTER));
ADD_COMMAND(JUMP_AREA_EXT(0, 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() { void DynOS_Lvl_Validate_Begin() {

View file

@ -30,6 +30,34 @@
#define WHIRLPOOL_COND_BOWSER2_BEATEN 2 #define WHIRLPOOL_COND_BOWSER2_BEATEN 2
#define WHIRLPOOL_COND_AT_LEAST_SECOND_STAR 3 #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 // Head defines
#define REGULAR_FACE 0x0002 #define REGULAR_FACE 0x0002
#define DIZZY_FACE 0x0003 #define DIZZY_FACE 0x0003
@ -324,6 +352,30 @@
CMD_W(arg), \ CMD_W(arg), \
CMD_PTR(target) 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 // // README //
// README // // README //

View file

@ -18,6 +18,7 @@
#include "goddard/renderer.h" #include "goddard/renderer.h"
#include "geo_layout.h" #include "geo_layout.h"
#include "graph_node.h" #include "graph_node.h"
#include "level_commands.h"
#include "level_script.h" #include "level_script.h"
#include "level_misc_macros.h" #include "level_misc_macros.h"
#include "macro_presets.h" #include "macro_presets.h"
@ -918,124 +919,94 @@ static void level_cmd_cleardemoptr(void)
sCurrentCmd = CMD_NEXT; sCurrentCmd = CMD_NEXT;
} }
//
// coop // coop
static void level_cmd_place_object_ext(void) { //
u8 val7 = 1 << (gCurrActNum - 1);
struct SpawnInfo *spawnInfo;
u16 modIndex = gLevelScriptModIndex; static bool find_lua_param(uintptr_t *param, u32 offset, u32 luaParams, u32 luaParamFlag, const char *paramType) {
const char* behStr = dynos_level_get_token(CMD_GET(u32, 20)); *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) { const char *paramStr = dynos_level_get_token(*param);
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) {
gSmLuaConvertSuccess = true; 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;
}
} }
return true;
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;
} }
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); u8 val7 = 1 << (gCurrActNum - 1);
struct SpawnInfo *spawnInfo; struct SpawnInfo *spawnInfo;
u16 modIndex = gLevelScriptModIndex; u8 cmdType = sCurrentCmd->type;
const char* modelStr = dynos_level_get_token(CMD_GET(u32, 20)); u16 luaParams = (
const char* behStr = dynos_level_get_token(CMD_GET(u32, 24)); cmdType == 0x3F ? OBJECT_EXT_LUA_BEHAVIOR : (
cmdType == 0x40 ? OBJECT_EXT_LUA_BEHAVIOR | OBJECT_EXT_LUA_MODEL : (
CMD_GET(u16, 2)
)));
if (gLevelScriptModIndex == -1) { get_lua_param(acts, u8, OBJECT_EXT_LUA_ACTS);
LOG_ERROR("Could not find level script mod index");
sCurrentCmd = CMD_NEXT;
return;
}
gSmLuaConvertSuccess = true; if (sCurrAreaIndex != -1 && (gLevelValues.disableActs || (acts & val7) || acts == 0x1F)) {
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)) {
spawnInfo = dynamic_pool_alloc(gLevelPool, sizeof(struct SpawnInfo)); spawnInfo = dynamic_pool_alloc(gLevelPool, sizeof(struct SpawnInfo));
spawnInfo->startPos[0] = CMD_GET(s16, 4); get_lua_param(modelId, u32, OBJECT_EXT_LUA_MODEL);
spawnInfo->startPos[1] = CMD_GET(s16, 6); get_lua_param(posX, s16, OBJECT_EXT_LUA_POS_X);
spawnInfo->startPos[2] = CMD_GET(s16, 8); 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->startPos[0] = posX;
spawnInfo->startAngle[1] = CMD_GET(s16, 12) * 0x8000 / 180; spawnInfo->startPos[1] = posY;
spawnInfo->startAngle[2] = CMD_GET(s16, 14) * 0x8000 / 180; 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->areaIndex = sCurrAreaIndex;
spawnInfo->activeAreaIndex = 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->next = gAreas[sCurrAreaIndex].objectSpawnInfos;
spawnInfo->syncID = spawnInfo->next 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) = { static void (*LevelScriptJumpTable[])(void) = {
/*00*/ level_cmd_load_and_execute, /*00*/ level_cmd_load_and_execute,
/*01*/ level_cmd_exit_and_execute, /*01*/ level_cmd_exit_and_execute,
@ -1130,10 +1116,12 @@ static void (*LevelScriptJumpTable[])(void) = {
/*3E*/ level_cmd_cleardemoptr, /*3E*/ level_cmd_cleardemoptr,
// coop // coop
/*3F*/ level_cmd_place_object_ext, /*3F*/ level_cmd_place_object_ext_lua_params,
/*40*/ level_cmd_place_object_ext2, /*40*/ level_cmd_place_object_ext_lua_params,
/*41*/ level_cmd_load_model_from_geo_ext, /*41*/ level_cmd_load_model_from_geo_ext,
/*42*/ level_cmd_jump_area_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) { struct LevelCommand *level_script_execute(struct LevelCommand *cmd) {

View file

@ -79,9 +79,9 @@ struct Area
/*0x24*/ struct Camera *camera; /*0x24*/ struct Camera *camera;
/*0x28*/ struct UnusedArea28 *unused28; // Filled by level script 0x3A, but is unused. /*0x28*/ struct UnusedArea28 *unused28; // Filled by level script 0x3A, but is unused.
/*0x2C*/ struct Whirlpool *whirlpools[2]; /*0x2C*/ struct Whirlpool *whirlpools[2];
/*0x34*/ u8 dialog[2]; // Level start dialog number (set by level script cmd 0x30) /*0x34*/ s32 dialog[2]; // Level start dialog number (set by level script cmd 0x30 and 0x44)
/*0x36*/ u16 musicParam; /*0x3C*/ u16 musicParam;
/*0x38*/ u16 musicParam2; /*0x40*/ u16 musicParam2;
/*????*/ u32 localAreaTimer; /*????*/ u32 localAreaTimer;
/*????*/ u8 *macroObjectsAltered; /*????*/ u8 *macroObjectsAltered;
/*????*/ u8 numRedCoins; /*????*/ u8 numRedCoins;

View file

@ -10,6 +10,7 @@
#include "game/mario_actions_stationary.h" #include "game/mario_actions_stationary.h"
#include "audio/external.h" #include "audio/external.h"
#include "object_fields.h" #include "object_fields.h"
#include "level_commands.h"
#include "engine/math_util.h" #include "engine/math_util.h"
#include "engine/level_script.h" #include "engine/level_script.h"
#include "pc/djui/djui_hud_utils.h" #include "pc/djui/djui_hud_utils.h"
@ -492,6 +493,30 @@ struct LuaLevelScriptParse {
struct LuaLevelScriptParse sLevelScriptParse = { 0 }; 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) { s32 smlua_func_level_script_parse_callback(u8 type, void *cmd) {
u32 areaIndex, bhvId, bhvArgs, bhvModelId; u32 areaIndex, bhvId, bhvArgs, bhvModelId;
s16 bhvPosX, bhvPosY, bhvPosZ; 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); const BehaviorScript *bhvPtr = (const BehaviorScript *) dynos_level_cmd_get(cmd, 20);
if (bhvPtr) { if (bhvPtr) {
bhvId = get_id_from_behavior(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) 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); bhvArgs = dynos_level_cmd_get(cmd, 16);
@ -529,54 +554,46 @@ s32 smlua_func_level_script_parse_callback(u8 type, void *cmd) {
} break; } break;
// OBJECT_EXT, OBJECT_WITH_ACTS_EXT // 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 // OBJECT_EXT2, OBJECT_WITH_ACTS_EXT2
case 0x40: { // OBJECT_EXT_LUA_PARAMS
case 0x3F:
case 0x40:
case 0x43: {
if (gLevelScriptModIndex != -1) { if (gLevelScriptModIndex != -1) {
const char *bhvStr = dynos_level_get_token(dynos_level_cmd_get(cmd, 24)); u16 luaParams = (
if (bhvStr) { type == 0x3F ? OBJECT_EXT_LUA_BEHAVIOR : (
gSmLuaConvertSuccess = true; type == 0x40 ? OBJECT_EXT_LUA_BEHAVIOR | OBJECT_EXT_LUA_MODEL : (
bhvId = smlua_get_integer_mod_variable(gLevelScriptModIndex, bhvStr); dynos_level_cmd_get(cmd, 2)
if (!gSmLuaConvertSuccess) { )));
gSmLuaConvertSuccess = true;
bhvId = smlua_get_any_integer_mod_variable(bhvStr); 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);
if (gSmLuaConvertSuccess) { smlua_func_level_get_lua_param(posY, s16, OBJECT_EXT_LUA_POS_Y);
bhvArgs = dynos_level_cmd_get(cmd, 16); smlua_func_level_get_lua_param(posZ, s16, OBJECT_EXT_LUA_POS_Z);
bhvModelId = dynos_level_cmd_get(cmd, 3); smlua_func_level_get_lua_param(angleX, s16, OBJECT_EXT_LUA_ANGLE_X);
bhvPosX = dynos_level_cmd_get(cmd, 4); smlua_func_level_get_lua_param(angleY, s16, OBJECT_EXT_LUA_ANGLE_Y);
bhvPosY = dynos_level_cmd_get(cmd, 6); smlua_func_level_get_lua_param(angleZ, s16, OBJECT_EXT_LUA_ANGLE_Z);
bhvPosZ = dynos_level_cmd_get(cmd, 8); smlua_func_level_get_lua_param(behParam, u32, OBJECT_EXT_LUA_BEH_PARAMS);
bhvPitch = (dynos_level_cmd_get(cmd, 10) * 0x8000) / 180; smlua_func_level_get_lua_param(behavior, uintptr_t, OBJECT_EXT_LUA_BEHAVIOR);
bhvYaw = (dynos_level_cmd_get(cmd, 12) * 0x8000) / 180;
bhvRoll = (dynos_level_cmd_get(cmd, 14) * 0x8000) / 180; bhvArgs = behParam;
bhv = true; 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; } break;