diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua
index 75cec01a3..4d19ac5e1 100644
--- a/autogen/lua_definitions/functions.lua
+++ b/autogen/lua_definitions/functions.lua
@@ -7594,6 +7594,15 @@ function warp_to_start_level()
-- ...
end
+--- @param aLevel integer
+--- @param aArea integer
+--- @param aAct integer
+--- @param aWarpId integer
+--- @return boolean
+function warp_to_warpnode(aLevel, aArea, aAct, aWarpId)
+ -- ...
+end
+
--- @param index integer
--- @param name string
--- @param offset integer
diff --git a/data/dynos.cpp.h b/data/dynos.cpp.h
index b165e70ba..0b55f3607 100644
--- a/data/dynos.cpp.h
+++ b/data/dynos.cpp.h
@@ -828,6 +828,7 @@ s16 *DynOS_Level_GetWarpDeath(s32 aLevel, s32 aArea);
//
void *DynOS_Warp_Update(void *aCmd, bool aIsLevelInitDone);
+bool DynOS_Warp_ToWarpNode(s32 aLevel, s32 aArea, s32 aAct, s32 aWarpId);
bool DynOS_Warp_ToLevel(s32 aLevel, s32 aArea, s32 aAct);
bool DynOS_Warp_RestartLevel();
bool DynOS_Warp_ExitLevel(s32 aDelay);
diff --git a/data/dynos_c.cpp b/data/dynos_c.cpp
index 25eedf6ad..bfdb2ff5e 100644
--- a/data/dynos_c.cpp
+++ b/data/dynos_c.cpp
@@ -35,6 +35,10 @@ LevelScript* dynos_get_level_script(char* scriptEntryName) {
return DynOS_Lvl_GetScript(scriptEntryName);
}
+bool dynos_warp_to_warpnode(s32 aLevel, s32 aArea, s32 aAct, s32 aWarpId) {
+ return DynOS_Warp_ToWarpNode(aLevel, aArea, aAct, aWarpId);
+}
+
bool dynos_warp_to_level(s32 aLevel, s32 aArea, s32 aAct) {
return DynOS_Warp_ToLevel(aLevel, aArea, aAct);
}
diff --git a/data/dynos_warps.cpp b/data/dynos_warps.cpp
index f6d7cb861..046299478 100644
--- a/data/dynos_warps.cpp
+++ b/data/dynos_warps.cpp
@@ -30,9 +30,31 @@ extern void set_play_mode(s16);
static s32 sDynosWarpLevelNum = -1;
static s32 sDynosWarpAreaNum = -1;
static s32 sDynosWarpActNum = -1;
+static s32 sDynosWarpNodeNum = -1;
static s32 sDynosExitLevelNum = -1;
static s32 sDynosExitAreaNum = -1;
+//
+// Specific Warp Node
+//
+
+bool DynOS_Warp_ToWarpNode(s32 aLevel, s32 aArea, s32 aAct, s32 aWarpId) {
+ if (!DynOS_Level_GetWarp(aLevel, aArea, aWarpId)) {
+ return false;
+ }
+
+ if (aLevel != gCurrLevelNum) {
+ // stop music
+ play_music(SEQ_PLAYER_LEVEL, 0, 0);
+ }
+
+ sDynosWarpLevelNum = aLevel;
+ sDynosWarpAreaNum = aArea;
+ sDynosWarpActNum = aAct;
+ sDynosWarpNodeNum = aWarpId;
+ return true;
+}
+
//
// Level Entry
//
@@ -266,14 +288,21 @@ static void *DynOS_Warp_UpdateWarp(void *aCmd, bool aIsLevelInitDone) {
// Phase 3 - End level initialization
if (aIsLevelInitDone) {
+ // Get Warp
+ s16 *_Warp;
+ if (sDynosWarpNodeNum == -1) {
+ _Warp = DynOS_Level_GetWarpEntry(gCurrLevelNum, gCurrAreaIndex);
+ } else {
+ _Warp = DynOS_Level_GetWarp(gCurrLevelNum, gCurrAreaIndex, sDynosWarpNodeNum);
+ }
+ s16 sDynosWarpSpawnType = sSpawnTypeFromWarpBhv[_Warp[2]];
+
// Init Mario
- s16 *_LevelEntryWarp = DynOS_Level_GetWarpEntry(gCurrLevelNum, gCurrAreaIndex);
- s16 sDynosWarpSpawnType = sSpawnTypeFromWarpBhv[_LevelEntryWarp[2]];
- gMarioSpawnInfo->startPos[0] = _LevelEntryWarp[3] + (sDynosWarpSpawnType == MARIO_SPAWN_DOOR_WARP) * 300.0f * sins(_LevelEntryWarp[6]);
- gMarioSpawnInfo->startPos[1] = _LevelEntryWarp[4];
- gMarioSpawnInfo->startPos[2] = _LevelEntryWarp[5] + (sDynosWarpSpawnType == MARIO_SPAWN_DOOR_WARP) * 300.0f * coss(_LevelEntryWarp[6]);
+ gMarioSpawnInfo->startPos[0] = _Warp[3] + (sDynosWarpSpawnType == MARIO_SPAWN_DOOR_WARP) * 300.0f * sins(_Warp[6]);
+ gMarioSpawnInfo->startPos[1] = _Warp[4];
+ gMarioSpawnInfo->startPos[2] = _Warp[5] + (sDynosWarpSpawnType == MARIO_SPAWN_DOOR_WARP) * 300.0f * coss(_Warp[6]);
gMarioSpawnInfo->startAngle[0] = 0;
- gMarioSpawnInfo->startAngle[1] = _LevelEntryWarp[6];
+ gMarioSpawnInfo->startAngle[1] = _Warp[6];
gMarioSpawnInfo->startAngle[2] = 0;
gMarioSpawnInfo->areaIndex = gCurrAreaIndex;
init_mario();
@@ -297,14 +326,16 @@ static void *DynOS_Warp_UpdateWarp(void *aCmd, bool aIsLevelInitDone) {
}
// Set music
- set_background_music(gCurrentArea->musicParam, gCurrentArea->musicParam2, 0);
- if (gMarioState->flags & MARIO_METAL_CAP) play_cap_music(SEQUENCE_ARGS(4, SEQ_EVENT_METAL_CAP));
- if (gMarioState->flags & MARIO_VANISH_CAP) play_cap_music(SEQUENCE_ARGS(4, SEQ_EVENT_POWERUP));
- if (gMarioState->flags & MARIO_WING_CAP) play_cap_music(SEQUENCE_ARGS(4, SEQ_EVENT_POWERUP));
- if (gCurrLevelNum == LEVEL_BOWSER_1 ||
- gCurrLevelNum == LEVEL_BOWSER_2 ||
- gCurrLevelNum == LEVEL_BOWSER_3) {
- sound_banks_enable(0, 0xFFFF); // Bowser levels sound fix
+ if (sWarpDest.type != WARP_TYPE_SAME_AREA && sWarpDest.type != WARP_TYPE_NOT_WARPING) {
+ set_background_music(gCurrentArea->musicParam, gCurrentArea->musicParam2, 0);
+ if (gMarioState->flags & MARIO_METAL_CAP) play_cap_music(SEQUENCE_ARGS(4, SEQ_EVENT_METAL_CAP));
+ if (gMarioState->flags & MARIO_VANISH_CAP) play_cap_music(SEQUENCE_ARGS(4, SEQ_EVENT_POWERUP));
+ if (gMarioState->flags & MARIO_WING_CAP) play_cap_music(SEQUENCE_ARGS(4, SEQ_EVENT_POWERUP));
+ if (gCurrLevelNum == LEVEL_BOWSER_1 ||
+ gCurrLevelNum == LEVEL_BOWSER_2 ||
+ gCurrLevelNum == LEVEL_BOWSER_3) {
+ sound_banks_enable(0, 0xFFFF); // Bowser levels sound fix
+ }
}
// lua hooks
@@ -315,6 +346,7 @@ static void *DynOS_Warp_UpdateWarp(void *aCmd, bool aIsLevelInitDone) {
sDynosWarpLevelNum = -1;
sDynosWarpAreaNum = -1;
sDynosWarpActNum = -1;
+ sDynosWarpNodeNum = -1;
}
}
@@ -446,7 +478,7 @@ static void *DynOS_Warp_UpdateExit(void *aCmd, bool aIsLevelInitDone) {
// Set music
set_background_music(gCurrentArea->musicParam, gCurrentArea->musicParam2, 0);
sDynosExitTargetWarp = NULL;
-
+
// lua hooks
smlua_call_event_hooks(HOOK_ON_WARP);
}
diff --git a/docs/lua/functions-4.md b/docs/lua/functions-4.md
index 7d1593348..5e62a467b 100644
--- a/docs/lua/functions-4.md
+++ b/docs/lua/functions-4.md
@@ -6304,6 +6304,29 @@
+## [warp_to_warpnode](#warp_to_warpnode)
+
+### Lua Example
+`local booleanValue = warp_to_warpnode(aLevel, aArea, aAct, aWarpId)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| aLevel | `integer` |
+| aArea | `integer` |
+| aAct | `integer` |
+| aWarpId | `integer` |
+
+### Returns
+- `boolean`
+
+### C Prototype
+`bool warp_to_warpnode(s32 aLevel, s32 aArea, s32 aAct, s32 aWarpId);`
+
+[:arrow_up_small:](#)
+
+
+
---
# functions from smlua_misc_utils.h
diff --git a/docs/lua/functions.md b/docs/lua/functions.md
index 8ab4e6b5e..758ad9a1f 100644
--- a/docs/lua/functions.md
+++ b/docs/lua/functions.md
@@ -1423,6 +1423,7 @@
- [warp_to_castle](functions-4.md#warp_to_castle)
- [warp_to_level](functions-4.md#warp_to_level)
- [warp_to_start_level](functions-4.md#warp_to_start_level)
+ - [warp_to_warpnode](functions-4.md#warp_to_warpnode)
diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c
index 5f3c91131..350296005 100644
--- a/src/pc/lua/smlua_functions_autogen.c
+++ b/src/pc/lua/smlua_functions_autogen.c
@@ -16789,6 +16789,23 @@ int smlua_func_warp_to_start_level(UNUSED lua_State* L) {
return 1;
}
+int smlua_func_warp_to_warpnode(lua_State* L) {
+ if(!smlua_functions_valid_param_count(L, 4)) { return 0; }
+
+ s32 aLevel = smlua_to_integer(L, 1);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1 for function 'warp_to_warpnode'"); return 0; }
+ s32 aArea = smlua_to_integer(L, 2);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 2 for function 'warp_to_warpnode'"); return 0; }
+ s32 aAct = smlua_to_integer(L, 3);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 3 for function 'warp_to_warpnode'"); return 0; }
+ s32 aWarpId = smlua_to_integer(L, 4);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 4 for function 'warp_to_warpnode'"); return 0; }
+
+ lua_pushboolean(L, warp_to_warpnode(aLevel, aArea, aAct, aWarpId));
+
+ return 1;
+}
+
////////////////////////
// smlua_misc_utils.h //
////////////////////////
@@ -19643,6 +19660,7 @@ void smlua_bind_functions_autogen(void) {
smlua_bind_function(L, "warp_to_castle", smlua_func_warp_to_castle);
smlua_bind_function(L, "warp_to_level", smlua_func_warp_to_level);
smlua_bind_function(L, "warp_to_start_level", smlua_func_warp_to_start_level);
+ smlua_bind_function(L, "warp_to_warpnode", smlua_func_warp_to_warpnode);
// smlua_misc_utils.h
smlua_bind_function(L, "add_scroll_target", smlua_func_add_scroll_target);
diff --git a/src/pc/lua/utils/smlua_level_utils.c b/src/pc/lua/utils/smlua_level_utils.c
index dae54ea87..7500d5b40 100644
--- a/src/pc/lua/utils/smlua_level_utils.c
+++ b/src/pc/lua/utils/smlua_level_utils.c
@@ -126,6 +126,10 @@ s16 level_register(const char* scriptEntryName, s16 courseNum, const char* fullN
return 0;
}
+bool warp_to_warpnode(s32 aLevel, s32 aArea, s32 aAct, s32 aWarpId) {
+ return dynos_warp_to_warpnode(aLevel, aArea, aAct, aWarpId);
+}
+
bool warp_to_level(s32 aLevel, s32 aArea, s32 aAct) {
return dynos_warp_to_level(aLevel, aArea, aAct);
}
@@ -144,4 +148,4 @@ bool warp_exit_level(s32 aDelay) {
bool warp_to_castle(s32 aLevel) {
return dynos_warp_to_castle(aLevel);
-}
\ No newline at end of file
+}
diff --git a/src/pc/lua/utils/smlua_level_utils.h b/src/pc/lua/utils/smlua_level_utils.h
index 473e2043a..107c80601 100644
--- a/src/pc/lua/utils/smlua_level_utils.h
+++ b/src/pc/lua/utils/smlua_level_utils.h
@@ -21,6 +21,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 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);
bool warp_to_start_level(void);