More rom-hacks globals to lua; more bug fixes (#84)

New gLevelValues exposed to lua:
        pssSlideStarTime: the time limit in frames for PSS-style levels (default: 630)
        pssSlideStarIndex: the index of the star spawned below the time limit for PSS-style levels (default: 1)
        coinsRequiredForCoinStar: number of coins required to spawn the 7th star of a main course (default: 100)
        wingCapDuration: duration in frames of the wing cap (default: 1800)
        metalCapDuration: duration in frames of the metal cap (default: 600)
        vanishCapDuration: duration in frames of the vanish cap (default: 600)
        wingCapDurationTotwc: duration in frames of the wing cap given to the player at the entrance of TOTWC (default: 1200)
        metalCapDurationCotmc: duration in frames of the metal cap given to the player at the entrance of COTMC (default: 600)
        vanishCapDurationVcutm: duration in frames of the vanish cap given to the player at the entrance of VCUTM (default: 600)
    Fixed a bug preventing the level music from restarting after defeating a Boss.
    Fixed some bugs with 3D coins or any model with the geo_rotate_coin function:
        Disable billboard and cylboard attributes.
        Set the pitch and roll to 0 for the model to rotate properly.
        The model no longer rotates every frame (even when the game is paused), but every time the object is updated.
This commit is contained in:
PeachyPeach 2022-05-08 21:18:25 +02:00 committed by GitHub
parent 6da950dc52
commit 94c531272f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 90 additions and 22 deletions

View file

@ -574,12 +574,21 @@
--- @field public yaw integer --- @field public yaw integer
--- @class LevelValues --- @class LevelValues
--- @field public coinsRequiredForCoinStar integer
--- @field public entryLevel LevelNum --- @field public entryLevel LevelNum
--- @field public exitCastleArea integer --- @field public exitCastleArea integer
--- @field public exitCastleLevel LevelNum --- @field public exitCastleLevel LevelNum
--- @field public exitCastleWarpNode integer --- @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 skipCreditsAt LevelNum
--- @field public starPositions StarPositions --- @field public starPositions StarPositions
--- @field public vanishCapDuration integer
--- @field public vanishCapDurationVcutm integer
--- @field public wingCapDuration integer
--- @field public wingCapDurationTotwc integer
--- @class LinearTransitionPoint --- @class LinearTransitionPoint
--- @field public dist number --- @field public dist number

View file

@ -1079,9 +1079,13 @@ static void *geo_rotate_3d_coin(s32 callContext, void *node, UNUSED void *c) {
struct Object *obj = (struct Object *) gCurGraphNodeObject; struct Object *obj = (struct Object *) gCurGraphNodeObject;
struct GraphNodeRotation *rotNode = (struct GraphNodeRotation *) ((struct GraphNode *) node)->next; struct GraphNodeRotation *rotNode = (struct GraphNodeRotation *) ((struct GraphNode *) node)->next;
rotNode->rotation[0] = 0; rotNode->rotation[0] = 0;
rotNode->rotation[1] = obj->oAnimState; rotNode->rotation[1] = obj->oAnimState * 0x0800;
rotNode->rotation[2] = 0; 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; return NULL;
} }

View file

