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
This commit is contained in:
Sarge-117 2022-11-22 17:04:40 -08:00 committed by GitHub
commit 9c162fc0ec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
78 changed files with 950 additions and 0 deletions

View file

@ -1330,6 +1330,7 @@ void BossDodongo_DeathCutscene(BossDodongo* this, PlayState* play) {
this->cameraAt.x = camera->at.x;
this->cameraAt.y = camera->at.y;
this->cameraAt.z = camera->at.z;
gSaveContext.sohStats.timestamp[TIMESTAMP_DEFEAT_KING_DODONGO] = GAMEPLAYSTAT_TOTAL_TIME;
break;
case 5:
tempSin = Math_SinS(this->actor.shape.rot.y - 0x1388) * 150.0f;

View file

@ -893,6 +893,7 @@ void BossFd2_CollisionCheck(BossFd2* this, PlayState* play) {
Audio_QueueSeqCmd(0x1 << 28 | SEQ_PLAYER_BGM_MAIN << 24 | 0x100FF);
Audio_PlayActorSound2(&this->actor, NA_SE_EN_VALVAISA_DEAD);
Enemy_StartFinishingBlow(play, &this->actor);
gSaveContext.sohStats.timestamp[TIMESTAMP_DEFEAT_VOLVAGIA] = GAMEPLAYSTAT_TOTAL_TIME;
} else if (damage) {
BossFd2_SetupDamaged(this, play);
this->work[FD2_DAMAGE_FLASH_TIMER] = 10;

View file

@ -2754,6 +2754,7 @@ void BossGanon_UpdateDamage(BossGanon* this, PlayState* play) {
func_80078914(&sZeroVec, NA_SE_EN_LAST_DAMAGE);
Audio_QueueSeqCmd(0x100100FF);
this->screenFlashTimer = 4;
gSaveContext.sohStats.timestamp[TIMESTAMP_DEFEAT_GANONDORF] = GAMEPLAYSTAT_TOTAL_TIME;
} else {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_GANON_DAMAGE2);
Audio_PlayActorSound2(&this->actor, NA_SE_EN_GANON_CUTBODY);

View file

@ -1670,6 +1670,8 @@ void func_8090120C(BossGanon2* this, PlayState* play) {
if ((ABS(temp_a0_2) < 0x2000) && (sqrtf(SQ(temp_f14) + SQ(temp_f12)) < 70.0f) &&
(player->swordState != 0) && (player->heldItemActionParam == PLAYER_AP_SWORD_MASTER)) {
func_80064520(play, &play->csCtx);
gSaveContext.sohStats.gameComplete = true;
gSaveContext.sohStats.timestamp[TIMESTAMP_DEFEAT_GANON] = GAMEPLAYSTAT_TOTAL_TIME;
this->unk_39E = Play_CreateSubCamera(play);
Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT);
Play_ChangeCameraStatus(play, this->unk_39E, CAM_STAT_ACTIVE);

View file

@ -1280,6 +1280,7 @@ void BossGanondrof_CollisionCheck(BossGanondrof* this, PlayState* play) {
if ((s8)this->actor.colChkInfo.health <= 0) {
BossGanondrof_SetupDeath(this, play);
Enemy_StartFinishingBlow(play, &this->actor);
gSaveContext.sohStats.timestamp[TIMESTAMP_DEFEAT_PHANTOM_GANON] = GAMEPLAYSTAT_TOTAL_TIME;
return;
}
}

View file

@ -1832,6 +1832,7 @@ void BossGoma_UpdateHit(BossGoma* this, PlayState* play) {
} else {
BossGoma_SetupDefeated(this, play);
Enemy_StartFinishingBlow(play, &this->actor);
gSaveContext.sohStats.timestamp[TIMESTAMP_DEFEAT_GOHMA] = GAMEPLAYSTAT_TOTAL_TIME;
}
this->invincibilityFrames = 10;

View file

@ -1780,6 +1780,7 @@ void BossMo_CoreCollisionCheck(BossMo* this, PlayState* play) {
if (((sMorphaTent1->csCamera == 0) && (sMorphaTent2 == NULL)) ||
((sMorphaTent1->csCamera == 0) && (sMorphaTent2 != NULL) && (sMorphaTent2->csCamera == 0))) {
Enemy_StartFinishingBlow(play, &this->actor);
gSaveContext.sohStats.timestamp[TIMESTAMP_DEFEAT_MORPHA] = GAMEPLAYSTAT_TOTAL_TIME;
Audio_QueueSeqCmd(0x1 << 28 | SEQ_PLAYER_BGM_MAIN << 24 | 0x100FF);
this->csState = MO_DEATH_START;
sMorphaTent1->drawActor = false;

View file

@ -2548,6 +2548,7 @@ void BossSst_HeadCollisionCheck(BossSst* this, PlayState* play) {
if (Actor_ApplyDamage(&this->actor) == 0) {
Enemy_StartFinishingBlow(play, &this->actor);
BossSst_HeadSetupDeath(this, play);
gSaveContext.sohStats.timestamp[TIMESTAMP_DEFEAT_BONGO_BONGO] = GAMEPLAYSTAT_TOTAL_TIME;
} else {
BossSst_HeadSetupDamage(this);
}

View file

@ -5285,6 +5285,7 @@ void BossTw_TwinrovaDamage(BossTw* this, PlayState* play, u8 damage) {
BossTw_TwinrovaSetupDeathCS(this, play);
Enemy_StartFinishingBlow(play, &this->actor);
Audio_PlayActorSound2(&this->actor, NA_SE_EN_TWINROBA_YOUNG_DEAD);
gSaveContext.sohStats.timestamp[TIMESTAMP_DEFEAT_TWINROVA] = GAMEPLAYSTAT_TOTAL_TIME;
return;
}

View file

@ -1394,6 +1394,7 @@ void BossVa_BodyPhase4(BossVa* this, PlayState* play) {
if (sFightPhase >= PHASE_DEATH) {
BossVa_SetupBodyDeath(this, play);
Enemy_StartFinishingBlow(play, &this->actor);
gSaveContext.sohStats.timestamp[TIMESTAMP_DEFEAT_BARINADE] = GAMEPLAYSTAT_TOTAL_TIME;
return;
}
this->actor.speedXZ = -10.0f;

View file

@ -268,6 +268,7 @@ void DoorKiller_Die(DoorKiller* this, PlayState* play) {
Flags_SetSwitch(play, switchFlag);
}
Actor_Kill(&this->actor);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DOOR_TRAP]++;
}
/**

View file

@ -883,6 +883,8 @@ void EnAm_Update(Actor* thisx, PlayState* play) {
dustPosScale += 60.0f;
}
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_ARMOS]++;
Actor_Kill(&this->dyna.actor);
return;
}

View file

@ -312,6 +312,7 @@ void EnAnubice_SetupDie(EnAnubice* this, PlayState* play) {
}
this->actionFunc = EnAnubice_Die;
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_ANUBIS]++;
}
void EnAnubice_Die(EnAnubice* this, PlayState* play) {

View file

@ -455,6 +455,7 @@ void EnBa_Update(Actor* thisx, PlayState* play) {
this->actor.colChkInfo.health--;
if (this->actor.colChkInfo.health == 0) {
func_809B75A0(this, play);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_PARASITIC_TENTACLE]++;
} else {
func_809B7174(this);
}

View file

@ -462,6 +462,19 @@ void EnBb_SetupDeath(EnBb* this, PlayState* play) {
}
this->action = BB_KILL;
EnBb_SetupAction(this, EnBb_Death);
if (this->actor.params == ENBB_GREEN || this->actor.params == ENBB_GREEN_BIG) {
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_GREEN]++;
}
if (this->actor.params == ENBB_BLUE) {
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_BLUE]++;
}
if (this->actor.params == ENBB_WHITE) {
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_WHITE]++;
}
if (this->actor.params == ENBB_RED) {
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_RED]++;
}
}
void EnBb_Death(EnBb* this, PlayState* play) {

View file

@ -646,6 +646,7 @@ void func_809BE26C(EnBigokuta* this, PlayState* play) {
SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 50, NA_SE_EN_OCTAROCK_BUBLE);
Item_DropCollectibleRandom(play, &this->actor, &this->actor.world.pos, 0xB0);
Actor_Kill(&this->actor);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BIG_OCTO]++;
}
}
}

View file

@ -231,6 +231,7 @@ void EnBili_SetupDie(EnBili* this) {
this->actor.flags &= ~ACTOR_FLAG_0;
this->actionFunc = EnBili_Die;
this->actor.speedXZ = 0.0f;
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BIRI]++;
}
/**

View file

@ -532,6 +532,7 @@ void EnBox_Open(EnBox* this, PlayState* play) {
if (Animation_OnFrame(&this->skelanime, 30.0f)) {
sfxId = NA_SE_EV_TBOX_UNLOCK;
gSaveContext.sohStats.count[COUNT_CHESTS_OPENED]++;
} else if (Animation_OnFrame(&this->skelanime, 90.0f)) {
sfxId = NA_SE_EV_TBOX_OPEN;
}

View file

@ -372,6 +372,7 @@ void EnBubble_Pop(EnBubble* this, PlayState* play) {
if (EnBubble_Explosion(this, play) >= 0) {
SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 60, NA_SE_EN_AWA_BREAK);
Actor_Kill(&this->actor);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SHABOM]++;
}
}

View file

@ -575,6 +575,7 @@ void func_809D00F4(EnBw* this) {
this->actor.speedXZ = 0.0f;
Audio_PlayActorSound2(&this->actor, NA_SE_EN_BUBLEWALK_DEAD);
EnBw_SetupAction(this, func_809D014C);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_TORCH_SLUG]++;
}
void func_809D014C(EnBw* this, PlayState* play) {

View file

@ -189,6 +189,7 @@ void EnCrow_SetupDamaged(EnCrow* this, PlayState* play) {
void EnCrow_SetupDie(EnCrow* this) {
this->actor.colorFilterTimer = 0;
this->actionFunc = EnCrow_Die;
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_GUAY]++;
}
void EnCrow_SetupTurnAway(EnCrow* this) {

View file

@ -406,6 +406,12 @@ void EnDekubaba_SetupPrunedSomersault(EnDekubaba* this) {
this->actor.speedXZ = this->size * 3.0f;
this->actor.flags |= ACTOR_FLAG_4 | ACTOR_FLAG_5;
this->actionFunc = EnDekubaba_PrunedSomersault;
if (this->actor.params == DEKUBABA_BIG) {
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DEKU_BABA_BIG]++;
} else {
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DEKU_BABA]++;
}
}
void EnDekubaba_SetupShrinkDie(EnDekubaba* this) {
@ -413,6 +419,12 @@ void EnDekubaba_SetupShrinkDie(EnDekubaba* this) {
0.0f, ANIMMODE_ONCE, -3.0f);
this->collider.base.acFlags &= ~AC_ON;
this->actionFunc = EnDekubaba_ShrinkDie;
if (this->actor.params == DEKUBABA_BIG) {
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DEKU_BABA_BIG]++;
} else {
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DEKU_BABA]++;
}
}
void EnDekubaba_SetupStunnedVertical(EnDekubaba* this) {

View file

@ -233,6 +233,7 @@ void EnDekunuts_SetupDie(EnDekunuts* this) {
this->actionFunc = EnDekunuts_Die;
this->actor.speedXZ = 0.0f;
Audio_PlayActorSound2(&this->actor, NA_SE_EN_NUTS_DEAD);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_MAD_SCRUB]++;
}
void EnDekunuts_Wait(EnDekunuts* this, PlayState* play) {

View file

@ -440,6 +440,7 @@ void EnDh_SetupDeath(EnDh* this) {
this->actor.params = ENDH_DEATH;
Audio_PlayActorSound2(&this->actor, NA_SE_EN_DEADHAND_DEAD);
EnDh_SetupAction(this, EnDh_Death);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DEAD_HAND]++;
}
void EnDh_Death(EnDh* this, PlayState* play) {

View file

@ -504,6 +504,7 @@ void EnDns_Burrow(EnDns* this, PlayState* play) {
}
}
Actor_Kill(&this->actor);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BUSINESS_SCRUB]++;
}
}

View file

@ -183,6 +183,7 @@ void func_809F6A20(EnDodojr* this) {
this->unk_1FC = 3;
this->actor.velocity.y = 10.0f;
}
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DODONGO_BABY]++;
}
void func_809F6AC4(EnDodojr* this) {

View file

@ -666,6 +666,7 @@ void EnDodongo_SetupDeath(EnDodongo* this, PlayState* play) {
this->actor.flags &= ~ACTOR_FLAG_0;
this->actor.speedXZ = 0.0f;
EnDodongo_SetupAction(this, EnDodongo_Death);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DODONGO]++;
}
void EnDodongo_Death(EnDodongo* this, PlayState* play) {

View file

@ -611,6 +611,7 @@ void EnEiyer_UpdateDamage(EnEiyer* this, PlayState* play) {
Enemy_StartFinishingBlow(play, &this->actor);
Audio_PlayActorSound2(&this->actor, NA_SE_EN_EIER_DEAD);
this->actor.flags &= ~ACTOR_FLAG_0;
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_STINGER]++;
}
// If underground, one hit kill

View file

@ -646,6 +646,7 @@ void EnFd_WaitForCore(EnFd* this, PlayState* play) {
} else if (this->actor.params & FLG_COREDEAD) {
this->actor.params = 0;
this->spinTimer = 30;
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_FLARE_DANCER]++;
}
}

View file

@ -223,6 +223,15 @@ void EnFirefly_SetupDie(EnFirefly* this) {
this->timer = 15;
this->actor.speedXZ = 0.0f;
this->actionFunc = EnFirefly_Die;
if (this->actor.params == KEESE_NORMAL_FLY || this->actor.params == KEESE_NORMAL_PERCH) {
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_KEESE]++;
}
if (this->actor.params == KEESE_FIRE_FLY || this->actor.params == KEESE_FIRE_PERCH) {
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_KEESE_FIRE]++;
}
if (this->actor.params == KEESE_ICE_FLY) {
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_KEESE_ICE]++;
}
}
void EnFirefly_SetupRebound(EnFirefly* this) {

View file

@ -439,6 +439,7 @@ void EnFloormas_Die(EnFloormas* this, PlayState* play) {
// Die
Item_DropCollectibleRandom(play, &this->actor, &this->actor.world.pos, 0x90);
EnFloormas_SetupSmShrink(this, play);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_FLOORMASTER]++;
}
}

View file

@ -363,6 +363,7 @@ void EnFz_ApplyDamage(EnFz* this, PlayState* play) {
vec.z = this->actor.world.pos.z;
EnFz_Damaged(this, play, &vec, 30, 10.0f);
EnFz_SetupDespawn(this, play);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_FREEZARD]++;
}
}
} else {

View file

@ -1318,6 +1318,7 @@ void EnGeldB_SetupDefeated(EnGeldB* this) {
this->actor.flags &= ~ACTOR_FLAG_0;
Audio_PlayActorSound2(&this->actor, NA_SE_EN_GERUDOFT_DEAD);
EnGeldB_SetupAction(this, EnGeldB_Defeated);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_GERUDO_THIEF]++;
}
void EnGeldB_Defeated(EnGeldB* this, PlayState* play) {

View file

@ -396,6 +396,7 @@ void EnGoma_SetupDead(EnGoma* this) {
Animation_GetLastFrame(&gObjectGolDeadTwitchingAnim), ANIMMODE_LOOP, -2.0f);
this->actionFunc = EnGoma_Dead;
this->actionTimer = 3;
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_GOHMA_LARVA]++;
}
void EnGoma_Dead(EnGoma* this, PlayState* play) {
@ -666,6 +667,7 @@ void EnGoma_UpdateHit(EnGoma* this, PlayState* play) {
EnGoma_SpawnHatchDebris(this, play);
Actor_Kill(&this->actor);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_GOHMA_LARVA]++;
}
}
}

View file

@ -428,6 +428,7 @@ void EnHintnuts_Leave(EnHintnuts* this, PlayState* play) {
Actor_ChangeCategory(play, &play->actorCtx, this->actor.child, ACTORCAT_PROP);
}
Actor_Kill(&this->actor);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DEKU_SCRUB]++;
}
}

View file

@ -628,6 +628,7 @@ void func_80A7598C(EnIk* this) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_IRONNACK_DEAD);
Audio_PlayActorSound2(&this->actor, NA_SE_EN_NUTS_CUTBODY);
EnIk_SetupAction(this, func_80A75A38);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_IRON_KNUCKLE]++;
}
void func_80A75A38(EnIk* this, PlayState* play) {
@ -1446,6 +1447,7 @@ void func_80A781CC(Actor* thisx, PlayState* play) {
}
gSaveContext.eventChkInf[3] |= 0x1000;
func_80A7735C(this, play);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_IRON_KNUCKLE_NABOORU]++;
}
}

View file

@ -180,6 +180,7 @@ void EnKarebaba_SetupDying(EnKarebaba* this) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_DEKU_JR_DEAD);
this->actor.flags |= ACTOR_FLAG_4 | ACTOR_FLAG_5;
this->actionFunc = EnKarebaba_Dying;
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_WITHERED_DEKU_BABA]++;
}
void EnKarebaba_SetupDeadItemDrop(EnKarebaba* this, PlayState* play) {

View file

@ -310,6 +310,7 @@ void EnKusa_Main(EnKusa* this, PlayState* play) {
EnKusa_SpawnFragments(this, play);
EnKusa_DropCollectible(this, play);
SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 20, NA_SE_EV_PLANT_BROKEN);
gSaveContext.sohStats.count[COUNT_BUSHES_CUT]++;
if ((this->actor.params >> 4) & 1) {
EnKusa_SpawnBugs(this, play);
@ -378,6 +379,7 @@ void EnKusa_Fall(EnKusa* this, PlayState* play) {
if (this->actor.bgCheckFlags & 0xB) {
if (!(this->actor.bgCheckFlags & 0x20)) {
SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 20, NA_SE_EV_PLANT_BROKEN);
gSaveContext.sohStats.count[COUNT_BUSHES_CUT]++;
}
EnKusa_SpawnFragments(this, play);
EnKusa_DropCollectible(this, play);

View file

@ -1400,12 +1400,14 @@ void EnMb_CheckColliding(EnMb* this, PlayState* play) {
if (this->actor.params == ENMB_TYPE_CLUB) {
if (this->actor.colChkInfo.health == 0) {
EnMb_SetupClubDead(this);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_MOBLIN_CLUB]++;
} else if (this->state != ENMB_STATE_CLUB_KNEELING) {
EnMb_SetupClubDamaged(this);
}
} else {
if (this->actor.colChkInfo.health == 0) {
EnMb_SetupSpearDead(this);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_MOBLIN]++;
} else {
EnMb_SetupSpearDamaged(this);
}

View file

@ -447,6 +447,7 @@ void EnNy_SetupDie(EnNy* this, PlayState* play) {
}
Audio_PlayActorSound2(&this->actor, NA_SE_EN_NYU_DEAD);
this->actionFunc = EnNy_Die;
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SPIKE]++;
}
}

View file

@ -253,6 +253,7 @@ void EnOkuta_SetupDie(EnOkuta* this) {
Animation_MorphToPlayOnce(&this->skelAnime, &gOctorokDieAnim, -3.0f);
this->timer = 0;
this->actionFunc = EnOkuta_Die;
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_OCTOROK]++;
}
void EnOkuta_SetupFreeze(EnOkuta* this) {

View file

@ -590,6 +590,7 @@ void EnPeehat_Larva_StateSeekPlayer(EnPeehat* this, PlayState* play) {
}
Item_DropCollectibleRandom(play, &this->actor, &this->actor.world.pos, 0x20);
Actor_Kill(&this->actor);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_PEAHAT_LARVA]++;
}
}
}
@ -759,6 +760,7 @@ void EnPeehat_StateAttackRecoil(EnPeehat* this, PlayState* play) {
1);
}
Actor_Kill(&this->actor);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_PEAHAT_LARVA]++;
} else {
EnPeehat_Ground_SetStateSeekPlayer(this);
// Is PEAHAT_TYPE_GROUNDED
@ -875,6 +877,7 @@ void EnPeehat_StateExplode(EnPeehat* this, PlayState* play) {
Item_DropCollectibleRandom(play, &this->actor, &this->actor.world.pos, 0x40);
Item_DropCollectibleRandom(play, &this->actor, &this->actor.world.pos, 0x40);
Actor_Kill(&this->actor);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_PEAHAT]++;
}
}

View file

@ -577,6 +577,11 @@ void EnPoField_Death(EnPoField* this, PlayState* play) {
255, 0, 0, 255, 1, 9, 1);
if (this->actionTimer == 1) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_EXTINCT);
if (this->actor.params == EN_PO_FIELD_BIG) {
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_POE_BIG]++;
} else {
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_POE]++;
}
}
} else if (this->actionTimer == 28) {
EnPoField_SetupSoulIdle(this, play);

View file

@ -1179,6 +1179,7 @@ void func_80ADC10C(EnPoSisters* this, PlayState* play) {
} else {
Enemy_StartFinishingBlow(play, &this->actor);
Audio_PlayActorSound2(&this->actor, NA_SE_EN_PO_SISTER_DEAD);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_POE_SISTERS]++;
}
func_80AD95D8(this);
}

View file

@ -636,6 +636,11 @@ void func_80ADF15C(EnPoh* this, PlayState* play) {
0, 0, 255, 1, 9, 1);
if (this->unk_198 == 1) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_EXTINCT);
if (this->actor.params == EN_POH_FLAT || this->actor.params == EN_POH_SHARP) {
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_POE_COMPOSER]++;
} else {
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_POE]++;
}
}
} else if (this->unk_198 == 28) {
EnPoh_SetupDeath(this, play);

View file

@ -639,6 +639,11 @@ void func_80AE3C20(EnRd* this) {
this->actor.speedXZ = 0.0f;
Audio_PlayActorSound2(&this->actor, NA_SE_EN_REDEAD_DEAD);
EnRd_SetupAction(this, func_80AE3C98);
if (this->actor.params >= -1) {
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_REDEAD]++;
} else {
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_GIBDO]++;
}
}
void func_80AE3C98(EnRd* this, PlayState* play) {

View file

@ -439,6 +439,7 @@ void func_80AE5A9C(EnReeba* this, PlayState* play) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_RIVA_DEAD);
Enemy_StartFinishingBlow(play, &this->actor);
this->actionfunc = func_80AE5C38;
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_LEEVER]++;
}
}
@ -493,6 +494,11 @@ void func_80AE5C38(EnReeba* this, PlayState* play) {
}
Actor_Kill(&this->actor);
if (this->isBig) {
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_LEEVER_BIG]++;
} else {
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_LEEVER]++;
}
}
}
}

View file

@ -381,6 +381,7 @@ void EnRr_SetupDeath(EnRr* this) {
this->actionFunc = EnRr_Death;
Audio_PlayActorSound2(&this->actor, NA_SE_EN_LIKE_DEAD);
this->actor.flags &= ~ACTOR_FLAG_0;
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_LIKE_LIKE]++;
}
void EnRr_SetupStunned(EnRr* this) {

View file

@ -456,6 +456,7 @@ void EnSb_Update(Actor* thisx, PlayState* play) {
} else {
Item_DropCollectible(play, &this->actor.world.pos, 8);
}
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SHELLBLADE]++;
Actor_Kill(&this->actor);
}
} else {

View file

@ -412,6 +412,7 @@ void func_80AFD7B4(EnSkb* this, PlayState* play) {
this->unk_283 |= 4;
EffectSsDeadSound_SpawnStationary(play, &this->actor.projectedPos, NA_SE_EN_STALKID_DEAD, 1, 1, 0x28);
EnSkb_SetupAction(this, func_80AFD880);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_STALCHILD]++;
}
void func_80AFD880(EnSkb* this, PlayState* play) {

View file

@ -733,6 +733,7 @@ void EnSkj_SariasSongKidIdle(EnSkj* this, PlayState* play) {
void EnSkj_SetupDie(EnSkj* this) {
EnSkj_ChangeAnim(this, SKJ_ANIM_DIE);
EnSkj_SetupAction(this, SKJ_ACTION_WAIT_FOR_DEATH_ANIM);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SKULL_KID]++;
}
void EnSkj_WaitForDeathAnim(EnSkj* this, PlayState* play) {

View file

@ -465,6 +465,11 @@ s32 EnSt_CheckHitBackside(EnSt* this, PlayState* play) {
this->deathTimer = 20;
this->actor.gravity = -1.0f;
Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALWALL_DEAD);
if (this->actor.params == 1) {
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SKULLTULA_BIG]++;
} else {
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SKULLTULA]++;
}
if (flags & 0x1F820) {
// arrow, fire arrow, ice arrow, light arrow,

View file

@ -346,6 +346,7 @@ s32 func_80B0C9F0(EnSw* this, PlayState* play) {
this->unk_38A = 1;
this->unk_420 *= 4.0f;
this->actionFunc = func_80B0D878;
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SKULLTULA_GOLD]++;
} else {
this->actor.shape.shadowDraw = ActorShadow_DrawCircle;
this->actor.shape.shadowAlpha = 0xFF;
@ -354,6 +355,7 @@ s32 func_80B0C9F0(EnSw* this, PlayState* play) {
this->actor.gravity = -1.0f;
this->actor.flags &= ~ACTOR_FLAG_0;
this->actionFunc = func_80B0DB00;
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SKULLWALLTULA]++;
}
Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALWALL_DEAD);

View file

@ -1525,6 +1525,7 @@ void func_80862E6C(EnTest* this, PlayState* play) {
}
Actor_Kill(&this->actor);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_STALFOS]++;
}
}
}
@ -1633,6 +1634,7 @@ void func_808633E8(EnTest* this, PlayState* play) {
}
Actor_Kill(&this->actor);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_STALFOS]++;
}
}
@ -1723,6 +1725,7 @@ void EnTest_Update(Actor* thisx, PlayState* play) {
if ((floorProperty == 5) || (floorProperty == 0xC) ||
func_80041D4C(&play->colCtx, this->actor.floorPoly, this->actor.floorBgId) == 9) {
Actor_Kill(&this->actor);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_STALFOS]++;
return;
}
}

View file

@ -764,8 +764,10 @@ void EnTite_FallApart(EnTite* this, PlayState* play) {
if (BodyBreak_SpawnParts(&this->actor, &this->bodyBreak, play, this->actor.params + 0xB)) {
if (this->actor.params == TEKTITE_BLUE) {
Item_DropCollectibleRandom(play, &this->actor, &this->actor.world.pos, 0xE0);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_TEKTITE_BLUE]++;
} else {
Item_DropCollectibleRandom(play, &this->actor, &this->actor.world.pos, 0x40);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_TEKTITE_RED]++;
}
Actor_Kill(&this->actor);
}

View file

@ -546,6 +546,7 @@ void EnTorch2_Update(Actor* thisx, PlayState* play2) {
case ENTORCH2_DEATH:
if (sAlpha - 13 <= 0) {
sAlpha = 0;
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DARK_LINK]++;
Actor_Kill(&this->actor);
return;
}

View file

@ -289,6 +289,9 @@ void EnTp_SetupDie(EnTp* this) {
}
this->actionIndex = TAILPASARAN_ACTION_DIE;
EnTp_SetupAction(this, EnTp_Die);
if (this->actor.params == TAILPASARAN_HEAD) { // Only count the head, otherwise each body segment will increment
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_TAILPASARAN]++;
}
}
/**

View file

@ -176,6 +176,7 @@ void EnTuboTrap_HandleImpact(EnTuboTrap* this, PlayState* play) {
SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 40, NA_SE_EV_BOMB_DROP_WATER);
EnTuboTrap_DropCollectible(this, play);
Actor_Kill(&this->actor);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_FLYING_POT]++;
return;
}
@ -186,6 +187,7 @@ void EnTuboTrap_HandleImpact(EnTuboTrap* this, PlayState* play) {
SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 40, NA_SE_EV_POT_BROKEN);
EnTuboTrap_DropCollectible(this, play);
Actor_Kill(&this->actor);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_FLYING_POT]++;
return;
}
@ -196,6 +198,7 @@ void EnTuboTrap_HandleImpact(EnTuboTrap* this, PlayState* play) {
SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 40, NA_SE_EV_POT_BROKEN);
EnTuboTrap_DropCollectible(this, play);
Actor_Kill(&this->actor);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_FLYING_POT]++;
return;
}
@ -207,6 +210,7 @@ void EnTuboTrap_HandleImpact(EnTuboTrap* this, PlayState* play) {
SoundSource_PlaySfxAtFixedWorldPos(play, &player2->actor.world.pos, 40, NA_SE_PL_BODY_HIT);
EnTuboTrap_DropCollectible(this, play);
Actor_Kill(&this->actor);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_FLYING_POT]++;
return;
}
}
@ -216,6 +220,7 @@ void EnTuboTrap_HandleImpact(EnTuboTrap* this, PlayState* play) {
SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 40, NA_SE_EV_POT_BROKEN);
EnTuboTrap_DropCollectible(this, play);
Actor_Kill(&this->actor);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_FLYING_POT]++;
return;
}
}

View file

@ -252,6 +252,7 @@ void EnVali_SetupDivideAndDie(EnVali* this, PlayState* play) {
this->actor.flags &= ~ACTOR_FLAG_0;
this->actor.draw = NULL;
this->actionFunc = EnVali_DivideAndDie;
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BARI]++;
}
void EnVali_SetupStunned(EnVali* this) {

View file

@ -366,6 +366,7 @@ void EnVm_SetupDie(EnVm* this) {
this->actor.speedXZ = Rand_ZeroOne() + 1.0f;
this->actor.world.rot.y = Rand_CenteredFloat(65535.0f);
EnVm_SetupAction(this, EnVm_Die);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BEAMOS]++;
}
void EnVm_Die(EnVm* this, PlayState* play) {

View file

@ -252,6 +252,7 @@ void EnWallmas_SetupDie(EnWallmas* this, PlayState* play) {
Item_DropCollectibleRandom(play, &this->actor, &this->actor.world.pos, 0xC0);
this->actionFunc = EnWallmas_Die;
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_WALLMASTER]++;
}
void EnWallmas_SetupTakePlayer(EnWallmas* this, PlayState* play) {

View file

@ -574,6 +574,7 @@ void func_80B3368C(EnWeiyer* this, PlayState* play) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_EIER_DEAD);
this->actor.flags &= ~ACTOR_FLAG_0;
func_80B32724(this);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_STINGER]++;
} else {
func_80B325A0(this);
}

View file

@ -1193,6 +1193,11 @@ void EnWf_SetupDie(EnWf* this) {
this->actionTimer = this->skelAnime.animLength;
Audio_PlayActorSound2(&this->actor, NA_SE_EN_WOLFOS_DEAD);
EnWf_SetupAction(this, EnWf_Die);
if (this->actor.params == WOLFOS_WHITE) {
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_WOLFOS_WHITE]++;
} else {
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_WOLFOS]++;
}
}
void EnWf_Die(EnWf* this, PlayState* play) {

View file

@ -111,6 +111,7 @@ void EnYukabyun_Break(EnYukabyun* this, PlayState* play) {
EffectSsHahen_SpawnBurst(play, &this->actor.world.pos, 8.0f, 0, 1300, 300, 15, OBJECT_YUKABYUN, 10,
gFloorTileEnemyFragmentDL);
Actor_Kill(&this->actor);
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_FLOOR_TILE]++;
}
void EnYukabyun_Update(Actor* thisx, PlayState* play) {

View file

@ -1921,6 +1921,12 @@ void EnZf_SetupDie(EnZf* this) {
D_80B4A1B0 = 0;
Audio_PlayActorSound2(&this->actor, NA_SE_EN_RIZA_DEAD);
EnZf_SetupAction(this, EnZf_Die);
if (this->actor.params == ENZF_TYPE_DINOLFOS) {
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DINOLFOS]++;
} else {
gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_LIZALFOS]++;
}
}
void EnZf_Die(EnZf* this, PlayState* play) {

View file

@ -188,6 +188,7 @@ void ObjTsubo_AirBreak(ObjTsubo* this, PlayState* play) {
sObjectIds[(this->actor.params >> 8) & 1], D_80BA1B8C[(this->actor.params >> 8) & 1]);
}
func_80033480(play, &this->actor.world.pos, 30.0f, 4, 20, 50, 1);
gSaveContext.sohStats.count[COUNT_POTS_BROKEN]++;
}
void ObjTsubo_WaterBreak(ObjTsubo* this, PlayState* play) {
@ -216,6 +217,7 @@ void ObjTsubo_WaterBreak(ObjTsubo* this, PlayState* play) {
(Rand_ZeroOne() * 95.0f) + 15.0f, 0, 32, 70, KAKERA_COLOR_NONE,
sObjectIds[(this->actor.params >> 8) & 1], D_80BA1B8C[(this->actor.params >> 8) & 1]);
}
gSaveContext.sohStats.count[COUNT_POTS_BROKEN]++;
}
void ObjTsubo_SetupWaitForObject(ObjTsubo* this) {

View file

@ -1460,6 +1460,12 @@ void func_808327F8(Player* this, f32 arg1) {
}
func_800F4010(&this->actor.projectedPos, sfxId, arg1);
// Gameplay stats: Count footsteps
// Only count while game isn't complete and don't count Link's idle animations or crawling in crawlspaces
if (!gSaveContext.sohStats.gameComplete && !(this->stateFlags2 & PLAYER_STATE2_28) &&
!(this->stateFlags2 & PLAYER_STATE2_18)) {
gSaveContext.sohStats.count[COUNT_STEPS]++;
}
}
void func_80832854(Player* this) {
@ -1950,6 +1956,10 @@ void func_80833A20(Player* this, s32 newSwordState) {
if ((this->swordAnimation < 0x10) || (this->swordAnimation >= 0x14)) {
func_80832698(this, voiceSfx);
}
if (this->heldItemActionParam >= PLAYER_AP_SWORD_MASTER && this->heldItemActionParam <= PLAYER_AP_SWORD_BGS) {
gSaveContext.sohStats.count[COUNT_SWORD_SWINGS]++;
}
}
this->swordState = newSwordState;
@ -5285,6 +5295,7 @@ void func_8083BC04(Player* this, PlayState* play) {
func_80835C58(play, this, func_80844708, 0);
LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, D_80853914[PLAYER_ANIMGROUP_16][this->modelAnimType],
1.25f * D_808535E8);
gSaveContext.sohStats.count[COUNT_ROLLS]++;
}
s32 func_8083BC7C(Player* this, PlayState* play) {
@ -6258,6 +6269,8 @@ s32 func_8083E5A8(Player* this, PlayState* play) {
func_80837C0C(play, this, 3, 0.0f, 0.0f, 0, 20);
this->getItemId = GI_NONE;
this->getItemEntry = (GetItemEntry) GET_ITEM_NONE;
// Gameplay stats: Increment Ice Trap count
gSaveContext.sohStats.count[COUNT_ICE_TRAPS]++;
return 1;
}
@ -8648,6 +8661,7 @@ void func_80844708(Player* this, PlayState* play) {
func_8002F7DC(&this->actor, NA_SE_PL_BODY_HIT);
func_80832698(this, NA_SE_VO_LI_CLIMB_END);
this->unk_850 = 1;
gSaveContext.sohStats.count[COUNT_BONKS]++;
return;
}
}
@ -12887,6 +12901,8 @@ void func_8084E6D4(Player* this, PlayState* play) {
func_80837C0C(play, this, 3, 0.0f, 0.0f, 0, 20);
this->getItemId = GI_NONE;
this->getItemEntry = (GetItemEntry)GET_ITEM_NONE;
// Gameplay stats: Increment Ice Trap count
gSaveContext.sohStats.count[COUNT_ICE_TRAPS]++;
}
return;
}