From 68e1b72b9929178bf9b1985ce48a67b7c55523c7 Mon Sep 17 00:00:00 2001 From: PeachyPeach <72323920+PeachyPeachSM64@users.noreply.github.com> Date: Sun, 8 May 2022 04:09:37 +0200 Subject: [PATCH] 3-digits orange numbers; Fixed red coins and secrets bugs; Correct red coins display during pause (#82) Modified number_geo to allow it to display orange numbers from 0 to 999. Edited red coins/secrets code: Added two fields in the Area struct: numRedCoins and numSecrets The number of red coins/secrets in every area is computed during level script processing Removed the useless global gRedCoinsCollected These changes fix the following bugs: Wrong sound effect played and incorrect number displayed when there is more than 8 red coins/5 secrets Desynced red coins/secrets counter when going from an area to another Remotely spawning red coins/secrets stars in other areas without collecting all red coins/secrets Pausing the game now shows the correct number of collected red coins / the total number of red coins in the current area. --- actors/number/geo.inc.c | 219 ++++++++++++++++-- autogen/lua_definitions/structs.lua | 2 + bin/segment2.c | 113 ++++++++- docs/lua/structs.md | 2 + src/engine/level_script.c | 24 ++ src/game/area.h | 2 + src/game/behaviors/hidden_star.inc.c | 22 +- src/game/behaviors/red_coin.inc.c | 18 +- src/game/behaviors/spawn_star.inc.c | 5 +- src/game/ingame_menu.c | 29 ++- src/game/ingame_menu.h | 1 - src/game/obj_behaviors.c | 5 - src/pc/lua/smlua_cobject_autogen.c | 4 +- src/pc/network/packets/packet_level.c | 10 - textures/segment2/custom_hud_slash.rgba16.png | Bin 0 -> 243 bytes 15 files changed, 389 insertions(+), 67 deletions(-) create mode 100644 textures/segment2/custom_hud_slash.rgba16.png diff --git a/actors/number/geo.inc.c b/actors/number/geo.inc.c index 0cf3845c..44b4135d 100644 --- a/actors/number/geo.inc.c +++ b/actors/number/geo.inc.c @@ -1,20 +1,205 @@ // 0x16000E14 +// const GeoLayout number_geo[] = { +// GEO_NODE_START(), +// GEO_OPEN_NODE(), +// GEO_SWITCH_CASE(10, geo_switch_anim_state), +// GEO_OPEN_NODE(), +// GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num_0), +// GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num_1), +// GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num_2), +// GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num_3), +// GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num_4), +// GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num_5), +// GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num_6), +// GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num_7), +// GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num_8), +// GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num_9), +// GEO_CLOSE_NODE(), +// GEO_CLOSE_NODE(), +// GEO_END(), +// }; + +// +// Three-digits orange number +// + +#include "types.h" +#include "object_fields.h" +#include "engine/graph_node.h" +#include "game/rendering_graph_node.h" + +Gfx *geo_num3_switch(s32 callContext, struct GraphNode *node, UNUSED void *context) { + if (gCurGraphNodeObject != NULL && callContext == GEO_CONTEXT_RENDER) { + s32 number = ((struct Object *) gCurGraphNodeObject)->oBehParams2ndByte; + struct GraphNodeSwitchCase *switchCase = (struct GraphNodeSwitchCase *) node; + s32 numMin, numMax, numDiv; + switch (switchCase->numCases) { + case 0: numMin = 0; numMax = 9; numDiv = 1; break; + case 1: numMin = 10; numMax = 99; numDiv = 10; break; + case 2: numMin = 10; numMax = 99; numDiv = 1; break; + case 3: numMin = 100; numMax = 999; numDiv = 100; break; + case 4: numMin = 100; numMax = 999; numDiv = 10; break; + case 5: numMin = 100; numMax = 999; numDiv = 1; break; + } + if (number >= numMin && number <= numMax) { + switchCase->selectedCase = (number / numDiv) % 10; + } else { + switchCase->selectedCase = 10; + } + } +} + +extern const Gfx dl_billboard_num3_0[]; +extern const Gfx dl_billboard_num3_1[]; +extern const Gfx dl_billboard_num3_2[]; +extern const Gfx dl_billboard_num3_3[]; +extern const Gfx dl_billboard_num3_4[]; +extern const Gfx dl_billboard_num3_5[]; +extern const Gfx dl_billboard_num3_6[]; +extern const Gfx dl_billboard_num3_7[]; +extern const Gfx dl_billboard_num3_8[]; +extern const Gfx dl_billboard_num3_9[]; +extern const Gfx dl_billboard_num3_0x[]; +extern const Gfx dl_billboard_num3_1x[]; +extern const Gfx dl_billboard_num3_2x[]; +extern const Gfx dl_billboard_num3_3x[]; +extern const Gfx dl_billboard_num3_4x[]; +extern const Gfx dl_billboard_num3_5x[]; +extern const Gfx dl_billboard_num3_6x[]; +extern const Gfx dl_billboard_num3_7x[]; +extern const Gfx dl_billboard_num3_8x[]; +extern const Gfx dl_billboard_num3_9x[]; +extern const Gfx dl_billboard_num3_x0[]; +extern const Gfx dl_billboard_num3_x1[]; +extern const Gfx dl_billboard_num3_x2[]; +extern const Gfx dl_billboard_num3_x3[]; +extern const Gfx dl_billboard_num3_x4[]; +extern const Gfx dl_billboard_num3_x5[]; +extern const Gfx dl_billboard_num3_x6[]; +extern const Gfx dl_billboard_num3_x7[]; +extern const Gfx dl_billboard_num3_x8[]; +extern const Gfx dl_billboard_num3_x9[]; +extern const Gfx dl_billboard_num3_0xx[]; +extern const Gfx dl_billboard_num3_1xx[]; +extern const Gfx dl_billboard_num3_2xx[]; +extern const Gfx dl_billboard_num3_3xx[]; +extern const Gfx dl_billboard_num3_4xx[]; +extern const Gfx dl_billboard_num3_5xx[]; +extern const Gfx dl_billboard_num3_6xx[]; +extern const Gfx dl_billboard_num3_7xx[]; +extern const Gfx dl_billboard_num3_8xx[]; +extern const Gfx dl_billboard_num3_9xx[]; +extern const Gfx dl_billboard_num3_x0x[]; +extern const Gfx dl_billboard_num3_x1x[]; +extern const Gfx dl_billboard_num3_x2x[]; +extern const Gfx dl_billboard_num3_x3x[]; +extern const Gfx dl_billboard_num3_x4x[]; +extern const Gfx dl_billboard_num3_x5x[]; +extern const Gfx dl_billboard_num3_x6x[]; +extern const Gfx dl_billboard_num3_x7x[]; +extern const Gfx dl_billboard_num3_x8x[]; +extern const Gfx dl_billboard_num3_x9x[]; +extern const Gfx dl_billboard_num3_xx0[]; +extern const Gfx dl_billboard_num3_xx1[]; +extern const Gfx dl_billboard_num3_xx2[]; +extern const Gfx dl_billboard_num3_xx3[]; +extern const Gfx dl_billboard_num3_xx4[]; +extern const Gfx dl_billboard_num3_xx5[]; +extern const Gfx dl_billboard_num3_xx6[]; +extern const Gfx dl_billboard_num3_xx7[]; +extern const Gfx dl_billboard_num3_xx8[]; +extern const Gfx dl_billboard_num3_xx9[]; + const GeoLayout number_geo[] = { - GEO_NODE_START(), - GEO_OPEN_NODE(), - GEO_SWITCH_CASE(10, geo_switch_anim_state), - GEO_OPEN_NODE(), - GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num_0), - GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num_1), - GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num_2), - GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num_3), - GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num_4), - GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num_5), - GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num_6), - GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num_7), - GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num_8), - GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num_9), - GEO_CLOSE_NODE(), - GEO_CLOSE_NODE(), - GEO_END(), + GEO_NODE_START(), + GEO_OPEN_NODE(), + GEO_BILLBOARD(), + GEO_OPEN_NODE(), + GEO_SWITCH_CASE(0, geo_num3_switch), + GEO_OPEN_NODE(), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_0), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_1), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_2), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_3), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_4), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_5), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_6), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_7), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_8), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_9), + GEO_DISPLAY_LIST(LAYER_ALPHA, NULL), + GEO_CLOSE_NODE(), + GEO_SWITCH_CASE(1, geo_num3_switch), + GEO_OPEN_NODE(), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_0x), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_1x), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_2x), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_3x), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_4x), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_5x), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_6x), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_7x), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_8x), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_9x), + GEO_DISPLAY_LIST(LAYER_ALPHA, NULL), + GEO_CLOSE_NODE(), + GEO_SWITCH_CASE(2, geo_num3_switch), + GEO_OPEN_NODE(), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_x0), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_x1), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_x2), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_x3), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_x4), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_x5), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_x6), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_x7), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_x8), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_x9), + GEO_DISPLAY_LIST(LAYER_ALPHA, NULL), + GEO_CLOSE_NODE(), + GEO_SWITCH_CASE(3, geo_num3_switch), + GEO_OPEN_NODE(), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_0xx), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_1xx), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_2xx), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_3xx), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_4xx), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_5xx), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_6xx), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_7xx), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_8xx), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_9xx), + GEO_DISPLAY_LIST(LAYER_ALPHA, NULL), + GEO_CLOSE_NODE(), + GEO_SWITCH_CASE(4, geo_num3_switch), + GEO_OPEN_NODE(), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_x0x), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_x1x), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_x2x), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_x3x), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_x4x), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_x5x), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_x6x), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_x7x), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_x8x), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_x9x), + GEO_DISPLAY_LIST(LAYER_ALPHA, NULL), + GEO_CLOSE_NODE(), + GEO_SWITCH_CASE(5, geo_num3_switch), + GEO_OPEN_NODE(), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_xx0), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_xx1), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_xx2), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_xx3), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_xx4), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_xx5), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_xx6), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_xx7), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_xx8), + GEO_DISPLAY_LIST(LAYER_ALPHA, dl_billboard_num3_xx9), + GEO_DISPLAY_LIST(LAYER_ALPHA, NULL), + GEO_CLOSE_NODE(), + GEO_CLOSE_NODE(), + GEO_CLOSE_NODE(), + GEO_END(), }; diff --git a/autogen/lua_definitions/structs.lua b/autogen/lua_definitions/structs.lua index 7227f6a0..2a0d1759 100644 --- a/autogen/lua_definitions/structs.lua +++ b/autogen/lua_definitions/structs.lua @@ -34,6 +34,8 @@ --- @field public macroObjectsAltered Pointer_integer --- @field public musicParam integer --- @field public musicParam2 integer +--- @field public numRedCoins integer +--- @field public numSecrets integer --- @field public objectSpawnInfos SpawnInfo --- @field public paintingWarpNodes WarpNode --- @field public surfaceRooms Pointer_integer diff --git a/bin/segment2.c b/bin/segment2.c index 57bf1c38..7cc07beb 100644 --- a/bin/segment2.c +++ b/bin/segment2.c @@ -205,6 +205,10 @@ ALIGNED8 const Texture texture_hud_char_percent[] = { }; #endif +ALIGNED8 const Texture texture_hud_char_slash[] = { +#include "textures/segment2/custom_hud_slash.rgba16.inc.c" +}; + ALIGNED8 const Texture texture_hud_char_multiply[] = { #include "textures/segment2/segment2.05600.rgba16.inc.c" }; @@ -1840,7 +1844,7 @@ const Texture *const main_hud_lut[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, texture_hud_char_multiply, texture_hud_char_coin, + 0x0, texture_hud_char_slash, texture_hud_char_multiply, texture_hud_char_coin, texture_hud_char_mario_head, texture_hud_char_star, texture_hud_char_luigi_head, 0x0, texture_hud_char_apostrophe, texture_hud_char_double_quote, texture_hud_char_umlaut, #elif defined(VERSION_US) @@ -1856,7 +1860,7 @@ const Texture *const main_hud_lut[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, texture_hud_char_multiply, texture_hud_char_coin, + 0x0, texture_hud_char_slash, texture_hud_char_multiply, texture_hud_char_coin, texture_hud_char_mario_head, texture_hud_char_star, texture_hud_char_luigi_head, texture_hud_char_toad_head, texture_hud_char_apostrophe, texture_hud_char_double_quote, #else @@ -1872,7 +1876,7 @@ const Texture *const main_hud_lut[] = { texture_hud_char_exclamation, texture_hud_char_double_exclamation, texture_hud_char_question, texture_hud_char_ampersand, texture_hud_char_percent, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, texture_hud_char_multiply, texture_hud_char_coin, + 0x0, texture_hud_char_slash, texture_hud_char_multiply, texture_hud_char_coin, texture_hud_char_mario_head, texture_hud_char_star, texture_hud_char_decimal_point, texture_hud_char_beta_key, texture_hud_char_apostrophe, texture_hud_char_double_quote, #endif @@ -2475,6 +2479,109 @@ const Gfx dl_billboard_num_9[] = { gsSPEndDisplayList(), }; +// +// Three-digits orange number +// + +const Vtx vertex_billboard_num3[] = { + { { { -32, -32, 0 }, 0, { 0, 1024 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { +32, -32, 0 }, 0, { 1024, 1024 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { +32, +32, 0 }, 0, { 1024, 0 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { -32, +32, 0 }, 0, { 0, 0 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { -56, -32, 0 }, 0, { 0, 1024 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { +8, -32, 0 }, 0, { 1024, 1024 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { +8, +32, 0 }, 0, { 1024, 0 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { -56, +32, 0 }, 0, { 0, 0 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { -8, -32, 0 }, 0, { 0, 1024 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { +56, -32, 0 }, 0, { 1024, 1024 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { +56, +32, 0 }, 0, { 1024, 0 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { -8, +32, 0 }, 0, { 0, 0 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { -80, -32, 0 }, 0, { 0, 1024 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { -16, -32, 0 }, 0, { 1024, 1024 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { -16, +32, 0 }, 0, { 1024, 0 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { -80, +32, 0 }, 0, { 0, 0 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { -32, -32, 0 }, 0, { 0, 1024 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { +32, -32, 0 }, 0, { 1024, 1024 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { +32, +32, 0 }, 0, { 1024, 0 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { -32, +32, 0 }, 0, { 0, 0 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { +16, -32, 0 }, 0, { 0, 1024 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { +80, -32, 0 }, 0, { 1024, 1024 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { +80, +32, 0 }, 0, { 1024, 0 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, + { { { +16, +32, 0 }, 0, { 0, 0 }, { 0xFF, 0xFF, 0xFF, 0xFF } } }, +}; + +#define define_dl_billboard_num3(type, digit, offset) \ +const Gfx dl_billboard_num3_##type[] = { \ + gsSPDisplayList(dl_billboard_num_begin), \ + gsDPSetTextureImage(G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, texture_hud_char_##digit), \ + gsDPLoadSync(), \ + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, 16 * 16 - 1, CALC_DXT(16, G_IM_SIZ_16b_BYTES)), \ + gsSPVertex(vertex_billboard_num3 + (4 * (offset)), 4, 0), \ + gsSPDisplayList(dl_billboard_num_end + 1), \ + gsSPEndDisplayList(), \ +}; + +define_dl_billboard_num3(0, 0, 0); +define_dl_billboard_num3(1, 1, 0); +define_dl_billboard_num3(2, 2, 0); +define_dl_billboard_num3(3, 3, 0); +define_dl_billboard_num3(4, 4, 0); +define_dl_billboard_num3(5, 5, 0); +define_dl_billboard_num3(6, 6, 0); +define_dl_billboard_num3(7, 7, 0); +define_dl_billboard_num3(8, 8, 0); +define_dl_billboard_num3(9, 9, 0); +define_dl_billboard_num3(0x, 0, 1); +define_dl_billboard_num3(1x, 1, 1); +define_dl_billboard_num3(2x, 2, 1); +define_dl_billboard_num3(3x, 3, 1); +define_dl_billboard_num3(4x, 4, 1); +define_dl_billboard_num3(5x, 5, 1); +define_dl_billboard_num3(6x, 6, 1); +define_dl_billboard_num3(7x, 7, 1); +define_dl_billboard_num3(8x, 8, 1); +define_dl_billboard_num3(9x, 9, 1); +define_dl_billboard_num3(x0, 0, 2); +define_dl_billboard_num3(x1, 1, 2); +define_dl_billboard_num3(x2, 2, 2); +define_dl_billboard_num3(x3, 3, 2); +define_dl_billboard_num3(x4, 4, 2); +define_dl_billboard_num3(x5, 5, 2); +define_dl_billboard_num3(x6, 6, 2); +define_dl_billboard_num3(x7, 7, 2); +define_dl_billboard_num3(x8, 8, 2); +define_dl_billboard_num3(x9, 9, 2); +define_dl_billboard_num3(0xx, 0, 3); +define_dl_billboard_num3(1xx, 1, 3); +define_dl_billboard_num3(2xx, 2, 3); +define_dl_billboard_num3(3xx, 3, 3); +define_dl_billboard_num3(4xx, 4, 3); +define_dl_billboard_num3(5xx, 5, 3); +define_dl_billboard_num3(6xx, 6, 3); +define_dl_billboard_num3(7xx, 7, 3); +define_dl_billboard_num3(8xx, 8, 3); +define_dl_billboard_num3(9xx, 9, 3); +define_dl_billboard_num3(x0x, 0, 4); +define_dl_billboard_num3(x1x, 1, 4); +define_dl_billboard_num3(x2x, 2, 4); +define_dl_billboard_num3(x3x, 3, 4); +define_dl_billboard_num3(x4x, 4, 4); +define_dl_billboard_num3(x5x, 5, 4); +define_dl_billboard_num3(x6x, 6, 4); +define_dl_billboard_num3(x7x, 7, 4); +define_dl_billboard_num3(x8x, 8, 4); +define_dl_billboard_num3(x9x, 9, 4); +define_dl_billboard_num3(xx0, 0, 5); +define_dl_billboard_num3(xx1, 1, 5); +define_dl_billboard_num3(xx2, 2, 5); +define_dl_billboard_num3(xx3, 3, 5); +define_dl_billboard_num3(xx4, 4, 5); +define_dl_billboard_num3(xx5, 5, 5); +define_dl_billboard_num3(xx6, 6, 5); +define_dl_billboard_num3(xx7, 7, 5); +define_dl_billboard_num3(xx8, 8, 5); +define_dl_billboard_num3(xx9, 9, 5); + ALIGNED8 const Texture texture_shadow_quarter_circle[] = { #include "textures/segment2/shadow_quarter_circle.ia8.inc.c" }; diff --git a/docs/lua/structs.md b/docs/lua/structs.md index ef939e69..a12ea74e 100644 --- a/docs/lua/structs.md +++ b/docs/lua/structs.md @@ -122,6 +122,8 @@ | macroObjectsAltered | `Pointer` <`integer`> | read-only | | musicParam | `integer` | | | musicParam2 | `integer` | | +| numRedCoins | `integer` | | +| numSecrets | `integer` | | | objectSpawnInfos | [SpawnInfo](structs.md#SpawnInfo) | | | paintingWarpNodes | [WarpNode](structs.md#WarpNode) | | | surfaceRooms | `Pointer` <`integer`> | read-only | diff --git a/src/engine/level_script.c b/src/engine/level_script.c index 57f5788c..ade7021f 100644 --- a/src/engine/level_script.c +++ b/src/engine/level_script.c @@ -20,6 +20,7 @@ #include "graph_node.h" #include "level_script.h" #include "level_misc_macros.h" +#include "macro_presets.h" #include "math_util.h" #include "surface_collision.h" #include "surface_load.h" @@ -99,6 +100,23 @@ static s32 eval_script_op(s8 op, s32 arg) { return result; } +static void area_check_red_coin_or_secret(void *arg, bool isMacroObject) { + const BehaviorScript *bhv = NULL; + if (isMacroObject) { + MacroObject index = (*((MacroObject *) arg) & 0x1FF) - 0x1F; + if (index >= 0 && index < 366) { + bhv = MacroObjectPresets[index].behavior; + } + } else { + bhv = (const BehaviorScript *) arg; + } + if (bhv == bhvRedCoin) { + gAreas[sCurrAreaIndex].numRedCoins++; + } else if (bhv == bhvHiddenStarTrigger) { + gAreas[sCurrAreaIndex].numSecrets++; + } +} + static void level_cmd_load_and_execute(void) { main_pool_push_state(); load_segment(CMD_GET(s16, 2), CMD_GET(void *, 4), CMD_GET(void *, 8), MEMORY_POOL_LEFT); @@ -384,6 +402,8 @@ static void level_cmd_begin_area(void) { sCurrAreaIndex = areaIndex; screenArea->areaIndex = areaIndex; gAreas[areaIndex].unk04 = screenArea; + gAreas[areaIndex].numRedCoins = 0; + gAreas[areaIndex].numSecrets = 0; if (node != NULL) { gAreas[areaIndex].camera = (struct Camera *) node->config.camera; @@ -506,6 +526,7 @@ static void level_cmd_place_object(void) { spawnInfo->next = gAreas[sCurrAreaIndex].objectSpawnInfos; gAreas[sCurrAreaIndex].objectSpawnInfos = spawnInfo; + area_check_red_coin_or_secret(spawnInfo->behaviorScript, false); } sCurrentCmd = CMD_NEXT; @@ -669,6 +690,7 @@ static void level_cmd_set_macro_objects(void) { MacroObject *data = segmented_to_virtual(CMD_GET(void *, 4)); s32 len = 0; while (data[len++] != MACRO_OBJECT_END()) { + area_check_red_coin_or_secret(&data[len - 1], true); len += 4; } gAreas[sCurrAreaIndex].macroObjects = alloc_only_pool_alloc(sLevelPool, len * sizeof(MacroObject)); @@ -902,6 +924,7 @@ static void level_cmd_place_object_ext(void) { spawnInfo->next = gAreas[sCurrAreaIndex].objectSpawnInfos; gAreas[sCurrAreaIndex].objectSpawnInfos = spawnInfo; + area_check_red_coin_or_secret(spawnInfo->behaviorScript, false); } sCurrentCmd = CMD_NEXT; @@ -971,6 +994,7 @@ static void level_cmd_place_object_ext2(void) { spawnInfo->next = gAreas[sCurrAreaIndex].objectSpawnInfos; gAreas[sCurrAreaIndex].objectSpawnInfos = spawnInfo; + area_check_red_coin_or_secret(spawnInfo->behaviorScript, false); } sCurrentCmd = CMD_NEXT; diff --git a/src/game/area.h b/src/game/area.h index bed88efc..21492ac2 100644 --- a/src/game/area.h +++ b/src/game/area.h @@ -85,6 +85,8 @@ struct Area /*????*/ Vec3f cachedPositions[256]; /*????*/ u32 localAreaTimer; /*????*/ u8 *macroObjectsAltered; + /*????*/ u8 numRedCoins; + /*????*/ u8 numSecrets; }; // All the transition data to be used in screen_transition.c diff --git a/src/game/behaviors/hidden_star.inc.c b/src/game/behaviors/hidden_star.inc.c index ea77d0a1..44113827 100644 --- a/src/game/behaviors/hidden_star.inc.c +++ b/src/game/behaviors/hidden_star.inc.c @@ -8,7 +8,7 @@ void bhv_hidden_star_init(void) { o->activeFlags = ACTIVE_FLAG_DEACTIVATED; } - o->oHiddenStarTriggerCounter = 5 - count; + o->oHiddenStarTriggerCounter = gCurrentArea->numSecrets - count; // We haven't interacted with a player yet. // We also don't sync this as not only is it not required @@ -34,7 +34,7 @@ void bhv_hidden_star_init(void) { void bhv_hidden_star_loop(void) { switch (o->oAction) { case 0: - if (o->oHiddenStarTriggerCounter == 5) { + if (o->oHiddenStarTriggerCounter >= gCurrentArea->numSecrets) { o->oAction = 1; } break; @@ -63,11 +63,8 @@ void bhv_hidden_star_trigger_loop(void) { if (hiddenStar != NULL) { s16 count = (count_objects_with_behavior(bhvHiddenStarTrigger) - 1); - hiddenStar->oHiddenStarTriggerCounter = 5 - count; - - if (hiddenStar->oHiddenStarTriggerCounter != 5) { - spawn_orange_number(hiddenStar->oHiddenStarTriggerCounter, 0, 0, 0); - } + hiddenStar->oHiddenStarTriggerCounter = gCurrentArea->numSecrets - count; + spawn_orange_number(hiddenStar->oHiddenStarTriggerCounter, 0, 0, 0); // Set the last person who interacted with a secret to the // parent so only they get the star cutscene. @@ -79,9 +76,11 @@ void bhv_hidden_star_trigger_loop(void) { #ifdef VERSION_JP play_sound(SOUND_MENU_STAR_SOUND, gGlobalSoundSource); #else - play_sound(SOUND_MENU_COLLECT_SECRET - + (((u8) hiddenStar->oHiddenStarTriggerCounter - 1) << 16), - gGlobalSoundSource); + if (count < 5) { + play_sound(SOUND_MENU_COLLECT_SECRET + ((4 - count) << 16), gGlobalSoundSource); + } else { + play_sound(SOUND_MENU_COLLECT_SECRET, gGlobalSoundSource); + } #endif } @@ -93,10 +92,9 @@ void bhv_hidden_star_trigger_loop(void) { } void bhv_bowser_course_red_coin_star_loop(void) { - gRedCoinsCollected = o->oHiddenStarTriggerCounter; switch (o->oAction) { case 0: - if (o->oHiddenStarTriggerCounter == 8) { + if (o->oHiddenStarTriggerCounter >= gCurrentArea->numRedCoins) { o->oAction = 1; } break; diff --git a/src/game/behaviors/red_coin.inc.c b/src/game/behaviors/red_coin.inc.c index 2797e539..7ffa8080 100644 --- a/src/game/behaviors/red_coin.inc.c +++ b/src/game/behaviors/red_coin.inc.c @@ -49,8 +49,8 @@ void bhv_red_coin_loop(void) { if (o->oInteractStatus & INT_STATUS_INTERACTED) { // ...and there is a red coin star in the level... if (o->parentObj != NULL) { - // ...increment the star's counter. - o->parentObj->oHiddenStarTriggerCounter++; + s16 redCoins = count_objects_with_behavior(bhvRedCoin) - 1; + o->parentObj->oHiddenStarTriggerCounter = gCurrentArea->numRedCoins - redCoins; // Set the last person who interacted with a red coin to the // parent so only they get the star cutscene. @@ -63,16 +63,16 @@ void bhv_red_coin_loop(void) { #ifdef VERSION_JP create_sound_spawner(SOUND_GENERAL_RED_COIN); #endif - // 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); - } + // Spawn the orange number counter + spawn_orange_number(o->parentObj->oHiddenStarTriggerCounter, 0, 0, 0); // On all versions but the JP version, each coin collected plays a higher noise. #ifndef VERSION_JP - play_sound(SOUND_MENU_COLLECT_RED_COIN - + (((u8) o->parentObj->oHiddenStarTriggerCounter - 1) << 16), - gGlobalSoundSource); + if (redCoins < 8) { + play_sound(SOUND_MENU_COLLECT_RED_COIN + ((7 - redCoins) << 16), gGlobalSoundSource); + } else { + play_sound(SOUND_MENU_COLLECT_RED_COIN, gGlobalSoundSource); + } #endif } diff --git a/src/game/behaviors/spawn_star.inc.c b/src/game/behaviors/spawn_star.inc.c index c77ed6b1..e3000cf7 100644 --- a/src/game/behaviors/spawn_star.inc.c +++ b/src/game/behaviors/spawn_star.inc.c @@ -236,7 +236,7 @@ void bhv_hidden_red_coin_star_init(void) { o->activeFlags = ACTIVE_FLAG_DEACTIVATED; } - o->oHiddenStarTriggerCounter = 8 - redCoins; + o->oHiddenStarTriggerCounter = gCurrentArea->numRedCoins - redCoins; // We haven't interacted with a player yet. // We also don't sync this as not only is it not required @@ -260,10 +260,9 @@ void bhv_hidden_red_coin_star_init(void) { } void bhv_hidden_red_coin_star_loop(void) { - gRedCoinsCollected = o->oHiddenStarTriggerCounter; switch (o->oAction) { case 0: - if (o->oHiddenStarTriggerCounter == 8) { + if (o->oHiddenStarTriggerCounter >= gCurrentArea->numRedCoins) { o->oAction = 1; } break; diff --git a/src/game/ingame_menu.c b/src/game/ingame_menu.c index 4b8ed7a9..f805375d 100644 --- a/src/game/ingame_menu.c +++ b/src/game/ingame_menu.c @@ -4,6 +4,7 @@ #include "actors/common1.h" #include "area.h" #include "audio/external.h" +#include "behavior_data.h" #include "camera.h" #include "course_table.h" #include "dialog_ids.h" @@ -15,6 +16,7 @@ #include "level_update.h" #include "levels/castle_grounds/header.h" #include "memory.h" +#include "object_helpers.h" #include "print.h" #include "save_file.h" #include "segment2.h" @@ -42,7 +44,6 @@ s16 gDialogY; // D_8032F69C #endif s16 gCutsceneMsgXOffset; s16 gCutsceneMsgYOffset; -s8 gRedCoinsCollected; extern u8 gLastCompletedCourseNum; extern u8 gLastCompletedStarNum; @@ -2308,7 +2309,6 @@ void render_hud_cannon_reticle(void) { } void reset_red_coins_collected(void) { - gRedCoinsCollected = 0; } void change_dialog_camera_angle(void) { @@ -2359,11 +2359,28 @@ void print_animated_red_coin(s16 x, s16 y) { gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW); } -void render_pause_red_coins(void) { - s8 x; +static inline void red_coins_print_glyph(s16 *x, u8 glyph, u8 width) { + u8 text[] = { glyph, GLYPH_SPACE }; + print_hud_lut_string(HUD_LUT_GLOBAL, *x, SCREEN_HEIGHT - 35, text); + *x += width; +} - for (x = 0; x < gRedCoinsCollected; x++) { - print_animated_red_coin(GFX_DIMENSIONS_FROM_RIGHT_EDGE(30) - x * 20, 16); +void render_pause_red_coins(void) { + if (gCurrentArea->numRedCoins > 0) { + u8 collected = gCurrentArea->numRedCoins - count_objects_with_behavior(bhvRedCoin); + s16 x = GFX_DIMENSIONS_RECT_FROM_LEFT_EDGE(38); + print_animated_red_coin(x - 8, 20); + gSPDisplayList(gDisplayListHead++, dl_rgba16_text_begin); + gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, gDialogTextAlpha); + red_coins_print_glyph(&x, GLYPH_MULTIPLY, 16); + if (collected >= 100) red_coins_print_glyph(&x, (collected / 100) % 10, 12); + if (collected >= 10) red_coins_print_glyph(&x, (collected / 10) % 10, 12); + red_coins_print_glyph(&x, collected % 10, 15); + red_coins_print_glyph(&x, GLYPH_MULTIPLY - 1, 15); + if (gCurrentArea->numRedCoins >= 100) red_coins_print_glyph(&x, (gCurrentArea->numRedCoins / 100) % 10, 12); + if (gCurrentArea->numRedCoins >= 10) red_coins_print_glyph(&x, (gCurrentArea->numRedCoins / 10) % 10, 12); + red_coins_print_glyph(&x, gCurrentArea->numRedCoins % 10, 15); + gSPDisplayList(gDisplayListHead++, dl_rgba16_text_end); } } diff --git a/src/game/ingame_menu.h b/src/game/ingame_menu.h index 417c2644..cd4c30db 100644 --- a/src/game/ingame_menu.h +++ b/src/game/ingame_menu.h @@ -115,7 +115,6 @@ extern s32 gDialogVariable; extern u16 gDialogTextAlpha; extern s16 gCutsceneMsgXOffset; extern s16 gCutsceneMsgYOffset; -extern s8 gRedCoinsCollected; void create_dl_identity_matrix(void); void create_dl_translation_matrix(s8 pushOp, f32 x, f32 y, f32 z); diff --git a/src/game/obj_behaviors.c b/src/game/obj_behaviors.c index c9cc5f4c..3a1a8722 100644 --- a/src/game/obj_behaviors.c +++ b/src/game/obj_behaviors.c @@ -909,11 +909,6 @@ s8 obj_lava_death(void) { */ void spawn_orange_number(s8 behParam, s16 relX, s16 relY, s16 relZ) { struct Object *orangeNumber; - - if (behParam >= 10) { - return; - } - orangeNumber = spawn_object_relative(behParam, relX, relY, relZ, o, MODEL_NUMBER, bhvOrangeNumber); if (orangeNumber == NULL) { return; } orangeNumber->oPosY += 25.0f; diff --git a/src/pc/lua/smlua_cobject_autogen.c b/src/pc/lua/smlua_cobject_autogen.c index ded641fb..c41157b5 100644 --- a/src/pc/lua/smlua_cobject_autogen.c +++ b/src/pc/lua/smlua_cobject_autogen.c @@ -48,7 +48,7 @@ static struct LuaObjectField sAnimationFields[LUA_ANIMATION_FIELD_COUNT] = { { "values", LVT_S16_P, offsetof(struct Animation, values), true, LOT_POINTER }, }; -#define LUA_AREA_FIELD_COUNT 15 +#define LUA_AREA_FIELD_COUNT 17 static struct LuaObjectField sAreaFields[LUA_AREA_FIELD_COUNT] = { // { "cachedBehaviors", LOT_???, offsetof(struct Area, cachedBehaviors), false, LOT_??? }, <--- UNIMPLEMENTED // { "cachedPositions", LOT_???, offsetof(struct Area, cachedPositions), false, LOT_??? }, <--- UNIMPLEMENTED @@ -62,6 +62,8 @@ static struct LuaObjectField sAreaFields[LUA_AREA_FIELD_COUNT] = { { "macroObjectsAltered", LVT_U8_P, offsetof(struct Area, macroObjectsAltered), true, LOT_POINTER }, { "musicParam", LVT_U16, offsetof(struct Area, musicParam), false, LOT_NONE }, { "musicParam2", LVT_U16, offsetof(struct Area, musicParam2), false, LOT_NONE }, + { "numRedCoins", LVT_U8, offsetof(struct Area, numRedCoins), false, LOT_NONE }, + { "numSecrets", LVT_U8, offsetof(struct Area, numSecrets), false, LOT_NONE }, { "objectSpawnInfos", LVT_COBJECT_P, offsetof(struct Area, objectSpawnInfos), false, LOT_SPAWNINFO }, { "paintingWarpNodes", LVT_COBJECT_P, offsetof(struct Area, paintingWarpNodes), false, LOT_WARPNODE }, { "surfaceRooms", LVT_S8_P, offsetof(struct Area, surfaceRooms), true, LOT_POINTER }, diff --git a/src/pc/network/packets/packet_level.c b/src/pc/network/packets/packet_level.c index 321a6102..fb5129e5 100644 --- a/src/pc/network/packets/packet_level.c +++ b/src/pc/network/packets/packet_level.c @@ -25,7 +25,6 @@ void network_send_level(struct NetworkPlayer* toNp, bool sendArea) { // level variables packet_write(&p, &gMarioStates[0].numCoins, sizeof(s16)); - packet_write(&p, &gRedCoinsCollected, sizeof(u8)); packet_write(&p, &gPssSlideStarted, sizeof(u8)); packet_write(&p, &gTTCSpeedSetting, sizeof(s16)); @@ -73,13 +72,4 @@ void network_receive_level(struct Packet* p) { packet_read(p, &gPssSlideStarted, sizeof(u8)); packet_read(p, &gTTCSpeedSetting, sizeof(s16)); // likely doesn't work after level load.. but it could gHudDisplay.coins = gMarioStates[0].numCoins; - - // hacky way to override red coins collected - gRedCoinsCollected = redCoinsCollected; - for (s32 i = 0; i < OBJECT_POOL_CAPACITY; i++) { - struct Object* o = &gObjectPool[i]; - if (o->behavior == bhvBowserCourseRedCoinStar || o->behavior == bhvHiddenRedCoinStar) { - o->oHiddenStarTriggerCounter = redCoinsCollected; - } - } } diff --git a/textures/segment2/custom_hud_slash.rgba16.png b/textures/segment2/custom_hud_slash.rgba16.png new file mode 100644 index 0000000000000000000000000000000000000000..d1ec0d94dccaa5e9aac6d082ab1693a117208388 GIT binary patch literal 243 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GGLLkg|>2BR0px{zZ z7srr_TW2RJ3Nb4Ru)NpYSm~x?)U`vgvktDOlAyjZQ39I*Fn z&f9H&YYi^{W{;Fs37zq9dH0R@rsV0LP5C1VI3(W*CNy#Wa`v}4+I0KwO*WSKg6b#U zrB#3E@+j5{SXpMhUq|@Kx3k|^U$=PI-G2LKjn&(qO|eheuP1HkH#~PPwP|bF?70t5 p>h0K?x7qm3xzmep^2DDNSIs{#oi}g#RiJ|zJYD@<);T3K0RYZFV($O| literal 0 HcmV?d00001