Merge pull request #629 from HackerN64/develop/2.1.0-red-coin-count-increase

Develop/2.1.0 red coin count increase
This commit is contained in:
CowQuack
2023-06-07 12:42:09 -04:00
committed by GitHub
12 changed files with 118 additions and 23 deletions

View File

@@ -121,7 +121,7 @@ Thanks to Frame#5375 and AloXado320 for also helping with silhouette stuff
- Use `render_multi_image` to draw large texture rectangles consisting of multiple images on the screen.
- More info in `puppyprint.c`
- Wiseguy's Farcall TLB mapping allows to store executable code inside uncompressed segments, that can be loaded and ran as needed, instead of it having to be loaded at all times. See `farcall.h` in the include folder for instructions and details.
- Red Coin Stars now support up to 99 red coins! In addition, multi-area red coin missions can now be created by setting the 2nd behavior paramater of the red coin star to the number of reds required for the star to spawn.
# UltraSM64
- This repo contains a full decompilation of Super Mario 64 (J), (U), (E), and (SH).

View File

@@ -4581,6 +4581,7 @@ const BehaviorScript bhvRedCoin[] = {
const BehaviorScript bhvBowserCourseRedCoinStar[] = {
BEGIN(OBJ_LIST_LEVEL),
OR_INT(oFlags, (OBJ_FLAG_PERSISTENT_RESPAWN | OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE)),
CALL_NATIVE(bhv_bowser_course_red_coin_star_init),
BEGIN_LOOP(),
CALL_NATIVE(bhv_bowser_course_red_coin_star_loop),
END_LOOP(),
@@ -4862,7 +4863,6 @@ const BehaviorScript bhvOrangeNumber[] = {
BEGIN(OBJ_LIST_LEVEL),
OR_INT(oFlags, OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE),
BILLBOARD(),
SET_HOME(),
CALL_NATIVE(bhv_orange_number_init),
BEGIN_LOOP(),
CALL_NATIVE(bhv_orange_number_loop),

View File

@@ -797,6 +797,9 @@
#define /*0x0F8*/ oRespawnerMinSpawnDist OBJECT_FIELD_F32(0x1C)
#define /*0x0FC*/ oRespawnerBehaviorToRespawn OBJECT_FIELD_CVPTR(0x1D)
/* Orange Number */
#define /*0x110*/ oOrangeNumberOffset OBJECT_FIELD_S32(0x22)
/* Openable Grill */
#define /*0x088*/ oOpenableGrillIsOpen OBJECT_FIELD_S32(0x00)
#define /*0x0F4*/ oOpenableGrillFloorSwitchObj OBJECT_FIELD_OBJ(0x1B)
@@ -998,6 +1001,7 @@
/* Hidden Star */
// Secrets/Red Coins
#define /*0x0F4*/ oHiddenStarTriggerCounter OBJECT_FIELD_S32(0x1B)
#define /*0x0F8*/ oHiddenStarTriggerTotal OBJECT_FIELD_S32(0x1C)
/* Sealed Door Star */
#define /*0x108*/ oUnlockDoorStarState OBJECT_FIELD_U32(0x20)

View File

@@ -380,6 +380,7 @@ void bhv_hidden_red_coin_star_init(void);
void bhv_hidden_red_coin_star_loop(void);
void bhv_red_coin_init(void);
void bhv_red_coin_loop(void);
void bhv_bowser_course_red_coin_star_init(void);
void bhv_bowser_course_red_coin_star_loop(void);
void bhv_hidden_star_init(void);
void bhv_hidden_star_loop(void);

View File

@@ -47,12 +47,24 @@ void bhv_hidden_star_trigger_loop(void) {
}
}
void bhv_bowser_course_red_coin_star_init(void) {
if (o->oBehParams2ndByte != 0) {
o->oHiddenStarTriggerTotal = o->oBehParams2ndByte;
o->oHiddenStarTriggerCounter = gRedCoinsCollected;
}
else {
s16 numRedCoinsRemaining = count_objects_with_behavior(bhvRedCoin);
o->oHiddenStarTriggerTotal = numRedCoinsRemaining + gRedCoinsCollected;
o->oHiddenStarTriggerCounter = o->oHiddenStarTriggerTotal - numRedCoinsRemaining;
}
}
void bhv_bowser_course_red_coin_star_loop(void) {
gRedCoinsCollected = o->oHiddenStarTriggerCounter;
switch (o->oAction) {
case 0:
if (o->oHiddenStarTriggerCounter == 8) {
if (o->oHiddenStarTriggerCounter == o->oHiddenStarTriggerTotal) {
o->oAction = 1;
}
break;

View File

@@ -3,6 +3,7 @@
void bhv_orange_number_init(void) {
o->oAnimState = o->oBehParams2ndByte;
o->oVelY = 26.0f;
o->oHomeY = o->oPosY;
}
void bhv_orange_number_loop(void) {
@@ -16,6 +17,13 @@ void bhv_orange_number_loop(void) {
o->oVelY = 14.0f;
}
s32 offsetX, offsetZ;
offsetX = o->oOrangeNumberOffset * sins(gCamera->nextYaw + 0x4000);
offsetZ = o->oOrangeNumberOffset * coss(gCamera->nextYaw + 0x4000);
o->oPosX = o->oHomeX + offsetX;
o->oPosZ = o->oHomeZ + offsetZ;
if (o->oTimer == 35) {
struct Object *sparkleObj = spawn_object(o, MODEL_SPARKLES, bhvCoinSparklesSpawner);
sparkleObj->oPosY -= 30.0f;

View File

@@ -50,18 +50,35 @@ void bhv_red_coin_loop(void) {
o->parentObj->oHiddenStarTriggerCounter++;
// Spawn the orange number counter, as long as it isn't the last coin.
if (o->parentObj->oHiddenStarTriggerCounter != 8) {
spawn_orange_number(o->parentObj->oHiddenStarTriggerCounter, 0, 0, 0);
if (o->parentObj->oHiddenStarTriggerCounter != o->parentObj->oHiddenStarTriggerTotal) {
// Cap visible count to 99
if (o->parentObj->oHiddenStarTriggerCounter > 99) {
spawn_orange_number(9, 28, 0, 0);
spawn_orange_number(9, -28, 0, 0);
}
else if (o->parentObj->oHiddenStarTriggerCounter >= 10) {
spawn_orange_number(o->parentObj->oHiddenStarTriggerCounter % 10, 28, 0, 0);
spawn_orange_number(o->parentObj->oHiddenStarTriggerCounter / 10, -28, 0, 0);
}
else {
spawn_orange_number(o->parentObj->oHiddenStarTriggerCounter, 0, 0, 0);
}
}
#ifdef JP_RED_COIN_SOUND
// For JP version, play an identical sound for all coins.
create_sound_spawner(SOUND_GENERAL_RED_COIN);
#else
// On all versions but the JP version, each coin collected plays a higher noise.
play_sound(SOUND_MENU_COLLECT_RED_COIN
+ (((u8) o->parentObj->oHiddenStarTriggerCounter - 1) << 16),
gGlobalSoundSource);
if (o->parentObj->oHiddenStarTriggerTotal - o->parentObj->oHiddenStarTriggerCounter > 7) {
// Play the first red coin sound until it gets to the final 8
play_sound(SOUND_MENU_COLLECT_RED_COIN, gGlobalSoundSource);
}
else {
// On all versions but the JP version, each coin collected plays a higher noise.
play_sound(SOUND_MENU_COLLECT_RED_COIN
+ (((u8) 7 - (o->parentObj->oHiddenStarTriggerTotal - o->parentObj->oHiddenStarTriggerCounter)) << 16),
gGlobalSoundSource);
}
#endif
}

View File

@@ -157,14 +157,27 @@ void bhv_hidden_red_coin_star_init(void) {
spawn_object(o, MODEL_TRANSPARENT_STAR, bhvRedCoinStarMarker);
}
s16 numRedCoinsRemaining = count_objects_with_behavior(bhvRedCoin);
if (numRedCoinsRemaining == 0) {
starObj = spawn_object_abs_with_rot(o, 0, MODEL_STAR, bhvStar, o->oPosX, o->oPosY, o->oPosZ, 0, 0, 0);
starObj->oBehParams = o->oBehParams;
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
// check if bparam2 specifies a total number of coins that should spawn the star
if (o->oBehParams2ndByte != 0) {
o->oHiddenStarTriggerTotal = o->oBehParams2ndByte;
o->oHiddenStarTriggerCounter = gRedCoinsCollected;
if (o->oHiddenStarTriggerCounter >= o->oHiddenStarTriggerTotal) {
starObj = spawn_object_abs_with_rot(o, 0, MODEL_STAR, bhvStar, o->oPosX, o->oPosY, o->oPosZ, 0, 0, 0);
starObj->oBehParams = o->oBehParams;
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
}
}
o->oHiddenStarTriggerCounter = 8 - numRedCoinsRemaining;
else {
s16 numRedCoinsRemaining = count_objects_with_behavior(bhvRedCoin);
if (numRedCoinsRemaining == 0) {
starObj = spawn_object_abs_with_rot(o, 0, MODEL_STAR, bhvStar, o->oPosX, o->oPosY, o->oPosZ, 0, 0, 0);
starObj->oBehParams = o->oBehParams;
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
}
o->oHiddenStarTriggerTotal = numRedCoinsRemaining + gRedCoinsCollected;
o->oHiddenStarTriggerCounter = o->oHiddenStarTriggerTotal - numRedCoinsRemaining;
}
}
void bhv_hidden_red_coin_star_loop(void) {
@@ -172,7 +185,7 @@ void bhv_hidden_red_coin_star_loop(void) {
switch (o->oAction) {
case HIDDEN_STAR_ACT_INACTIVE:
if (o->oHiddenStarTriggerCounter == 8) {
if (o->oHiddenStarTriggerCounter == o->oHiddenStarTriggerTotal) {
o->oAction = HIDDEN_STAR_ACT_ACTIVE;
}
break;

View File

@@ -1512,8 +1512,36 @@ void print_animated_red_coin(s16 x, s16 y) {
void render_pause_red_coins(void) {
s8 x;
for (x = 0; x < gRedCoinsCollected; x++) {
print_animated_red_coin(GFX_DIMENSIONS_FROM_RIGHT_EDGE(30) - x * 20, 16);
if (gRedCoinsCollected <= 9) {
for (x = 0; x < gRedCoinsCollected; x++) {
print_animated_red_coin(GFX_DIMENSIONS_FROM_RIGHT_EDGE(30) - x * 20, 16);
}
}
else {
print_animated_red_coin(GFX_DIMENSIONS_FROM_RIGHT_EDGE(108), 16);
Mtx *mtx;
mtx = alloc_display_list(sizeof(*mtx));
if (mtx == NULL) {
return;
}
guOrtho(mtx, 0.0f, SCREEN_WIDTH, 0.0f, SCREEN_HEIGHT, -10.0f, 10.0f, 1.0f);
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(mtx), G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH);
gSPDisplayList(gDisplayListHead++, dl_hud_img_begin);
s8 redCoinCount = gRedCoinsCollected;
if (redCoinCount > 99) {
redCoinCount = 99;
}
add_glyph_texture(GLYPH_MULTIPLY);
render_textrect(GFX_DIMENSIONS_FROM_RIGHT_EDGE(100), 16, 0);
add_glyph_texture(char_to_glyph_index((char) (48 + (redCoinCount / 10))));
render_textrect(GFX_DIMENSIONS_FROM_RIGHT_EDGE(86), 16, 0);
add_glyph_texture(char_to_glyph_index((char) (48 + (redCoinCount % 10))));
render_textrect(GFX_DIMENSIONS_FROM_RIGHT_EDGE(86), 16, 1);
gSPDisplayList(gDisplayListHead++, dl_hud_img_end);
}
}

View File

@@ -1707,11 +1707,14 @@ u32 check_read_sign(struct MarioState *m, struct Object *obj) {
&& abs_angle_diff(mario_obj_angle_to_object(m, obj), m->faceAngle[1]) <= SIGN_RANGE
) {
#ifdef DIALOG_INDICATOR
struct Object *orangeNumber;
if (obj->behavior == segmented_to_virtual(bhvSignOnWall)) {
spawn_object_relative(ORANGE_NUMBER_A, 0, 180, 32, obj, MODEL_NUMBER, bhvOrangeNumber);
orangeNumber = spawn_object_relative(ORANGE_NUMBER_A, 0, 180, 32, obj, MODEL_NUMBER, bhvOrangeNumber);
} else {
spawn_object_relative(ORANGE_NUMBER_A, 0, 160, 8, obj, MODEL_NUMBER, bhvOrangeNumber);
orangeNumber = spawn_object_relative(ORANGE_NUMBER_A, 0, 160, 8, obj, MODEL_NUMBER, bhvOrangeNumber);
}
orangeNumber->oHomeX = orangeNumber->oPosX;
orangeNumber->oHomeZ = orangeNumber->oPosZ;
#endif
if (m->input & READ_MASK) {
#else
@@ -1742,11 +1745,14 @@ u32 check_npc_talk(struct MarioState *m, struct Object *obj) {
&& abs_angle_diff(mario_obj_angle_to_object(m, obj), m->faceAngle[1]) <= SIGN_RANGE
) {
#ifdef DIALOG_INDICATOR
struct Object *orangeNumber;
if (obj->behavior == segmented_to_virtual(bhvYoshi)) {
spawn_object_relative(ORANGE_NUMBER_A, 0, 256, 64, obj, MODEL_NUMBER, bhvOrangeNumber);
orangeNumber = spawn_object_relative(ORANGE_NUMBER_A, 0, 256, 64, obj, MODEL_NUMBER, bhvOrangeNumber);
} else {
spawn_object_relative(ORANGE_NUMBER_A, 0, 160, 0, obj, MODEL_NUMBER, bhvOrangeNumber);
orangeNumber = spawn_object_relative(ORANGE_NUMBER_A, 0, 160, 0, obj, MODEL_NUMBER, bhvOrangeNumber);
}
orangeNumber->oHomeX = orangeNumber->oPosX;
orangeNumber->oHomeZ = orangeNumber->oPosZ;
#endif
if (m->input & READ_MASK) {
#else

View File

@@ -691,6 +691,9 @@ void spawn_orange_number(s8 behParam, s16 relX, s16 relY, s16 relZ) {
struct Object *orangeNumber = spawn_object_relative(behParam, relX, relY, relZ, o, MODEL_NUMBER, bhvOrangeNumber);
orangeNumber->oPosY += 25.0f;
orangeNumber->oOrangeNumberOffset = relX;
orangeNumber->oHomeX = o->oPosX;
orangeNumber->oHomeZ = o->oPosZ;
}
/**

View File

@@ -34,5 +34,8 @@ void print_text_fmt_int(s32 x, s32 y, const char *str, s32 n);
void print_text(s32 x, s32 y, const char *str);
void print_text_centered(s32 x, s32 y, const char *str);
void render_text_labels(void);
s32 char_to_glyph_index(char c);
void add_glyph_texture(s8 glyphIndex);
void render_textrect(s32 x, s32 y, s32 pos);
#endif // PRINT_H