diff --git a/autogen/lua_definitions/structs.lua b/autogen/lua_definitions/structs.lua index 2a0d1759d..900cc3527 100644 --- a/autogen/lua_definitions/structs.lua +++ b/autogen/lua_definitions/structs.lua @@ -574,12 +574,21 @@ --- @field public yaw integer --- @class LevelValues +--- @field public coinsRequiredForCoinStar integer --- @field public entryLevel LevelNum --- @field public exitCastleArea integer --- @field public exitCastleLevel LevelNum --- @field public exitCastleWarpNode integer +--- @field public metalCapDuration integer +--- @field public metalCapDurationCotmc integer +--- @field public pssSlideStarIndex integer +--- @field public pssSlideStarTime integer --- @field public skipCreditsAt LevelNum --- @field public starPositions StarPositions +--- @field public vanishCapDuration integer +--- @field public vanishCapDurationVcutm integer +--- @field public wingCapDuration integer +--- @field public wingCapDurationTotwc integer --- @class LinearTransitionPoint --- @field public dist number diff --git a/data/dynos_mgr_builtin.cpp b/data/dynos_mgr_builtin.cpp index d1b89871a..1b478b027 100644 --- a/data/dynos_mgr_builtin.cpp +++ b/data/dynos_mgr_builtin.cpp @@ -1079,9 +1079,13 @@ static void *geo_rotate_3d_coin(s32 callContext, void *node, UNUSED void *c) { struct Object *obj = (struct Object *) gCurGraphNodeObject; struct GraphNodeRotation *rotNode = (struct GraphNodeRotation *) ((struct GraphNode *) node)->next; rotNode->rotation[0] = 0; - rotNode->rotation[1] = obj->oAnimState; + rotNode->rotation[1] = obj->oAnimState * 0x0800; rotNode->rotation[2] = 0; - obj->oAnimState += 0x0800; + obj->oFaceAnglePitch = 0; + obj->oMoveAnglePitch = 0; + obj->oFaceAngleRoll = 0; + obj->oMoveAngleRoll = 0; + obj->header.gfx.node.flags &= ~(GRAPH_RENDER_BILLBOARD | GRAPH_RENDER_CYLBOARD); } return NULL; } diff --git a/docs/lua/structs.md b/docs/lua/structs.md index a12ea74ec..d86c52098 100644 --- a/docs/lua/structs.md +++ b/docs/lua/structs.md @@ -837,12 +837,21 @@ | Field | Type | Access | | ----- | ---- | ------ | +| coinsRequiredForCoinStar | `integer` | | | entryLevel | [enum LevelNum](constants.md#enum-LevelNum) | | | exitCastleArea | `integer` | | | exitCastleLevel | [enum LevelNum](constants.md#enum-LevelNum) | | | exitCastleWarpNode | `integer` | | +| metalCapDuration | `integer` | | +| metalCapDurationCotmc | `integer` | | +| pssSlideStarIndex | `integer` | | +| pssSlideStarTime | `integer` | | | skipCreditsAt | [enum LevelNum](constants.md#enum-LevelNum) | | | starPositions | [StarPositions](structs.md#StarPositions) | read-only | +| vanishCapDuration | `integer` | | +| vanishCapDurationVcutm | `integer` | | +| wingCapDuration | `integer` | | +| wingCapDurationTotwc | `integer` | | [:arrow_up_small:](#) diff --git a/src/audio/external.c b/src/audio/external.c index c79e7ee0c..6966ea374 100644 --- a/src/audio/external.c +++ b/src/audio/external.c @@ -2435,6 +2435,23 @@ void stop_background_music(u16 seqId) { // queue slot). foundIndex = sBackgroundMusicQueueSize; + // BUG: If the boss sequence is missing, the level music is not going to restart... + // So, add the boss music in the queue to force the stop_background_music + // function to remove it from the queue and restart the level music. + if ((seqId & 0xFF) == SEQ_EVENT_BOSS) { + for (i = 0; i <= sBackgroundMusicQueueSize; ++i) { + if (i == sBackgroundMusicQueueSize) { + sBackgroundMusicQueueSize = MIN(sBackgroundMusicQueueSize + 1, MAX_BACKGROUND_MUSIC_QUEUE_SIZE); + memmove(sBackgroundMusicQueue + 1, sBackgroundMusicQueue, sizeof(sBackgroundMusicQueue[0]) * (MAX_BACKGROUND_MUSIC_QUEUE_SIZE - 1)); + sBackgroundMusicQueue[0].seqId = SEQ_EVENT_BOSS; + sBackgroundMusicQueue[0].priority = 4; + break; + } else if (sBackgroundMusicQueue[i].seqId == SEQ_EVENT_BOSS) { + break; + } + } + } + // Search for the sequence. for (i = 0; i < sBackgroundMusicQueueSize; i++) { if (sBackgroundMusicQueue[i].seqId == (u8)(seqId & 0xff)) { diff --git a/src/game/hardcoded.c b/src/game/hardcoded.c index 7e24c7f43..1e74a242d 100644 --- a/src/game/hardcoded.c +++ b/src/game/hardcoded.c @@ -43,6 +43,15 @@ struct LevelValues gLevelValues = { .exitCastleArea = 1, .exitCastleWarpNode = 0x1F, .skipCreditsAt = (LEVEL_MAX+1), + .pssSlideStarTime = 630, + .pssSlideStarIndex = 1, + .coinsRequiredForCoinStar = 100, + .wingCapDuration = 1800, + .metalCapDuration = 600, + .vanishCapDuration = 600, + .wingCapDurationTotwc = 1200, + .metalCapDurationCotmc = 600, + .vanishCapDurationVcutm = 600, .starPositions = { .KoopaBobStarPos = { 3030.0f, 4500.0f, -4600.0f }, .KoopaThiStarPos = { 7100.0f, -1300.0f, -6000.0f }, diff --git a/src/game/hardcoded.h b/src/game/hardcoded.h index 1ebf69a75..cca523b6b 100644 --- a/src/game/hardcoded.h +++ b/src/game/hardcoded.h @@ -42,6 +42,15 @@ struct LevelValues { s16 exitCastleArea; u8 exitCastleWarpNode; enum LevelNum skipCreditsAt; + u16 pssSlideStarTime; + u8 pssSlideStarIndex; + s16 coinsRequiredForCoinStar; + u16 wingCapDuration; + u16 metalCapDuration; + u16 vanishCapDuration; + u16 wingCapDurationTotwc; + u16 metalCapDurationCotmc; + u16 vanishCapDurationVcutm; struct StarPositions starPositions; }; diff --git a/src/game/interaction.c b/src/game/interaction.c index b82e2c1ed..a8afe1753 100644 --- a/src/game/interaction.c +++ b/src/game/interaction.c @@ -853,8 +853,8 @@ u32 interact_coin(struct MarioState *m, UNUSED u32 interactType, struct Object * o->oInteractStatus = INT_STATUS_INTERACTED; - if (COURSE_IS_MAIN_COURSE(gCurrCourseNum) && m->numCoins - o->oDamageOrCoinValue < 100 - && m->numCoins >= 100) { + if (COURSE_IS_MAIN_COURSE(gCurrCourseNum) && m->numCoins - o->oDamageOrCoinValue < gLevelValues.coinsRequiredForCoinStar + && m->numCoins >= gLevelValues.coinsRequiredForCoinStar) { bhv_spawn_star_no_level_exit(m->marioObj, 6, FALSE); } @@ -1969,17 +1969,17 @@ u32 interact_cap(struct MarioState *m, UNUSED u32 interactType, struct Object *o switch (capFlag) { case MARIO_VANISH_CAP: - capTime = 600; + capTime = gLevelValues.vanishCapDuration; capMusic = SEQUENCE_ARGS(4, SEQ_EVENT_POWERUP); break; case MARIO_METAL_CAP: - capTime = 600; + capTime = gLevelValues.metalCapDuration; capMusic = SEQUENCE_ARGS(4, SEQ_EVENT_METAL_CAP); break; case MARIO_WING_CAP: - capTime = 1800; + capTime = gLevelValues.wingCapDuration; capMusic = SEQUENCE_ARGS(4, SEQ_EVENT_POWERUP); break; } @@ -2266,10 +2266,10 @@ void pss_end_slide(struct MarioState *m) { //! This flag isn't set on death or level entry, allowing double star spawn if (gPssSlideStarted) { u16 slideTime = level_control_timer(TIMER_CONTROL_STOP); - if (slideTime < 630) { + if (slideTime < gLevelValues.pssSlideStarTime) { // PSS secret star uses oBehParams to spawn s32 tmp = m->marioObj->oBehParams; - m->marioObj->oBehParams = (1 << 24); + m->marioObj->oBehParams = (gLevelValues.pssSlideStarIndex << 24); f32* starPos = gLevelValues.starPositions.PssSlideStarPos; spawn_default_star(starPos[0], starPos[1], starPos[2]); m->marioObj->oBehParams = tmp; diff --git a/src/game/level_info.c b/src/game/level_info.c index a906a043d..8494d8d47 100644 --- a/src/game/level_info.c +++ b/src/game/level_info.c @@ -2,6 +2,7 @@ #include #include #include "course_table.h" +#include "game/hardcoded.h" #include "game/memory.h" #include "level_info.h" #include "level_table.h" @@ -240,7 +241,7 @@ const char *get_star_name_ascii(s16 courseNum, s16 starNum, s16 charCase) { const u8 *starName = segmented_to_virtual(actNameTable[(courseNum - COURSE_BOB) * 6 + (starNum - 1)]); convert_string_sm64_to_ascii(output, starName); } else if (starNum == 7) { - snprintf(output, 256, "100 Coins Star"); + snprintf(output, 256, "%d Coins Star", (s32) gLevelValues.coinsRequiredForCoinStar); } else { snprintf(output, 256, "A Secret Star!"); } diff --git a/src/game/level_update.c b/src/game/level_update.c index 4b8865c22..50608d49c 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -314,17 +314,17 @@ void set_mario_initial_cap_powerup(struct MarioState *m) { switch (capCourseIndex) { case COURSE_COTMC - COURSE_CAP_COURSES: m->flags |= MARIO_METAL_CAP | MARIO_CAP_ON_HEAD; - m->capTimer = 600; + m->capTimer = gLevelValues.metalCapDurationCotmc; break; case COURSE_TOTWC - COURSE_CAP_COURSES: m->flags |= MARIO_WING_CAP | MARIO_CAP_ON_HEAD; - m->capTimer = 1200; + m->capTimer = gLevelValues.wingCapDurationTotwc; break; case COURSE_VCUTM - COURSE_CAP_COURSES: m->flags |= MARIO_VANISH_CAP | MARIO_CAP_ON_HEAD; - m->capTimer = 600; + m->capTimer = gLevelValues.vanishCapDurationVcutm; break; } } diff --git a/src/pc/lua/smlua_cobject_autogen.c b/src/pc/lua/smlua_cobject_autogen.c index c41157b52..655878d8b 100644 --- a/src/pc/lua/smlua_cobject_autogen.c +++ b/src/pc/lua/smlua_cobject_autogen.c @@ -670,14 +670,23 @@ static struct LuaObjectField sLakituStateFields[LUA_LAKITU_STATE_FIELD_COUNT] = { "yaw", LVT_S16, offsetof(struct LakituState, yaw), false, LOT_NONE }, }; -#define LUA_LEVEL_VALUES_FIELD_COUNT 6 +#define LUA_LEVEL_VALUES_FIELD_COUNT 15 static struct LuaObjectField sLevelValuesFields[LUA_LEVEL_VALUES_FIELD_COUNT] = { - { "entryLevel", LVT_S32, offsetof(struct LevelValues, entryLevel), false, LOT_NONE }, - { "exitCastleArea", LVT_S16, offsetof(struct LevelValues, exitCastleArea), false, LOT_NONE }, - { "exitCastleLevel", LVT_S32, offsetof(struct LevelValues, exitCastleLevel), false, LOT_NONE }, - { "exitCastleWarpNode", LVT_U8, offsetof(struct LevelValues, exitCastleWarpNode), false, LOT_NONE }, - { "skipCreditsAt", LVT_S32, offsetof(struct LevelValues, skipCreditsAt), false, LOT_NONE }, - { "starPositions", LVT_COBJECT, offsetof(struct LevelValues, starPositions), true, LOT_STARPOSITIONS }, + { "coinsRequiredForCoinStar", LVT_S16, offsetof(struct LevelValues, coinsRequiredForCoinStar), false, LOT_NONE }, + { "entryLevel", LVT_S32, offsetof(struct LevelValues, entryLevel), false, LOT_NONE }, + { "exitCastleArea", LVT_S16, offsetof(struct LevelValues, exitCastleArea), false, LOT_NONE }, + { "exitCastleLevel", LVT_S32, offsetof(struct LevelValues, exitCastleLevel), false, LOT_NONE }, + { "exitCastleWarpNode", LVT_U8, offsetof(struct LevelValues, exitCastleWarpNode), false, LOT_NONE }, + { "metalCapDuration", LVT_U16, offsetof(struct LevelValues, metalCapDuration), false, LOT_NONE }, + { "metalCapDurationCotmc", LVT_U16, offsetof(struct LevelValues, metalCapDurationCotmc), false, LOT_NONE }, + { "pssSlideStarIndex", LVT_U8, offsetof(struct LevelValues, pssSlideStarIndex), false, LOT_NONE }, + { "pssSlideStarTime", LVT_U16, offsetof(struct LevelValues, pssSlideStarTime), false, LOT_NONE }, + { "skipCreditsAt", LVT_S32, offsetof(struct LevelValues, skipCreditsAt), false, LOT_NONE }, + { "starPositions", LVT_COBJECT, offsetof(struct LevelValues, starPositions), true, LOT_STARPOSITIONS }, + { "vanishCapDuration", LVT_U16, offsetof(struct LevelValues, vanishCapDuration), false, LOT_NONE }, + { "vanishCapDurationVcutm", LVT_U16, offsetof(struct LevelValues, vanishCapDurationVcutm), false, LOT_NONE }, + { "wingCapDuration", LVT_U16, offsetof(struct LevelValues, wingCapDuration), false, LOT_NONE }, + { "wingCapDurationTotwc", LVT_U16, offsetof(struct LevelValues, wingCapDurationTotwc), false, LOT_NONE }, }; #define LUA_LINEAR_TRANSITION_POINT_FIELD_COUNT 5 diff --git a/src/pc/network/packets/packet_collect_coin.c b/src/pc/network/packets/packet_collect_coin.c index 62ef48fed..5dbdbaab2 100644 --- a/src/pc/network/packets/packet_collect_coin.c +++ b/src/pc/network/packets/packet_collect_coin.c @@ -4,6 +4,7 @@ #include "object_constants.h" #include "behavior_table.h" #include "course_table.h" +#include "src/game/hardcoded.h" #include "src/game/interaction.h" #include "src/engine/math_util.h" #include "src/game/memory.h" @@ -96,8 +97,8 @@ SANITY_CHECK_COINS:; // check for 100-coin star if (COURSE_IS_MAIN_COURSE(gCurrCourseNum) - && oldNumCoins < 100 - && gMarioStates[0].numCoins >= 100 + && oldNumCoins < gLevelValues.coinsRequiredForCoinStar + && gMarioStates[0].numCoins >= gLevelValues.coinsRequiredForCoinStar && gCurrAreaIndex == areaIndex) { bhv_spawn_star_no_level_exit(gMarioStates[p->localIndex].marioObj, 6, FALSE); }