diff options
| author | Sarge-117 <108380086+Sarge-117@users.noreply.github.com> | 2022-11-22 17:04:40 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-11-22 20:04:40 -0500 |
| commit | 9c162fc0ecd4c2f4b7ad23bb311cd06496da9ca1 (patch) | |
| tree | 86e87eb271b5dafff1e96d3782f98c47597b1d58 /soh/src/code | |
| parent | 9cfe7bff4775e4fb7cece3208ad3d77071d71851 (diff) | |
Gameplay Stat Tracker V1 (#1986)
* First test of gathering some gameplay stats
* timer changes and other stuff
* Move code to new files + rename
* Name change - gamePlayStats
* Finish rename, remove n64ddFlag checks
* Improve item get times
* Better time tracking, more stats,
* Put button under Enhancements
* Fix merge conflict
* Add pauseCount, fix bug with rando items
* Adjust inits/declarations
* step counter
* Name change: "itemGetTime" to "timestamp"
* Tidying + CI test
* Set up array for stat counts
* Macro
#define GAMEPLAYSTAT_TOTAL_TIME (gSaveContext.gameplayStats.playTimer / 2 + gSaveContext.gameplayStats.pauseTimer / 3)
* Add boss defeat timestamps
* Add sword swings, pots broken, bushes cut
* fix int type
* Add counts for enemies defeated
Broken down by enemy, with a total
* Add ammo used
* Hide breakdowns until count > 0
* Forgot Big Octo
* Count chests opened
* Update after LUS submodule
* Enemy count spacing
* Comments
* Count 3 mini Floormasters as 1 Floormaster
+ some cleanup
* Comments
* Colour coding for timestamps on quest items
i.e. medallions/stones/songs
* Move stat into the sohStats struct
+ rearrange the counts enum for easier addition of future counts
* Some documentation + count button presses
* Stop counting button presses when Ganon defeated
* Couple bugfixes
Add count for Gerudo Thief, fix step counter counting in some situations where it shouldn't
* Fix comment
Diffstat (limited to 'soh/src/code')
| -rw-r--r-- | soh/src/code/z_kaleido_scope_call.c | 5 | ||||
| -rw-r--r-- | soh/src/code/z_parameter.c | 117 | ||||
| -rw-r--r-- | soh/src/code/z_play.c | 22 |
3 files changed, 144 insertions, 0 deletions
diff --git a/soh/src/code/z_kaleido_scope_call.c b/soh/src/code/z_kaleido_scope_call.c index 81e442d8a..5d1f6937d 100644 --- a/soh/src/code/z_kaleido_scope_call.c +++ b/soh/src/code/z_kaleido_scope_call.c @@ -56,6 +56,10 @@ void KaleidoScopeCall_Update(PlayState* play) { KaleidoMgrOverlay* kaleidoScopeOvl = &gKaleidoMgrOverlayTable[KALEIDO_OVL_KALEIDO_SCOPE]; PauseContext* pauseCtx = &play->pauseCtx; + if (!gSaveContext.sohStats.gameComplete) { + gSaveContext.sohStats.pauseTimer++; + } + if ((pauseCtx->state != 0) || (pauseCtx->debugState != 0)) { if (pauseCtx->state == 1) { if (ShrinkWindow_GetCurrentVal() == 0) { @@ -65,6 +69,7 @@ void KaleidoScopeCall_Update(PlayState* play) { pauseCtx->unk_1E4 = 0; pauseCtx->unk_1EC = 0; pauseCtx->state = (pauseCtx->state & 0xFFFF) + 1; + gSaveContext.sohStats.count[COUNT_PAUSES]++; } } else if (pauseCtx->state == 8) { HREG(80) = 7; diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 0c3afc651..f7af5b728 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -1614,6 +1614,72 @@ void func_80084BF4(PlayState* play, u16 flag) { } } +// Gameplay stat tracking: Update time the item was acquired +// (special cases for some duplicate items) +void GameplayStats_SetTimestamp(u8 item) { + + if (gSaveContext.sohStats.timestamp[item] != 0) { + return; + } + + u32 time = GAMEPLAYSTAT_TOTAL_TIME; + + // Have items in Link's pocket shown as being obtained at 0.1 seconds + if (time == 0) { + time = 1; + } + + // Count any bottled item as a bottle + if (item >= ITEM_BOTTLE && item <= ITEM_POE) { + if (gSaveContext.sohStats.timestamp[ITEM_BOTTLE] == 0) { + gSaveContext.sohStats.timestamp[ITEM_BOTTLE] = time; + } + return; + } + // Count any bombchu pack as bombchus + if (item == ITEM_BOMBCHU || (item >= ITEM_BOMBCHUS_5 && item <= ITEM_BOMBCHUS_20)) { + if (gSaveContext.sohStats.timestamp[ITEM_BOMBCHU] == 0) { + gSaveContext.sohStats.timestamp[ITEM_BOMBCHU] = time; + } + return; + } + + gSaveContext.sohStats.timestamp[item] = time; +} + +// Gameplay stat tracking: Update time the item was acquired +// (special cases for rando items) +void Randomizer_GameplayStats_SetTimestamp(uint16_t item) { + + u32 time = GAMEPLAYSTAT_TOTAL_TIME; + + // Have items in Link's pocket shown as being obtained at 0.1 seconds + if (time == 0) { + time = 1; + } + + // Count any bottled item as a bottle + if (item >= RG_EMPTY_BOTTLE && item <= RG_BOTTLE_WITH_BIG_POE) { + if (gSaveContext.sohStats.timestamp[ITEM_BOTTLE] == 0) { + gSaveContext.sohStats.timestamp[ITEM_BOTTLE] = time; + } + return; + } + // Count any bombchu pack as bombchus + if (item >= RG_BOMBCHU_5 && item <= RG_BOMBCHU_DROP) { + if (gSaveContext.sohStats.timestamp[ITEM_BOMBCHU] = 0) { + gSaveContext.sohStats.timestamp[ITEM_BOMBCHU] = time; + } + return; + } + if (item == RG_MAGIC_SINGLE) { + gSaveContext.sohStats.timestamp[ITEM_SINGLE_MAGIC] = time; + } + if (item == RG_DOUBLE_DEFENSE) { + gSaveContext.sohStats.timestamp[ITEM_DOUBLE_DEFENSE] = time; + } +} + /** * @brief Adds the given item to Link's inventory. * @@ -1631,6 +1697,9 @@ u8 Item_Give(PlayState* play, u8 item) { s16 slot; s16 temp; + // Gameplay stats: Update the time the item was obtained + GameplayStats_SetTimestamp(item); + slot = SLOT(item); if (item >= ITEM_STICKS_5) { slot = SLOT(sExtraItemBases[item - ITEM_STICKS_5]); @@ -2291,6 +2360,9 @@ u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) { uint16_t i; uint16_t slot; + // Gameplay stats: Update the time the item was obtained + Randomizer_GameplayStats_SetTimestamp(item); + slot = SLOT(item); if (item == RG_MAGIC_SINGLE) { gSaveContext.magicAcquired = true; @@ -2975,6 +3047,10 @@ s32 Health_ChangeBy(PlayState* play, s16 healthChange) { osSyncPrintf("***** 増減=%d (now=%d, max=%d) ***", healthChange, gSaveContext.health, gSaveContext.healthCapacity); + if (healthChange < 0) { + gSaveContext.sohStats.count[COUNT_DAMAGE_TAKEN] += -healthChange; + } + // If one-hit ko mode is on, any damage kills you and you cannot gain health. if (chaosEffectOneHitKO) { if (healthChange < 0) { @@ -3041,6 +3117,43 @@ void Health_RemoveHearts(s16 hearts) { void Rupees_ChangeBy(s16 rupeeChange) { gSaveContext.rupeeAccumulator += rupeeChange; + + if (rupeeChange > 0) { + gSaveContext.sohStats.count[COUNT_RUPEES_COLLECTED] += rupeeChange; + } + if (rupeeChange < 0) { + gSaveContext.sohStats.count[COUNT_RUPEES_SPENT] += -rupeeChange; + } +} + +void GameplayStats_UpdateAmmoUsed(s16 item, s16 ammoUsed) { + + switch (item) { + case ITEM_STICK: + gSaveContext.sohStats.count[COUNT_AMMO_USED_STICK] += ammoUsed; + break; + case ITEM_NUT: + gSaveContext.sohStats.count[COUNT_AMMO_USED_NUT] += ammoUsed; + break; + case ITEM_BOMB: + gSaveContext.sohStats.count[COUNT_AMMO_USED_BOMB] += ammoUsed; + break; + case ITEM_BOW: + gSaveContext.sohStats.count[COUNT_AMMO_USED_ARROW] += ammoUsed; + break; + case ITEM_SLINGSHOT: + gSaveContext.sohStats.count[COUNT_AMMO_USED_SEED] += ammoUsed; + break; + case ITEM_BOMBCHU: + gSaveContext.sohStats.count[COUNT_AMMO_USED_BOMBCHU] += ammoUsed; + break; + case ITEM_BEAN: + gSaveContext.sohStats.count[COUNT_AMMO_USED_BEAN] += ammoUsed; + break; + default: + break; + } + return; } void Inventory_ChangeAmmo(s16 item, s16 ammoChange) { @@ -3100,6 +3213,10 @@ void Inventory_ChangeAmmo(s16 item, s16 ammoChange) { } osSyncPrintf("合計 = (%d)\n", AMMO(item)); // "Total = (%d)" + + if (ammoChange < 0) { + GameplayStats_UpdateAmmoUsed(item, -ammoChange); + } } void Magic_Fill(PlayState* play) { diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c index 0203c7ca2..2cd647c79 100644 --- a/soh/src/code/z_play.c +++ b/soh/src/code/z_play.c @@ -699,6 +699,24 @@ void Play_Update(PlayState* play) { play->transitionMode = 1; } + // Gameplay stats: Count button presses + if (!gSaveContext.sohStats.gameComplete) { + if (CHECK_BTN_ALL(input[0].press.button, BTN_A)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_A]++;} + if (CHECK_BTN_ALL(input[0].press.button, BTN_B)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_B]++;} + if (CHECK_BTN_ALL(input[0].press.button, BTN_CUP)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_CUP]++;} + if (CHECK_BTN_ALL(input[0].press.button, BTN_CRIGHT)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_CLEFT]++;} + if (CHECK_BTN_ALL(input[0].press.button, BTN_CLEFT)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_CDOWN]++;} + if (CHECK_BTN_ALL(input[0].press.button, BTN_CDOWN)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_CRIGHT]++;} + if (CHECK_BTN_ALL(input[0].press.button, BTN_DUP)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_DUP]++;} + if (CHECK_BTN_ALL(input[0].press.button, BTN_DRIGHT)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_DRIGHT]++;} + if (CHECK_BTN_ALL(input[0].press.button, BTN_DDOWN)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_DDOWN]++;} + if (CHECK_BTN_ALL(input[0].press.button, BTN_DLEFT)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_DLEFT]++;} + if (CHECK_BTN_ALL(input[0].press.button, BTN_L)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_L]++;} + if (CHECK_BTN_ALL(input[0].press.button, BTN_R)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_R]++;} + if (CHECK_BTN_ALL(input[0].press.button, BTN_Z)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_Z]++;} + if (CHECK_BTN_ALL(input[0].press.button, BTN_START)) {gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_START]++;} + } + if (gTrnsnUnkState != 0) { switch (gTrnsnUnkState) { case 2: @@ -1066,6 +1084,10 @@ void Play_Update(PlayState* play) { } play->gameplayFrames++; + // Gameplay stat tracking + if (!gSaveContext.sohStats.gameComplete) { + gSaveContext.sohStats.playTimer++; + } func_800AA178(1); |