@ -837,12 +837,21 @@
| Field | Type | Access | | Field | Type | Access |
| ----- | ---- | ------ | | ----- | ---- | ------ |
| coinsRequiredForCoinStar | `integer` | |
| entryLevel | [enum LevelNum](constants.md#enum-LevelNum) | | | entryLevel | [enum LevelNum](constants.md#enum-LevelNum) | |
| exitCastleArea | `integer` | | | exitCastleArea | `integer` | |
| exitCastleLevel | [enum LevelNum](constants.md#enum-LevelNum) | | | exitCastleLevel | [enum LevelNum](constants.md#enum-LevelNum) | |
| exitCastleWarpNode | `integer` | | | exitCastleWarpNode | `integer` | |
| metalCapDuration | `integer` | |
| metalCapDurationCotmc | `integer` | |
| pssSlideStarIndex | `integer` | |
| pssSlideStarTime | `integer` | |
| skipCreditsAt | [enum LevelNum](constants.md#enum-LevelNum) | | | skipCreditsAt | [enum LevelNum](constants.md#enum-LevelNum) | |
| starPositions | [StarPositions](structs.md#StarPositions) | read-only | | starPositions | [StarPositions](structs.md#StarPositions) | read-only |
| vanishCapDuration | `integer` | |
| vanishCapDurationVcutm | `integer` | |
| wingCapDuration | `integer` | |
| wingCapDurationTotwc | `integer` | |
[:arrow_up_small:](#) [:arrow_up_small:](#)

View file

@ -2435,6 +2435,23 @@ void stop_background_music(u16 seqId) {
// queue slot). // queue slot).
foundIndex = sBackgroundMusicQueueSize; 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. // Search for the sequence.
for (i = 0; i < sBackgroundMusicQueueSize; i++) { for (i = 0; i < sBackgroundMusicQueueSize; i++) {
if (sBackgroundMusicQueue[i].seqId == (u8)(seqId & 0xff)) { if (sBackgroundMusicQueue[i].seqId == (u8)(seqId & 0xff)) {

View file

@ -43,6 +43,15 @@ struct LevelValues gLevelValues = {
.exitCastleArea = 1, .exitCastleArea = 1,
.exitCastleWarpNode = 0x1F, .exitCastleWarpNode = 0x1F,
.skipCreditsAt = (LEVEL_MAX+1), .skipCreditsAt = (LEVEL_MAX+1),
.pssSlideStarTime = 630,
.pssSlideStarIndex = 1,
.coinsRequiredForCoinStar = 100,
.wingCapDuration = 1800,
.metalCapDuration = 600,
.vanishCapDuration = 600,
.wingCapDurationTotwc = 1200,
.metalCapDurationCotmc = 600,
.vanishCapDurationVcutm = 600,
.starPositions = { .starPositions = {
.KoopaBobStarPos = { 3030.0f, 4500.0f, -4600.0f }, .KoopaBobStarPos = { 3030.0f, 4500.0f, -4600.0f },
.KoopaThiStarPos = { 7100.0f, -1300.0f, -6000.0f }, .KoopaThiStarPos = { 7100.0f, -1300.0f, -6000.0f },

View file

@ -42,6 +42,15 @@ struct LevelValues {
s16 exitCastleArea; s16 exitCastleArea;
u8 exitCastleWarpNode; u8 exitCastleWarpNode;
enum LevelNum skipCreditsAt; enum LevelNum skipCreditsAt;
u16 pssSlideStarTime;
u8 pssSlideStarIndex;
s16 coinsRequiredForCoinStar;
u16 wingCapDuration;
u16 metalCapDuration;
u16 vanishCapDuration;
u16 wingCapDurationTotwc;
u16 metalCapDurationCotmc;
u16 vanishCapDurationVcutm;
struct StarPositions starPositions; struct StarPositions starPositions;
}; };

View file

@ -853,8 +853,8 @@ u32 interact_coin(struct MarioState *m, UNUSED u32 interactType, struct Object *
o->oInteractStatus = INT_STATUS_INTERACTED; o->oInteractStatus = INT_STATUS_INTERACTED;
if (COURSE_IS_MAIN_COURSE(gCurrCourseNum) && m->numCoins - o->oDamageOrCoinValue < 100 if (COURSE_IS_MAIN_COURSE(gCurrCourseNum) && m->numCoins - o->oDamageOrCoinValue < gLevelValues.coinsRequiredForCoinStar
&& m->numCoins >= 100) { && m->numCoins >= gLevelValues.coinsRequiredForCoinStar) {
bhv_spawn_star_no_level_exit(m->marioObj, 6, FALSE); 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) { switch (capFlag) {
case MARIO_VANISH_CAP: case MARIO_VANISH_CAP:
capTime = 600; capTime = gLevelValues.vanishCapDuration;
capMusic = SEQUENCE_ARGS(4, SEQ_EVENT_POWERUP); capMusic = SEQUENCE_ARGS(4, SEQ_EVENT_POWERUP);
break; break;
case MARIO_METAL_CAP: case MARIO_METAL_CAP:
capTime = 600; capTime = gLevelValues.metalCapDuration;
capMusic = SEQUENCE_ARGS(4, SEQ_EVENT_METAL_CAP); capMusic = SEQUENCE_ARGS(4, SEQ_EVENT_METAL_CAP);
break; break;
case MARIO_WING_CAP: case MARIO_WING_CAP:
capTime = 1800; capTime = gLevelValues.wingCapDuration;
capMusic = SEQUENCE_ARGS(4, SEQ_EVENT_POWERUP); capMusic = SEQUENCE_ARGS(4, SEQ_EVENT_POWERUP);
break; 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 //! This flag isn't set on death or level entry, allowing double star spawn
if (gPssSlideStarted) { if (gPssSlideStarted) {
u16 slideTime = level_control_timer(TIMER_CONTROL_STOP); u16 slideTime = level_control_timer(TIMER_CONTROL_STOP);
if (slideTime < 630) { if (slideTime < gLevelValues.pssSlideStarTime) {
// PSS secret star uses oBehParams to spawn // PSS secret star uses oBehParams to spawn
s32 tmp = m->marioObj->oBehParams; s32 tmp = m->marioObj->oBehParams;
m->marioObj->oBehParams = (1 << 24); m->marioObj->oBehParams = (gLevelValues.pssSlideStarIndex << 24);
f32* starPos = gLevelValues.starPositions.PssSlideStarPos; f32* starPos = gLevelValues.starPositions.PssSlideStarPos;
spawn_default_star(starPos[0], starPos[1], starPos[2]); spawn_default_star(starPos[0], starPos[1], starPos[2]);
m->marioObj->oBehParams = tmp; m->marioObj->oBehParams = tmp;

View file

@ -2,6 +2,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "course_table.h" #include "course_table.h"
#include "game/hardcoded.h"
#include "game/memory.h" #include "game/memory.h"
#include "level_info.h" #include "level_info.h"
#include "level_table.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)]); const u8 *starName = segmented_to_virtual(actNameTable[(courseNum - COURSE_BOB) * 6 + (starNum - 1)]);
convert_string_sm64_to_ascii(output, starName); convert_string_sm64_to_ascii(output, starName);
} else if (starNum == 7) { } else if (starNum == 7) {
snprintf(output, 256, "100 Coins Star"); snprintf(output, 256, "%d Coins Star", (s32) gLevelValues.coinsRequiredForCoinStar);
} else { } else {
snprintf(output, 256, "A Secret Star!"); snprintf(output, 256, "A Secret Star!");
} }

View file

@ -314,17 +314,17 @@ void set_mario_initial_cap_powerup(struct MarioState *m) {
switch (capCourseIndex) { switch (capCourseIndex) {
case COURSE_COTMC - COURSE_CAP_COURSES: case COURSE_COTMC - COURSE_CAP_COURSES:
m->flags |= MARIO_METAL_CAP | MARIO_CAP_ON_HEAD; m->flags |= MARIO_METAL_CAP | MARIO_CAP_ON_HEAD;
m->capTimer = 600; m->capTimer = gLevelValues.metalCapDurationCotmc;
break; break;
case COURSE_TOTWC - COURSE_CAP_COURSES: case COURSE_TOTWC - COURSE_CAP_COURSES:
m->flags |= MARIO_WING_CAP | MARIO_CAP_ON_HEAD; m->flags |= MARIO_WING_CAP | MARIO_CAP_ON_HEAD;
m->capTimer = 1200; m->capTimer = gLevelValues.wingCapDurationTotwc;
break; break;
case COURSE_VCUTM - COURSE_CAP_COURSES: case COURSE_VCUTM - COURSE_CAP_COURSES:
m->flags |= MARIO_VANISH_CAP | MARIO_CAP_ON_HEAD; m->flags |= MARIO_VANISH_CAP | MARIO_CAP_ON_HEAD;
m->capTimer = 600; m->capTimer = gLevelValues.vanishCapDurationVcutm;
break; break;
} }
} }

View file

@ -670,14 +670,23 @@ static struct LuaObjectField sLakituStateFields[LUA_LAKITU_STATE_FIELD_COUNT] =
{ "yaw", LVT_S16, offsetof(struct LakituState, yaw), false, LOT_NONE }, { "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] = { static struct LuaObjectField sLevelValuesFields[LUA_LEVEL_VALUES_FIELD_COUNT] = {
{ "coinsRequiredForCoinStar", LVT_S16, offsetof(struct LevelValues, coinsRequiredForCoinStar), false, LOT_NONE },
{ "entryLevel", LVT_S32, offsetof(struct LevelValues, entryLevel), false, LOT_NONE }, { "entryLevel", LVT_S32, offsetof(struct LevelValues, entryLevel), false, LOT_NONE },
{ "exitCastleArea", LVT_S16, offsetof(struct LevelValues, exitCastleArea), false, LOT_NONE }, { "exitCastleArea", LVT_S16, offsetof(struct LevelValues, exitCastleArea), false, LOT_NONE },
{ "exitCastleLevel", LVT_S32, offsetof(struct LevelValues, exitCastleLevel), false, LOT_NONE }, { "exitCastleLevel", LVT_S32, offsetof(struct LevelValues, exitCastleLevel), false, LOT_NONE },
{ "exitCastleWarpNode", LVT_U8, offsetof(struct LevelValues, exitCastleWarpNode), 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 }, { "skipCreditsAt", LVT_S32, offsetof(struct LevelValues, skipCreditsAt), false, LOT_NONE },
{ "starPositions", LVT_COBJECT, offsetof(struct LevelValues, starPositions), true, LOT_STARPOSITIONS }, { "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 #define LUA_LINEAR_TRANSITION_POINT_FIELD_COUNT 5

View file

@ -4,6 +4,7 @@
#include "object_constants.h" #include "object_constants.h"
#include "behavior_table.h" #include "behavior_table.h"
#include "course_table.h" #include "course_table.h"
#include "src/game/hardcoded.h"
#include "src/game/interaction.h" #include "src/game/interaction.h"
#include "src/engine/math_util.h" #include "src/engine/math_util.h"
#include "src/game/memory.h" #include "src/game/memory.h"
@ -96,8 +97,8 @@ SANITY_CHECK_COINS:;
// check for 100-coin star // check for 100-coin star
if (COURSE_IS_MAIN_COURSE(gCurrCourseNum) if (COURSE_IS_MAIN_COURSE(gCurrCourseNum)
&& oldNumCoins < 100 && oldNumCoins < gLevelValues.coinsRequiredForCoinStar
&& gMarioStates[0].numCoins >= 100 && gMarioStates[0].numCoins >= gLevelValues.coinsRequiredForCoinStar
&& gCurrAreaIndex == areaIndex) { && gCurrAreaIndex == areaIndex) {
bhv_spawn_star_no_level_exit(gMarioStates[p->localIndex].marioObj, 6, FALSE); bhv_spawn_star_no_level_exit(gMarioStates[p->localIndex].marioObj, 6, FALSE);
} }