diff --git a/include/defines.h b/include/defines.h index b33633404..60c21af83 100644 --- a/include/defines.h +++ b/include/defines.h @@ -371,7 +371,6 @@ enum PLACE { FIRST_PLACE, SECOND_PLACE, THIRD_PLACE, FOURTH_PLACE }; #define UNKNOWN_EFFECT_0x40 0x40 // #define UNKNOWN_EFFECT_0x80 0x80 // #define UNKNOWN_EFFECT_0xC 0xC // -#define UNKNOWN_EFFECT_0x10 0x10 // #define UNKNOWN_EFFECT_0x100 0x100 // #define UNKNOWN_EFFECT_0x1000 0x1000 // #define STAR_EFFECT 0x200 // being a star diff --git a/src/code_80005FD0.c b/src/code_80005FD0.c index 384eb28c3..ed8781451 100644 --- a/src/code_80005FD0.c +++ b/src/code_80005FD0.c @@ -1080,7 +1080,8 @@ void func_80007FA4(s32 arg0, Player* player, f32 arg2) { (arg2 < ((test * 18.0) / 216.0)) ? func_80038BE4(player, 6) : player_decelerate_alternative(player, 1.0f); } else if (D_80163410[arg0] == 0) { test = 35; - (arg2 < (((test ^ 0) * 18.0) / 216.0)) ? func_80038BE4(player, 2) : player_decelerate_alternative(player, 1.0f); + (arg2 < (((test ^ 0) * 18.0) / 216.0)) ? func_80038BE4(player, 2) + : player_decelerate_alternative(player, 1.0f); } else { player_decelerate_alternative(player, 1.0f); } @@ -1188,58 +1189,34 @@ void regulate_cpu_speed(s32 playerId, f32 targetSpeed, Player* player) { } } -#ifdef NON_MATCHING -// generated by m2c commit 05102b12b75400ad2be8bd0872404237b36e1702 on Feb-20-2024 -// static ? gAIDistances; /* unable to generate initializer: unknown type */ -// static ? gMarioRacewayAIDistances; /* unable to generate initializer: unknown type */ -// static ? *D_800DCBB4[0x15] = { -// &gMarioRacewayAIDistances, -// &gAIDistances, -// &gAIDistances, -// &gAIDistances, -// &gAIDistances, -// &gAIDistances, -// &gAIDistances, -// &gAIDistances, -// &gAIDistances, -// &gAIDistances, -// &gAIDistances, -// &gAIDistances, -// &gAIDistances, -// &gAIDistances, -// &gAIDistances, -// &gAIDistances, -// &gAIDistances, -// &gAIDistances, -// &gAIDistances, -// &gAIDistances, -// &gAIDistances, -// }; - -bool func_800088D8(s32 playerId, s16 lapNum, s16 currRank) { +bool func_800088D8(s32 playerId, s16 lapNum, s16 arg2) { Player* player; - f32 interp; - s16 rank; - s16 var_a0_4; - s16 var_t1; - s16 var_v0; s16* temp_a3; - s32 temp_a2; - s32 arg1_times_8; - s32 var_a0_2; s32 progress; - s32 var_a1_4; + f32 interp; + s16 var_t1; + u16* var_a0_3; + s16 temp; + s16 temp2; s32 i; + s32 var_a0; + s16 var_v0; + s16 var_a0_4; + s32* var_v1; + s16 STEMP_V1; + s16 STEMP_V0; + s16 rank; D_80163128[playerId] = -1; D_80163150[playerId] = -1; - if (gModeSelection == 1) { + if (gModeSelection == TIME_TRIALS) { return true; } - if (lapNum < MIN_LAPS) { + if (lapNum < 0) { return true; - } else if (lapNum > MAX_LAPS) { - lapNum = MAX_LAPS; + } + if (lapNum >= 4) { + lapNum = 3; } if (D_80163330[playerId] == 1) { return true; @@ -1248,86 +1225,106 @@ bool func_800088D8(s32 playerId, s16 lapNum, s16 currRank) { if (player->type & 0x4000) { return true; } - arg1_times_8 = lapNum * 8; - temp_a3 = &CM_GetProps()->AIDistance[arg1_times_8]; - if (currRank == 0) { + + temp_a3 = &CM_GetProps()->AIDistance[lapNum * 8]; + if (arg2 == 0) { if (gDemoMode == 1) { - temp_a2 = gNumPathPointsTraversed[playerId] - gNumPathPointsTraversed[D_80164378[7]]; - if (temp_a2 < 0) { - temp_a2 = -temp_a2; + STEMP_V0 = gNumPathPointsTraversed[playerId]; + STEMP_V1 = gNumPathPointsTraversed[D_80164378[7]]; + progress = STEMP_V0 - STEMP_V1; + if (progress < 0) { + progress = -progress; } - if (arg1_times_8 < 24) { + if (lapNum < 3) { + STEMP_V0 = temp_a3[0]; + STEMP_V1 = temp_a3[8]; interp = gLapCompletionPercentByPlayerId[playerId]; - D_80163150[playerId] = temp_a3[8] * interp + temp_a3[0] * (1.0f - interp); + var_a0 = (STEMP_V1 * interp) + (STEMP_V0 * (1.0f - interp)); } else { - D_80163150[playerId] = temp_a3[0]; + var_a0 = temp_a3[0]; } - if (D_80163150[playerId] < temp_a2 && player->speed / 18.0f * 216.0f >= 20.0f) { + D_80163150[playerId] = var_a0; + if ((D_80163150[playerId] < progress) && (((player->speed / 18.0f) * 216.0f) >= 20.0f)) { return false; } return true; } - progress = gNumPathPointsTraversed[playerId] - gNumPathPointsTraversed[gBestRankedHumanPlayer]; - rank = gGPCurrentRaceRankByPlayerId[2 + (gBestRankedHumanPlayer * 4)]; - if (gPathCountByPathIndex[0] * 2 / 3 < progress && rank >= 6) { - progress = gNumPathPointsTraversed[playerId] - gNumPathPointsTraversed[gLapCountByPlayerId[-26 + rank * 2]]; + + STEMP_V0 = gNumPathPointsTraversed[playerId]; + STEMP_V1 = gNumPathPointsTraversed[gBestRankedHumanPlayer]; + progress = STEMP_V0 - STEMP_V1; + rank = gGPCurrentRaceRankByPlayerId[gBestRankedHumanPlayer]; + if (((((gPathCountByPathIndex[0] * 2) / 3)) < progress) && ((rank) >= 6)) { + STEMP_V0 = gNumPathPointsTraversed[playerId]; + STEMP_V1 = temp = gNumPathPointsTraversed[D_80164378[rank - 1]]; + progress = STEMP_V0 - STEMP_V1; } if (progress < 0) { progress = -progress; } - if (arg1_times_8 < 24) { + if (lapNum < 3) { + STEMP_V0 = temp_a3[0]; + STEMP_V1 = temp_a3[8]; interp = gLapCompletionPercentByPlayerId[playerId]; - var_a0_2 = temp_a3[8] * interp + temp_a3[0] * (1.0f - interp); + var_a0 = (STEMP_V1 * interp) + (STEMP_V0 * (1.0f - interp)); } else { - var_a0_2 = temp_a3[0]; + var_a0 = temp_a3[0]; } - D_80163150[playerId] = (gCCSelection + 1) * var_a0_2; - if (D_80163150[playerId] < progress && player->speed / 18.0f * 216.0f >= 20.0f) { + D_80163150[playerId] = var_a0 = (gCCSelection + 1) * var_a0; + if ((var_a0 < progress) && (((player->speed / 18.0f) * 216.0f) >= 20.0f)) { return false; } return true; - } else { - var_a1_4 = gNumPathPointsTraversed[(s16) *D_80163344] - gNumPathPointsTraversed[playerId]; - if (var_a1_4 < 0) { - var_a1_4 = -var_a1_4; + } + + temp2 = D_80163344[0]; + STEMP_V0 = gNumPathPointsTraversed[playerId]; + STEMP_V1 = gNumPathPointsTraversed[temp2]; + progress = STEMP_V1 - STEMP_V0; + if (progress < 0) { + progress = -progress; + } + + var_v0 = 0; + for (i = 0; i < 2; i++) { + if (gGPCurrentRaceRankByPlayerId[D_80163344[i] & 0xFFFF] < arg2) { + var_v0++; } - var_v0 = 0; - for (i = 0; i < 2; i++) { - if (gGPCurrentRaceRankByPlayerId[D_80163344[i]] < currRank) { - var_v0++; - } - } - var_a0_4 = 0; - for (i = 0; i < gPlayerCount; i++) { - if (gGPCurrentRaceRankByPlayerId[i] < currRank) { - var_a0_4++; - } - } - var_t1 = (currRank - var_v0) - var_a0_4; - if (var_v0 > 0 || var_a0_4 > 0) { - var_t1++; - } - D_80164538[playerId] = var_t1; - if (var_t1 < 0 || var_t1 >= 8) { - return false; - } - if (arg1_times_8 < 24) { - temp_a3 = &temp_a3[var_t1]; - interp = gLapCompletionPercentByPlayerId[playerId]; - D_80163150[playerId] = temp_a3[8] * interp + temp_a3[0] * (1.0f - interp); - } else { - D_80163150[playerId] = temp_a3[var_t1]; - } - D_80163128[playerId] = var_a1_4; - if (D_80163150[playerId] < var_a1_4) { - return true; + } + + var_a0_4 = 0; + for (i = 0; i < gPlayerCount; i++) { + if (gGPCurrentRaceRankByPlayerId[i] < arg2) { + var_a0_4++; } + } + + // FAKE + var_t1 = (arg2 - (var_v0 & 0xFFFF)) - var_a0_4; + arg2 -= var_v0; + + if ((var_v0 > 0) || (var_a0_4 > 0)) { + var_t1++; + } + D_80164538[playerId] = var_t1; + if ((var_t1 < 0) || (var_t1 >= 8)) { return false; } + if (lapNum < 3) { + STEMP_V0 = temp_a3[var_t1 + 0]; + STEMP_V1 = temp_a3[var_t1 + 8]; + interp = gLapCompletionPercentByPlayerId[playerId]; + var_a0 = (STEMP_V1 * interp) + (STEMP_V0 * (1.0f - interp)); + } else { + var_a0 = temp_a3[var_t1]; + } + D_80163128[playerId] = progress; + D_80163150[playerId] = var_a0; + if (var_a0 < progress) { + return true; + } + return false; } -#else -GLOBAL_ASM("asm/non_matchings/code_80005FD0/func_800088D8.s") -#endif void set_current_path(s32 pathIndex) { gCurrentTrackPath = gTrackPaths[pathIndex]; @@ -1445,59 +1442,55 @@ f32 func_80009258(UNUSED s32 playerId, f32 arg1, f32 arg2) { return gCourseTimer - ((COURSE_TIMER_ITER_f * temp_f2) / (temp_f2 + temp_f12)); } -#ifdef NON_MATCHING -// Weird stack issue, can't figure out how to get rid of it void update_player_path_completion(s32 playerId, Player* player) { - f32 tempPos0; - f32 tempPos1; - f32 tempPos2; + f32 playerX; + f32 playerY; + f32 playerZ; s32 var_v0; - s32 var_v1; - f32 someTemp0; - UNUSED s16 stackPadding0; - s16 var_t0; - UNUSED s32 stackPadding1; + UNUSED s16 pad; + f32 previousPlayerZ; - tempPos0 = player->pos[0]; - tempPos1 = player->pos[1]; - tempPos2 = player->pos[2]; - gIsPlayerNewPathPoint = 0; + playerX = player->pos[0]; + playerY = player->pos[1]; + playerZ = player->pos[2]; + previousPlayerZ = gPreviousPlayerZ[playerId]; + gIsPlayerNewPathPoint = false; D_80163240[playerId] = 0; - sSomeNearestPathPoint = update_player_path(tempPos0, tempPos1, tempPos2, gNearestPathPointByPlayerId[playerId], - player, playerId, gPlayerPathIndex); + sSomeNearestPathPoint = update_player_path(playerX, playerY, playerZ, gNearestPathPointByPlayerId[playerId], player, + playerId, gPlayerPathIndex); gCurrentNearestPathPoint = sSomeNearestPathPoint; if (gNearestPathPointByPlayerId[playerId] != sSomeNearestPathPoint) { gNearestPathPointByPlayerId[playerId] = sSomeNearestPathPoint; - gIsPlayerNewPathPoint = 1; + gIsPlayerNewPathPoint = true; update_player_completion(playerId); } if (IsPodiumCeremony()) { update_player_position_factor(playerId, sSomeNearestPathPoint, gPlayerPathIndex); return; } - if ((sSomeNearestPathPoint < 0x14) || ((gPathCountByPathIndex[gPlayerPathIndex] - 0x14) < sSomeNearestPathPoint) || + if ((sSomeNearestPathPoint < 20) || ((gPathCountByPathIndex[gPlayerPathIndex] - 20) < sSomeNearestPathPoint) || (IsKalimariDesert())) { - var_v1 = 0; - var_t0 = 0; + s16 var_v1 = 0; + s16 var_t0 = 0; if (IsKalimariDesert()) { D_801634EC = 0; if (player->effects & 0x200) { D_801634EC = 1; } if (gIsMirrorMode != 0) { - if (tempPos0 < 300.0f) { + if (playerX < 300.0f) { var_v1 = 1; var_t0 = 1; - } else if ((tempPos0 < 1300.0f) && (gLapCountByPlayerId[playerId] < 2) && ((D_801634EC == 1))) { + } else if ((playerX < 1300.0f) && (gLapCountByPlayerId[playerId] < 2) && ((D_801634EC == 1))) { var_v1 = 1; var_t0 = 1; } } else { - if (tempPos0 > -300.0f) { + if (playerX > -300.0f) { var_v1 = 1; var_t0 = 1; } else { - if ((tempPos0 > -1300.0f) && (gLapCountByPlayerId[playerId] < 2) && (D_801634EC == 1)) { + if ((playerX > -1300.0f) && (gLapCountByPlayerId[playerId] < 2) && (D_801634EC == 1)) { var_v1 = 1; var_t0 = 1; } @@ -1507,45 +1500,45 @@ void update_player_path_completion(s32 playerId, Player* player) { var_v1 = 1; var_t0 = 1; } - someTemp0 = gPreviousPlayerZ[playerId]; - if ((var_v1 != 0) && (tempPos2 <= gPathStartZ)) { - if (gPathStartZ < someTemp0) { + previousPlayerZ = gPreviousPlayerZ[playerId]; + if ((var_v1 != 0) && (playerZ <= gPathStartZ)) { + if (gPathStartZ < previousPlayerZ) { gLapCountByPlayerId[playerId]++; - if ((gModeSelection == 0) && (gLapCountByPlayerId[playerId] == 5)) { + if ((gModeSelection == GRAND_PRIX) && (gLapCountByPlayerId[playerId] == 5)) { if (gGPCurrentRaceRankByPlayerIdDup[playerId] == 7) { - for (var_v0 = 0; var_v0 < 8; var_v0++) { - gLapCountByPlayerId[var_v0]--; - } + // clang-format off + for (var_v0 = 0; var_v0 < NUM_PLAYERS; var_v0++) { gLapCountByPlayerId[var_v0]--; } // has to be one line to match + // clang-format on } } D_80163240[playerId] = 1; update_player_completion(playerId); reset_cpu_behaviour(playerId); cpu_ItemStrategy[playerId].numItemUse = 0; - if ((D_8016348C == 0) && !(player->type & 0x800)) { - gTimePlayerLastTouchedFinishLine[playerId] = func_80009258(playerId, someTemp0, tempPos2); + if ((D_8016348C == 0) && !(player->type & PLAYER_CINEMATIC_MODE)) { + gTimePlayerLastTouchedFinishLine[playerId] = func_80009258(playerId, previousPlayerZ, playerZ); } } } - if ((var_t0 != 0) && (someTemp0 <= gPathStartZ) && (gPathStartZ < tempPos2)) { + if ((var_t0 != 0) && (previousPlayerZ <= gPathStartZ) && (gPathStartZ < playerZ)) { gLapCountByPlayerId[playerId]--; update_player_completion(playerId); } } - gPreviousPlayerZ[playerId] = tempPos2; - if ((IsYoshiValley()) && (gIsPlayerNewPathPoint == 1)) { + gPreviousPlayerZ[playerId] = playerZ; + if ((IsYoshiValley()) && (gIsPlayerNewPathPoint == true)) { yoshi_valley_cpu_path(playerId); - if (((player->type & 0x4000) == 0) || (player->type & 0x1000)) { + if (((player->type & PLAYER_HUMAN) == 0) || (player->type & PLAYER_CPU)) { update_cpu_path_completion(playerId, player); } } - if ((player->type & 0x4000) && !(player->type & 0x1000)) { + if ((player->type & PLAYER_HUMAN) && !(player->type & PLAYER_CPU)) { detect_wrong_player_direction(playerId, player); - if ((gModeSelection == 0) && (gPlayerCount == 2) && (playerId == 0)) { - if (gGPCurrentRaceRankByPlayerIdDup[0] < gGPCurrentRaceRankByPlayerIdDup[1]) { - gBestRankedHumanPlayer = 0; + if ((gModeSelection == GRAND_PRIX) && (gPlayerCount == 2) && (playerId == 0)) { + if (gGPCurrentRaceRankByPlayerIdDup[PLAYER_ONE] < gGPCurrentRaceRankByPlayerIdDup[PLAYER_TWO]) { + gBestRankedHumanPlayer = PLAYER_ONE; } else { - gBestRankedHumanPlayer = 1; + gBestRankedHumanPlayer = PLAYER_TWO; } } } else { @@ -1553,9 +1546,6 @@ void update_player_path_completion(s32 playerId, Player* player) { } update_player_position_factor(playerId, sSomeNearestPathPoint, gPlayerPathIndex); } -#else -GLOBAL_ASM("asm/non_matchings/code_80005FD0/update_player_path_completion.s") -#endif void update_vehicles(void) { s32 i; @@ -1606,57 +1596,26 @@ void update_player_timer_sound(s32 playerId, UNUSED Player* unused) { } } -#ifdef NON_MATCHING -#define FAKEMATCH1 0 -#define FAKEMATCH2 0 -// https://decomp.me/scratch/uJCh3 -// Lots of register allocation differences, but messing around seems to suggest they stem from 2 specific areas -// MISMATCH1: something about the loading of `playerId` is off -// MISMATCH2: something about the handling of the math is off. Not sure exactly what though -// MISMATCH3: there's a small instruction ordering issue concerning `gCourseMaxX`. No idea what to do about it -// FAKEMATCH1 is the best improvement I've seen yet, MISMATCH2/3 become the only issues. - void update_player(s32 playerId) { - UNUSED s32 stackPadding00; - UNUSED s32 stackPadding01; - UNUSED s32 stackPadding02; - UNUSED s32 stackPadding03; - UNUSED s32 stackPadding04; - UNUSED s32 stackPadding05; - UNUSED s32 stackPadding06; - UNUSED s32 stackPadding07; - UNUSED s32 stackPadding08; - UNUSED s32 stackPadding09; - UNUSED s32 stackPadding0A; - UNUSED s32 stackPadding0B; - UNUSED s32 stackPadding0C; - UNUSED s32 stackPadding0D; + UNUSED s32 pad[14]; s16 var_a0_2; - s16 var_a1; - UNUSED s32 stackPadding0E; - UNUSED s32 stackPadding0F; - UNUSED s32 stackPadding10; - UNUSED s32 stackPadding11; - UNUSED s32 stackPadding12; - UNUSED s32 stackPadding13; - UNUSED s32 stackPadding14; - UNUSED s32 stackPadding15; - UNUSED s32 stackPadding16; - UNUSED s32 stackPadding17; - UNUSED s32 stackPadding18; - u16 stackPadding19; - u16 stackPadding1A; - f32 temp_f0; - f32 temp_f2; - s16 var_a2; - s16 var_v1; - s32 temp_f6; + s16 newAngle; + u16 pathIndex; + + f32 distX; + f32 minAngle; + + s16 angle; + s16 steeringSensitivity; + + s32 maxAngle; Player* player; - TrackPathPoint* waypoint; - f32 athing = 1.5f; + UNUSED s32 pad3[10]; + TrackPathPoint* pathPoint; + f32 onePointFive = 1.5f; player = &gPlayers[playerId]; - if (CM_GetProps()->AIMaximumSeparation >= 0.0f) { + if ((s32) CM_GetProps()->AIMaximumSeparation >= 0) { D_80163100[playerId] += 1; if (playerId == 0) { gIncrementUpdatePlayer++; @@ -1664,57 +1623,59 @@ void update_player(s32 playerId) { D_80163488 += 1; } } - if (!(player->type & 0x8000)) { - gNumPathPointsTraversed[playerId] = -0x00000014; + if (!(player->type & PLAYER_EXISTS)) { + gNumPathPointsTraversed[playerId] = -20; gCourseCompletionPercentByPlayerId[playerId] = -1000.0f; gLapCompletionPercentByPlayerId[playerId] = -1000.0f; return; } D_801633E0[playerId] = 0; - if (player->pos[0] < gCourseMinX) { - D_801633E0[playerId] = 1; - } - if (gCourseMaxX < player->pos[0]) { - D_801633E0[playerId] = 2; - } - if (player->pos[2] < gCourseMinZ) { - D_801633E0[playerId] = 3; - } - // MISMATCH3 - if (gCourseMaxZ < player->pos[2]) { - D_801633E0[playerId] = 4; - } + // clang-format off + if (player->pos[0] < gCourseMinX) { D_801633E0[playerId] = 1; } + if (gCourseMaxX < player->pos[0]) { D_801633E0[playerId] = 2; } + if (player->pos[2] < gCourseMinZ) { D_801633E0[playerId] = 3; } + if (gCourseMaxZ < player->pos[2]) { D_801633E0[playerId] = 4; } + // clang-format on + if (!(player->unk_0CA & 2) && !(player->unk_0CA & 8)) { gPlayerPathIndex = gPathIndexByPlayerId[playerId]; set_current_path(gPlayerPathIndex); - // if (IsKalimariDesert()) { + + // Changed to allow spawning vehicles in any track + // Collision is handled in the vehicles class now + + // switch (gCurrentCourseId) { /* irregular */ + // case COURSE_KALIMARI_DESERT: CM_VehicleCollision(playerId, player); // handle_trains_interactions(playerId, player); if (playerId == 0) { CM_CrossingTrigger(); // func_80013054(); } - //} - if (IsDkJungle()) { - // handle_paddle_boats_interactions(player); - } else if (IsToadsTurnpike()) { - handle_box_trucks_interactions(playerId, player); - handle_school_buses_interactions(playerId, player); - handle_tanker_trucks_interactions(playerId, player); - handle_cars_interactions(playerId, player); - } - if (player->type & 0x800) { - player->effects &= ~0x00400000; - player->unk_044 &= ~0x0001; + // break; + // case COURSE_DK_JUNGLE: + // handle_paddle_boats_interactions(player); + // break; + // case COURSE_TOADS_TURNPIKE: + // handle_box_trucks_interactions(playerId, player); + // handle_school_buses_interactions(playerId, player); + // handle_tanker_trucks_interactions(playerId, player); + // handle_cars_interactions(playerId, player); + // break; + // } + if (player->type & PLAYER_CINEMATIC_MODE) { + player->effects &= ~REVERSE_EFFECT; + player->unk_044 &= ~1; } update_player_path_completion(playerId, player); if ((!IsPodiumCeremony()) && ((D_80163240[playerId] == 1) || (playerId == 0))) { set_places(); } - if (player->type & 0x1000) { - if ((gIsPlayerNewPathPoint == 1) && (!IsPodiumCeremony())) { + if (player->type & PLAYER_CPU) { + if ((gIsPlayerNewPathPoint == true) && (!IsPodiumCeremony())) { cpu_behaviour(playerId); } + // one update it try to use an item, the other it doesn't if ((playerId & 1) != (gIncrementUpdatePlayer & 1)) { cpu_use_item_strategy(playerId); } @@ -1728,11 +1689,11 @@ void update_player(s32 playerId) { case 0: /* switch 1 */ break; } - D_801631E0[playerId] = 0; - if ((player->effects & 0x1000) && (!IsPodiumCeremony())) { - D_801631E0[playerId] = 1; + D_801631E0[playerId] = false; + if ((player->effects & UNKNOWN_EFFECT_0x1000) && (!IsPodiumCeremony())) { + D_801631E0[playerId] = true; } - if ((D_801646CC == 1) || (player->type & 0x800) || (IsPodiumCeremony())) { + if ((D_801646CC == 1) || (player->type & PLAYER_CINEMATIC_MODE) || (IsPodiumCeremony())) { if (!IsToadsTurnpike()) { gPlayerTrackPositionFactorInstruction[playerId].target = 0.0f; } @@ -1742,13 +1703,12 @@ void update_player(s32 playerId) { gPlayerTrackPositionFactorInstruction[playerId].target = 0.0f; gPlayerTrackPositionFactorInstruction[playerId].unkC = 0.0f; } - // gNearestPathPointByPlayerId[playerId] might need to be saved to a temp gPlayerPathY[playerId] = gTrackPaths[gPlayerPathIndex][gNearestPathPointByPlayerId[playerId]].posY + 4.3f; - if ((D_801631F8[playerId] == 1) && (D_801631E0[playerId] == 0)) { + if ((D_801631F8[playerId] == 1) && (D_801631E0[playerId] == false)) { set_player_height(player); } - if (D_801631E0[playerId] == 1) { + if (D_801631E0[playerId] == true) { player->pos[1] = gPlayerPathY[playerId]; } D_801631F8[playerId] = D_801631E0[playerId]; @@ -1764,7 +1724,22 @@ void update_player(s32 playerId) { // update_player_track_position_factor_from_cars(playerId); } - if (D_801631E0[playerId] == 1) { + // switch (gCurrentCourseId) { + // case COURSE_YOSHI_VALLEY: + // case COURSE_AWARD_CEREMONY: + // gPlayerTrackPositionFactorInstruction[playerId].target = 0.0f; + // break; + // default: + // break; + // case COURSE_TOADS_TURNPIKE: + // update_player_track_position_factor_from_box_trucks(playerId); + // update_player_track_position_factor_from_buses(playerId); + // update_player_track_position_factor_from_tanker_truck(playerId); + // update_player_track_position_factor_from_cars(playerId); + // break; + // } + + if (D_801631E0[playerId] == true) { D_801630E8[playerId] = 0; player->effects &= ~0x10; if ((playerId & 1) != (gIncrementUpdatePlayer & 1)) { @@ -1785,18 +1760,19 @@ void update_player(s32 playerId) { } CM_AICrossingBehaviour(playerId); // check_ai_crossing_distance(playerId); + cpu_track_position_factor(playerId); determine_ideal_cpu_position_offset(playerId, gCurrentNearestPathPoint); - temp_f0 = gOffsetPosition[0] - player->pos[0]; - temp_f2 = gOffsetPosition[2] - player->pos[2]; + distX = gOffsetPosition[0] - player->pos[0]; + minAngle = gOffsetPosition[2] - player->pos[2]; if (!(player->effects & 0x80) && !(player->effects & 0x40) && !(player->effects & 0x800)) { - if (((temp_f0 * temp_f0) + (temp_f2 * temp_f2)) > 6400.0f) { + if (((distX * distX) + (minAngle * minAngle)) > 6400.0f) { if (gPlayerPathIndex == 0) { func_8000B140(playerId); if (D_80162FF8[playerId] > 0) { - stackPadding1A = gCurrentNearestPathPoint + 5; - stackPadding1A %= gSelectedPathCount; - set_track_offset_position(stackPadding1A, D_80163090[playerId], gPlayerPathIndex); + pathIndex = gCurrentNearestPathPoint + 5; + pathIndex %= gSelectedPathCount; + set_track_offset_position(pathIndex, D_80163090[playerId], gPlayerPathIndex); } } player->rotation[1] = -get_angle_between_two_vectors(player->pos, gOffsetPosition); @@ -1814,55 +1790,50 @@ void update_player(s32 playerId) { player->effects |= DRIFTING_EFFECT; } if (D_801630E8[playerId] != 0) { - sPlayerAngle[playerId] = -get_angle_between_two_vectors(&player->oldPos[0], player->pos); + sPlayerAngle[playerId] = -get_angle_between_two_vectors(player->oldPos, player->pos); var_a0_2 = (gCurrentPathPointExpectedRotationPath[(sSomeNearestPathPoint + 2) % gSelectedPathCount] * 0x168) / 65535; - var_a1 = (sPlayerAngle[playerId] * 0x168) / 65535; + newAngle = (sPlayerAngle[playerId] * 0x168) / 65535; if (var_a0_2 < -0xB4) { var_a0_2 += 0x168; } if (var_a0_2 > 0xB4) { var_a0_2 -= 0x168; } - if (var_a1 < -0xB4) { - var_a1 += 0x168; + if (newAngle < -0xB4) { + newAngle += 0x168; } - if (var_a1 > 0xB4) { - var_a1 -= 0x168; + if (newAngle > 0xB4) { + newAngle -= 0x168; } - var_v1 = var_a0_2 - var_a1; - if (var_v1 < -0xB4) { - var_v1 += 0x168; + steeringSensitivity = var_a0_2 - newAngle; + if (steeringSensitivity < -0xB4) { + steeringSensitivity += 0x168; } - if (var_v1 > 0xB4) { - var_v1 -= 0x168; + if (steeringSensitivity > 0xB4) { + steeringSensitivity -= 0x168; } switch (D_801630E8[playerId]) { case -1: - if (var_v1 > 5) { + if (steeringSensitivity > 5) { D_801630E8[playerId] = 0; - player->effects &= ~0x10; + player->effects &= ~DRIFTING_EFFECT; } break; case 1: - if (var_v1 < -5) { + if (steeringSensitivity < -5) { D_801630E8[playerId] = 0; - player->effects &= ~0x10; + player->effects &= ~DRIFTING_EFFECT; } break; default: break; } } - // MISMATCH1 -#if FAKEMATCH2 == 1 - stackPadding00 = (playerId & 1) != (gIncrementUpdatePlayer & 1); - if (stackPadding00) { -#else + if ((playerId & 1) != (gIncrementUpdatePlayer & 1)) { -#endif apply_cpu_turn(player, gPreviousAngleSteering[playerId]); regulate_cpu_speed(playerId, gPreviousCpuTargetSpeed[playerId], player); return; @@ -1870,39 +1841,33 @@ void update_player(s32 playerId) { gIsPlayerInCurve[playerId] = are_in_curve(playerId, sSomeNearestPathPoint); determine_ideal_cpu_position_offset(playerId, sSomeNearestPathPoint); if (!IsPodiumCeremony()) { - if (gNumPathPointsTraversed[playerId] < 0xB) { - stackPadding1A = gCurrentNearestPathPoint; + if (gNumPathPointsTraversed[playerId] <= 10) { + pathIndex = gCurrentNearestPathPoint; if ((gNumPathPointsTraversed[playerId] > 0) && (IsToadsTurnpike())) { - stackPadding1A += 0x14; - stackPadding1A %= gSelectedPathCount; - set_track_offset_position(stackPadding1A, 0.0f, 0); + pathIndex += 20; + pathIndex %= gSelectedPathCount; + set_track_offset_position(pathIndex, 0.0f, 0); gPlayerTrackPositionFactorInstruction[playerId].target = 0.0f; } else { - stackPadding1A += 8; - stackPadding1A %= gSelectedPathCount; - set_track_offset_position(stackPadding1A, gTrackPositionFactor[playerId], gPlayerPathIndex); + pathIndex += 8; + pathIndex %= gSelectedPathCount; + set_track_offset_position(pathIndex, gTrackPositionFactor[playerId], gPlayerPathIndex); gPlayerTrackPositionFactorInstruction[playerId].current = gTrackPositionFactor[playerId]; } } if ((D_80162FD0 == 1) && (D_80162FF8[playerId] == 0)) { - stackPadding1A = gCurrentNearestPathPoint + 7; - stackPadding1A %= gSelectedPathCount; - set_track_offset_position(stackPadding1A, -0.7f, gPlayerPathIndex); + pathIndex = gCurrentNearestPathPoint + 7; + pathIndex %= gSelectedPathCount; + set_track_offset_position(pathIndex, -0.7f, gPlayerPathIndex); } + if (gPlayerPathIndex == 0) { func_8000B140(playerId); if (D_80162FF8[playerId] > 0) { - stackPadding1A = gCurrentNearestPathPoint + 5; -#if FAKEMATCH1 == 1 - if (1) {} - if (1) {} - if (1) {} - if (1) {} - if (1) {} - if (1) {} -#endif - stackPadding1A %= gSelectedPathCount; - set_track_offset_position(stackPadding1A, D_80163090[playerId], gPlayerPathIndex); + pathIndex = gCurrentNearestPathPoint + 5; + + pathIndex %= gSelectedPathCount; + set_track_offset_position(pathIndex, D_80163090[playerId], gPlayerPathIndex); } } } @@ -1913,80 +1878,75 @@ void update_player(s32 playerId) { gOffsetPosition[2] = D_80163438[playerId]; break; case 4: /* switch 3 */ - waypoint = &gTrackPaths[playerId][(gNearestPathPointByPlayerId[playerId] + 0xA) % - gPathCountByPathIndex[playerId]]; - gOffsetPosition[0] = waypoint->posX; - gOffsetPosition[2] = waypoint->posZ; + pathPoint = &gTrackPaths[playerId][(gNearestPathPointByPlayerId[playerId] + 0xA) % + gPathCountByPathIndex[playerId]]; + gOffsetPosition[0] = pathPoint->posX; + gOffsetPosition[2] = pathPoint->posZ; break; } } - gOffsetPosition[0] = (gPreviousPlayerAiOffsetX[playerId] + gOffsetPosition[0]) * 0.5f; - gOffsetPosition[2] = (gPreviousPlayerAiOffsetZ[playerId] + gOffsetPosition[2]) * 0.5f; + gOffsetPosition[0] = (gPreviousPlayerAiOffsetX[playerId] + gOffsetPosition[0]) * 0.5f; // average + gOffsetPosition[2] = (gPreviousPlayerAiOffsetZ[playerId] + gOffsetPosition[2]) * 0.5f; // average gPreviousPlayerAiOffsetX[playerId] = gOffsetPosition[0]; gPreviousPlayerAiOffsetZ[playerId] = gOffsetPosition[2]; - temp_f2 = athing * 182.0f; - temp_f6 = -athing * 182.0f; - // MISMATCH2 - // This fixes part of the register allocation problems, makes fixing others - // harder though. Needs more investigation - // var_a2 = (-get_angle_between_two_vectors(player->pos, gOffsetPosition)) - (var_a1 = - // player->rotation[1]); - stackPadding19 = -get_angle_between_two_vectors(player->pos, gOffsetPosition) - player->rotation[1]; - var_a1 = stackPadding19; - var_a2 = var_a1; - if ((s16) temp_f2 < var_a1) { - var_a2 = temp_f2; - } - if (var_a2 < (s16) temp_f6) { - var_a2 = temp_f6; - } - - var_v1 = CM_GetProps()->AISteeringSensitivity; + minAngle = onePointFive * 182.0f; + maxAngle = -onePointFive * 182.0f; + angle = -get_angle_between_two_vectors(player->pos, gOffsetPosition); + angle -= (newAngle = player->rotation[1]); + if ((s16) minAngle < angle) { + angle = minAngle; + } + if (angle < (s16) maxAngle) { + angle = maxAngle; + } + steeringSensitivity = CM_GetProps()->AISteeringSensitivity; switch (gCurrentTrackSectionTypesPath[playerId]) { /* switch 4; irregular */ - case 2: /* switch 4 */ + case RIGHT_CURVE: /* switch 4 */ if (gTrackPositionFactor[playerId] > (0.5f * 1.0f)) { - var_v1 = 0x0014; + steeringSensitivity = 0x0014; } if (gTrackPositionFactor[playerId] < -0.5f) { - var_v1 = 0x0035; + steeringSensitivity = 0x0035; } break; - case 3: /* switch 4 */ + case LEFT_CURVE: /* switch 4 */ if (gTrackPositionFactor[playerId] > 0.5f) { - var_v1 = 0x0035; + steeringSensitivity = 0x0035; } if (gTrackPositionFactor[playerId] < -0.5f) { - var_v1 = 0x0014; + steeringSensitivity = 0x0014; } break; } if ((cpu_BehaviourState[playerId] == CPU_BEHAVIOUR_STATE_RUNNING) && ((gTrackPositionFactor[playerId] > 0.9f) || (gTrackPositionFactor[playerId] < -0.9f))) { D_801630E8[playerId] = 0; - player->effects &= ~0x10; + player->effects &= ~DRIFTING_EFFECT; } if (player->effects & 2) { switch (D_801630E8[playerId]) { case 1: - var_a1 = 0x0035; + newAngle = 0x0035; break; case -1: - var_a1 = -0x0035; + newAngle = -0x0035; break; default: - var_a1 = (gPreviousAngleSteering[playerId] + ((var_a2 * var_v1) / temp_f2)) / 2; + newAngle = + (gPreviousAngleSteering[playerId] + ((angle * steeringSensitivity) / minAngle)) / 2; break; } - } else if (player->effects & 0x1000000C) { - var_a1 = 0; + } else if (player->effects & (UNKNOWN_EFFECT_0x10000000 | UNKNOWN_EFFECT_0xC)) { + newAngle = 0; } else { - var_a1 = (gPreviousAngleSteering[playerId] + ((var_a2 * var_v1) / temp_f2)) / 2; + newAngle = (gPreviousAngleSteering[playerId] + ((angle * steeringSensitivity) / minAngle)) / 2; } - apply_cpu_turn(player, var_a1); - gPreviousAngleSteering[playerId] = var_a1; + apply_cpu_turn(player, newAngle); + gPreviousAngleSteering[playerId] = newAngle; if ((gIsPlayerInCurve[playerId] == true) || (D_801630E8[playerId] == 1) || - (D_801630E8[playerId] == -1) || (player->effects & 0x1000000C)) { + (D_801630E8[playerId] == -1) || + (player->effects & (UNKNOWN_EFFECT_0x10000000 | UNKNOWN_EFFECT_0xC))) { cpu_TargetSpeed[playerId] = CM_GetProps()->CurveTargetSpeed[gCCSelection]; } else { cpu_TargetSpeed[playerId] = CM_GetProps()->NormalTargetSpeed[gCCSelection]; @@ -2008,8 +1968,10 @@ void update_player(s32 playerId) { a = calc_a(50, table[CC_50], 150, table[CC_150]); \ b = calc_b(50, table[CC_50], a); \ cpu_TargetSpeed[playerId] = a * CVarGetFloat("gCustomCC", 150.0f) + b; + // end of define if ((gIsPlayerInCurve[playerId] == true) || (D_801630E8[playerId] == 1) || - (D_801630E8[playerId] == -1) || (player->effects & 0x1000000C)) { + (D_801630E8[playerId] == -1) || + (player->effects & (UNKNOWN_EFFECT_0x10000000 | UNKNOWN_EFFECT_0xC))) { calc(CM_GetProps()->CurveTargetSpeed); } else { calc(CM_GetProps()->NormalTargetSpeed); @@ -2028,11 +1990,13 @@ void update_player(s32 playerId) { if ((D_801630E8[playerId] == 2) || (D_801630E8[playerId] == -2) || (D_801630E8[playerId] == 3)) { cpu_TargetSpeed[playerId] = 3.3333333f; } + // Override cpu speed for harder cpu enhancment if (CVarGetInteger("gHarderCPU", 0) == 1) { cpu_TargetSpeed[playerId] = player->topSpeed * 1.5f; } + gCurrentCpuTargetSpeed = cpu_TargetSpeed[playerId]; - player->effects &= ~0x00200000; + player->effects &= ~UNKNOWN_EFFECT_0x200000; gPreviousCpuTargetSpeed[playerId] = gCurrentCpuTargetSpeed; CM_AICrossingBehaviour(playerId); // check_ai_crossing_distance(playerId); @@ -2041,132 +2005,168 @@ void update_player(s32 playerId) { } } } -#undef FAKEMATCH1 -#undef FAKEMATCH2 -#else -GLOBAL_ASM("asm/non_matchings/code_80005FD0/update_player.s") -#endif -#ifdef NON_MATCHING -// Lots of work left to do, might be funtionally accurate? void func_8000B140(s32 playerId) { - UNUSED f32 stackPadding0; - UNUSED f32 stackPadding1; - UNUSED f32 stackPadding2; - UNUSED f32 stackPadding3; - UNUSED f32 stackPadding4; - UNUSED f32 stackPadding5; - UNUSED f32 stackPadding6; - UNUSED f32 stackPadding7; - f32 temp_f0_2; + s32 i; f32 temp_f12; f32 temp_f14; + s32 j; f32 temp_f16; + f32 temp_ft2; + s16 currPathPoint; + s16 temp_v1_2; f32 temp_f22; - f32 temp_f2; + f32 temp_f0_2; f32 var_f18; f32 var_f20; + UNUSED s32 pad[5]; s16 spB0[8]; - UNUSED f32 stackPadding8; + UNUSED f32 pad2; s16 sp9C[8]; - UNUSED f32 stackPadding9; + UNUSED f32 pad3; + f32 temp_f2; f32 sp74[8]; s32 temp_a1_2; - s16 temp_v1_2; - s16 var_t1; - s32 var_t2; - s32 someIndex; Player* player; - player = &gPlayers[playerId]; - if (!(player->effects & DRIFTING_EFFECT) && (D_801630E8[playerId] != 1) && (D_801630E8[playerId] != -1) && - !(gTrackPositionFactor[playerId] < -1.0f) && !(gTrackPositionFactor[playerId] > 1.0f) && - (player->characterId != 5) && (player->characterId != 7) && (player->characterId != 4) && - !(player->effects & STAR_EFFECT)) { - var_t1 = gNearestPathPointByPlayerId[playerId]; - temp_f22 = (player->speed / 18.0f) * 216.0f; - for (someIndex = 0; someIndex < 8; someIndex++) { - sp9C[someIndex] = -1; - spB0[someIndex] = 0x03E8; + + if (player->effects & DRIFTING_EFFECT) { + return; + } + + if (D_801630E8[playerId] == 1) { + return; + } + + if (D_801630E8[playerId] == -1) { + return; + } + + if (gTrackPositionFactor[playerId] < -1.0f) { + return; + } + + if (gTrackPositionFactor[playerId] > 1.0f) { + return; + } + + // Exclude heavyweights + if (player->characterId == WARIO) { + return; + } + + if (player->characterId == BOWSER) { + return; + } + + if (player->characterId == DK) { + return; + } + + // Skip if player has star + if (player->effects & STAR_EFFECT) { + return; + } + + currPathPoint = gNearestPathPointByPlayerId[playerId]; + temp_f22 = (player->speed / 18.0f) * 216.0f; + for (i = 0; i < 8; i++) { + sp9C[i] = -1; + spB0[i] = 0x03E8; + } + + if (D_80163010[playerId] > 0) { + D_80163010[playerId]--; + if (D_80163010[playerId] <= 0) { + D_80162FF8[playerId] = 0; } - if (D_80163010[playerId] > 0) { - D_80163010[playerId]--; - if (D_80163010[playerId] <= 0) { - D_80162FF8[playerId] = 0; - } - } - var_t2 = 0; - for (someIndex = 0; (var_t2 < 2) && (someIndex < 8); someIndex++) { - if (someIndex == playerId) - continue; - player = &gPlayers[someIndex]; - if (!(player->type & 0x8000)) - continue; - temp_f2 = (temp_f22) -5.0f; - temp_v1_2 = gNearestPathPointByPlayerId[someIndex]; - temp_f0_2 = (player->speed / 18.0f) * 216.0f; - if (temp_f0_2 < temp_f2) { - if (is_path_point_in_range(temp_v1_2, var_t1, 0U, 0x0014U, gSelectedPathCount) > 0) { - temp_a1_2 = temp_v1_2 - var_t1; - sp9C[var_t2] = someIndex; - if (temp_a1_2 > 0) { - spB0[var_t2] = temp_a1_2; - } else { - spB0[var_t2] = (temp_v1_2 + gSelectedPathCount) - var_t1; - } - sp74[var_t2] = temp_f2 - temp_f0_2; - var_t2 += 1; - } - } - } - if (var_t2 != 0) { - var_f18 = 1.0f; - var_f20 = -1.0f; - for (someIndex = 0; someIndex < var_t2; someIndex++) { - temp_f2 = gTrackPositionFactor[sp9C[someIndex]]; - if ((temp_f2 > -1.0f) && (temp_f2 < 1.0f)) { - temp_f12 = sp74[someIndex] + 10.0f; - temp_f12 *= 0.2f * (20.0f / (spB0[someIndex] + 20.0f)); - temp_f12 /= 20.0f; - if ((var_f18 == 1.0f) && (var_f20 == -1.0f)) { - var_f18 = temp_f2 - temp_f12; - var_f20 = temp_f2 + temp_f12; - } else { - temp_f14 = temp_f2 - temp_f12; - temp_f16 = temp_f2 + temp_f12; - if ((temp_f14 < 1.0f) && (temp_f16 > 1.0f)) { - var_f18 = temp_f14; - } - if ((temp_f16 > -1.0f) && (temp_f14 < -1.0f)) { - var_f20 = temp_f16; + } + j = 0; + i = 0; + while (i < 8) { + if (i != playerId) { + player = &gPlayers[i]; + if ((player->type & PLAYER_EXISTS)) { + temp_v1_2 = gNearestPathPointByPlayerId[i]; + temp_f0_2 = (player->speed / 18.0f) * 216.0f; + temp_f2 = temp_f22 - 5.0f; + if (temp_f0_2 < temp_f2) { + if (is_path_point_in_range(temp_v1_2, currPathPoint, 0, 0x0014U, gSelectedPathCount) > 0) { + temp_a1_2 = temp_v1_2 - currPathPoint; + sp9C[j] = i; + if (temp_a1_2 > 0) { + spB0[j] = temp_a1_2; + } else { + spB0[j] = (temp_v1_2 + gSelectedPathCount) - currPathPoint; } + sp74[j] = temp_f2 - temp_f0_2; + j++; } } } - if (!(var_f20 < var_f18) && !(gTrackPositionFactor[playerId] < var_f18) && - !(var_f20 < gTrackPositionFactor[playerId])) { - if (var_f20 > 1.0f) { - var_f20 = 1.0f; + } + i++; + if (j >= 2) { + break; + } + } + + if (j == 0) { + return; + } + + var_f18 = 1.0f; + var_f20 = -1.0f; + for (i = 0; i < j; i++) { + temp_f2 = gTrackPositionFactor[sp9C[i]]; + if ((temp_f2 > (-1.0f)) && (temp_f2 < 1.0f)) { + + temp_f12 = temp_ft2 = ((0.2f * (20.0f / (spB0[i] + 20.0f))) * ((sp74[i]) + 10.0f)) / 20.0f; + + if ((var_f18 == 1.0f) && (var_f20 == (-1.0f))) { + var_f18 = temp_f2 - temp_f12; + var_f20 = temp_f2 + temp_f12; + } else { + temp_f14 = temp_f2 - temp_f12; + temp_f16 = temp_f2 + temp_f12; + if ((temp_f14 < var_f18) && (temp_f16 > var_f18)) { + var_f18 = temp_f14; } - if (var_f18 < -1.0f) { - var_f18 = -1.0f; - } - if ((var_f18 + 1.0f) < (1.0f - var_f20)) { - D_80163010[playerId] = 0x003C; - D_80162FF8[playerId] = 1; - D_80163090[playerId] = var_f20; - } else { - D_80163010[playerId] = 0x003C; - D_80162FF8[playerId] = 2; - D_80163090[playerId] = var_f18; + if ((temp_f16 > var_f20) && (temp_f14 < var_f20)) { + var_f20 = temp_f16; } } } } + + if (var_f20 < var_f18) { + return; + } + + if (gTrackPositionFactor[playerId] < var_f18) { + return; + } + + if (var_f20 < gTrackPositionFactor[playerId]) { + return; + } + + if (var_f20 > 1.0f) { + var_f20 = 1.0f; + } + if (var_f18 < (-1.0f)) { + var_f18 = -1.0f; + } + if ((var_f18 + 1.0f) < (1.0f - var_f20)) { + D_80163010[playerId] = 0x003C; + D_80162FF8[playerId] = 1; + D_80163090[playerId] = var_f20; + } else { + D_80163010[playerId] = 0x003C; + D_80162FF8[playerId] = 2; + D_80163090[playerId] = var_f18; + } } -#else -GLOBAL_ASM("asm/non_matchings/code_80005FD0/func_8000B140.s") -#endif s32 are_in_curve(UNUSED s32 arg0, u16 waypointIndex) { s16 thing = gCurrentTrackConsecutiveCurveCountsPath[waypointIndex]; @@ -3703,7 +3703,8 @@ void load_track_path(s32 pathIndex) { TrackPathPoint* pathSrc = CM_GetProps()->PathTable2[pathIndex]; if (pathSrc == NULL) { - printf("code_80005FD0.c: Path %d in Course::PathTable2, was NULL.\n Your track is missing a path\n", pathIndex); + printf("code_80005FD0.c: Path %d in Course::PathTable2, was NULL.\n Your track is missing a path\n", + pathIndex); } var_v0 = process_path_data(pathDest, pathSrc); @@ -5960,12 +5961,14 @@ void func_80017054(Camera* camera, UNUSED Player* player, UNUSED s32 index, s32 sp58 = gPathCountByPathIndex[pathIndex]; D_80163238 = playerId; sp56 = gNearestPathPointByCameraId[cameraId]; - gNearestPathPointByCameraId[cameraId] = func_8000D33C(camera->pos[0], camera->pos[1], camera->pos[2], gNearestPathPointByCameraId[cameraId], pathIndex); + gNearestPathPointByCameraId[cameraId] = + func_8000D33C(camera->pos[0], camera->pos[1], camera->pos[2], gNearestPathPointByCameraId[cameraId], pathIndex); if (IsYoshiValley()) { if ((sp56 != gNearestPathPointByCameraId[cameraId]) && (gNearestPathPointByCameraId[cameraId] == 1)) { D_80163DD8[cameraId] = random_int(4); pathIndex = D_80163DD8[cameraId]; - gNearestPathPointByCameraId[cameraId] = func_8000D33C(camera->pos[0], camera->pos[1], camera->pos[2], gNearestPathPointByCameraId[cameraId], pathIndex); + gNearestPathPointByCameraId[cameraId] = func_8000D33C(camera->pos[0], camera->pos[1], camera->pos[2], + gNearestPathPointByCameraId[cameraId], pathIndex); } } waypoint1 = (gNearestPathPointByCameraId[cameraId] + 0xA) % sp58; @@ -7072,551 +7075,638 @@ void clear_expired_strategies(CpuItemStrategyData* arg0) { } } -#ifdef NON_MATCHING -// By the looks of this function is probably something like `cpu_use_item_strategy` -// The use of several different actor types might make getting a match hard(er), -// might have to get creative/ugly with just a single generic `Actor` variable. -// https://decomp.me/scratch/FOlbG void cpu_use_item_strategy(s32 playerId) { - bool isNoProblem; - Player* player; - TrackPathPoint* pathPoint; - CpuItemStrategyData* temp_s0; + Player* player = &gPlayerOne[playerId]; struct Actor* actor; - struct ShellActor* shell; - struct BananaActor* banana; - struct FakeItemBox* fakeItemBox; - struct BananaBunchParent* bananaBunchParent; + CpuItemStrategyData* cpuStrategy = &cpu_ItemStrategy[playerId]; + TrackPathPoint* pathPoint; + bool isValidBanana1; + bool isValidBanana2; - player = &gPlayerOne[playerId]; - if (((gModeSelection != ((s32) 1)) && (((u16) D_801646CC) != ((u16) 1))) && - (!(player->type & PLAYER_CINEMATIC_MODE))) { - temp_s0 = &cpu_ItemStrategy[playerId]; - switch (temp_s0->branch) { - case CPU_STRATEGY_WAIT_NEXT_ITEM: - temp_s0->actorIndex = -1; +// Only used in this function +#define BANANA_ACTOR(actor) ((struct BananaActor*) (actor)) +#define SHELL_ACTOR(actor) ((struct ShellActor*) (actor)) +#define FAKE_ITEMBOX_ACTOR(actor) ((struct FakeItemBox*) (actor)) +#define BANANA_BUNCH_ACTOR(actor) ((struct BananaBunchParent*) (actor)) - // Harder CPU Items - if (((gNumPathPointsTraversed[playerId] + (playerId * 0x14) + 0x64) % 0x8 == 0) && - (temp_s0->timer >= 0x200) && (CVarGetInteger("gHarderCPU", 0) == true)) { - cpu_decisions_branch_item(playerId, &temp_s0->branch, - hard_cpu_gen_random_item((s16) gLapCountByPlayerId[playerId], - gGPCurrentRaceRankByPlayerId[playerId])); + if (gModeSelection == TIME_TRIALS) { + return; + } + + if ((u16) D_801646CC == 1) { + return; + } + + if (player->type & PLAYER_CINEMATIC_MODE) { + return; + } + + switch (cpuStrategy->branch) { + case CPU_STRATEGY_WAIT_NEXT_ITEM: + cpuStrategy->actorIndex = -1; + + // Harder CPU Items + if (((gNumPathPointsTraversed[playerId] + (playerId * 20) + 100) % 8 == 0) && (cpuStrategy->timer >= 512) && + (CVarGetInteger("gHarderCPU", 0) == true)) { + + cpu_decisions_branch_item(playerId, &cpuStrategy->branch, + hard_cpu_gen_random_item((s16) gLapCountByPlayerId[playerId], + gGPCurrentRaceRankByPlayerId[playerId])); // Stock CPU Items - } else if ((((playerId * 0x14) + 0x64) < gNumPathPointsTraversed[playerId]) && (temp_s0->timer >= 0x259) && - (temp_s0->numItemUse < 3) && (gLapCountByPlayerId[playerId] < 3)) { - cpu_decisions_branch_item(playerId, &temp_s0->branch, - cpu_gen_random_item((s16) gLapCountByPlayerId[playerId], - gGPCurrentRaceRankByPlayerId[playerId])); - } else { - func_8001ABE0(playerId, temp_s0); + } else if ((((playerId * 20) + 100) < gNumPathPointsTraversed[playerId]) && (cpuStrategy->timer >= 0x259) && + (cpuStrategy->numItemUse < 3) && (gLapCountByPlayerId[playerId] < 3)) { + cpu_decisions_branch_item( + playerId, &cpuStrategy->branch, + cpu_gen_random_item((s16) gLapCountByPlayerId[playerId], gGPCurrentRaceRankByPlayerId[playerId])); + } else { + func_8001ABE0(playerId, cpuStrategy); + } + break; + + case CPU_STRATEGY_ITEM_BANANA: + // never true + if ((gLapCountByPlayerId[playerId] > 0) && + (gGPCurrentRaceRankByPlayerId[playerId] > gGPCurrentRaceRankByPlayerId[gBestRankedHumanPlayer]) && + (gGPCurrentRaceRankByPlayerId[gBestRankedHumanPlayer] == FIRST_PLACE)) { + switch (player->characterId) { + case DK: + if (is_path_point_in_range(gNearestPathPointByPlayerId[playerId], + gNearestPathPointByPlayerId[gBestRankedHumanPlayer], 40, 2, + gSelectedPathCount) > 0) { + cpuStrategy->branch = CPU_STRATEGY_THROW_BANANA; + } + break; + + case PEACH: + if (is_path_point_in_range(gNearestPathPointByPlayerId[playerId], + gNearestPathPointByPlayerId[gBestRankedHumanPlayer], 4, 2, + gSelectedPathCount) > 0) { + cpuStrategy->branch = CPU_STRATEGY_THROW_BANANA; + } + break; + + default: + if (is_path_point_in_range(gNearestPathPointByPlayerId[playerId], + gNearestPathPointByPlayerId[gBestRankedHumanPlayer], 10, 2, + gSelectedPathCount) > 0) { + cpuStrategy->branch = CPU_STRATEGY_THROW_BANANA; + } + break; } - break; - - case CPU_STRATEGY_ITEM_BANANA: - // never true - if ((gLapCountByPlayerId[playerId] > 0) && - (gGPCurrentRaceRankByPlayerId[gBestRankedHumanPlayer] > gGPCurrentRaceRankByPlayerId[playerId]) && - (gGPCurrentRaceRankByPlayerId[gBestRankedHumanPlayer] == FIRST_PLACE)) { - switch (player->characterId) { - case DK: - if (is_path_point_in_range(gNearestPathPointByPlayerId[playerId], - gNearestPathPointByPlayerId[gBestRankedHumanPlayer], 0x0028U, 2U, - (u16) ((s32) gSelectedPathCount)) > 0) { - temp_s0->branch = CPU_STRATEGY_THROW_BANANA; - } - break; - - case PEACH: - if (is_path_point_in_range(gNearestPathPointByPlayerId[playerId], - gNearestPathPointByPlayerId[gBestRankedHumanPlayer], 4U, 2U, - (u16) ((s32) gSelectedPathCount)) > 0) { - temp_s0->branch = CPU_STRATEGY_THROW_BANANA; - } - break; - - default: - if (is_path_point_in_range(gNearestPathPointByPlayerId[playerId], - gNearestPathPointByPlayerId[gBestRankedHumanPlayer], 0x000AU, 2U, - (u16) ((s32) gSelectedPathCount)) > 0) { - temp_s0->branch = CPU_STRATEGY_THROW_BANANA; - } - break; - } - } else if (temp_s0->branch == CPU_STRATEGY_ITEM_BANANA) { - temp_s0->actorIndex = use_banana_item(player); - if ((temp_s0->actorIndex >= 0) && (temp_s0->actorIndex < 0x64)) { - player->soundEffects |= HOLD_BANANA_SOUND_EFFECT; - temp_s0->branch = CPU_STRATEGY_HOLD_BANANA; - temp_s0->timer = 0; - temp_s0->numItemUse += 1; - temp_s0->timeBeforeThrow = (random_int(3U) * 0x14) + 0xA; - } else { - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; - temp_s0->timer = 0; - } - } - break; - - case CPU_STRATEGY_HOLD_BANANA: - banana = (struct BananaActor*) GET_ACTOR(temp_s0->actorIndex); - if ((!(banana->flags & 0x8000)) || (banana->type != ACTOR_BANANA) || (banana->state != HELD_BANANA) || - (playerId != banana->playerId)) { - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; - temp_s0->timer = 0; - player->soundEffects &= ~HOLD_BANANA_SOUND_EFFECT; - } else if (temp_s0->timeBeforeThrow < temp_s0->timer) { - temp_s0->branch = CPU_STRATEGY_DROP_BANANA; - } - break; - - case CPU_STRATEGY_DROP_BANANA: - banana = (struct BananaActor*) GET_ACTOR(temp_s0->actorIndex); - if ((((!(banana->flags & 0x8000)) || (banana->type != ACTOR_BANANA)) || - (banana->state != HELD_BANANA)) || - (playerId != banana->playerId)) { - if (playerId != banana->playerId) {} - } else { - banana->state = DROPPED_BANANA; - banana->velocity[0] = 0.0f; - banana->velocity[1] = 0.0f; - banana->velocity[2] = 0.0f; - if (D_801631E0[playerId] == ((u16) true)) { - banana->pos[1] = spawn_actor_on_surface(player->pos[0], (f32) (((f64) player->pos[1]) + 30.0), - player->pos[2]) + - (banana->boundingBoxSize + 1.0f); - } - } - player->soundEffects &= ~HOLD_BANANA_SOUND_EFFECT; - temp_s0->timer = 0; - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; - break; - - case CPU_STRATEGY_THROW_BANANA: - temp_s0->actorIndex = use_banana_item(player); - if ((temp_s0->actorIndex >= 0) && (temp_s0->actorIndex < 0x64)) { - banana = (struct BananaActor*) GET_ACTOR(temp_s0->actorIndex); - banana->state = BANANA_ON_GROUND; + } else if (cpuStrategy->branch == CPU_STRATEGY_ITEM_BANANA) { + cpuStrategy->actorIndex = use_banana_item(player); + if ((cpuStrategy->actorIndex >= 0) && (cpuStrategy->actorIndex < 100)) { player->soundEffects |= HOLD_BANANA_SOUND_EFFECT; - temp_s0->branch = CPU_STRATEGY_HOLD_THROW_BANANA; - temp_s0->timer = 0; - temp_s0->numItemUse += 1; - pathPoint = &gTrackPaths[gPathIndexByPlayerId[0]] - [(gNearestPathPointByPlayerId[gBestRankedHumanPlayer] + 0x1E) % - gPathCountByPathIndex[gPathIndexByPlayerId[gBestRankedHumanPlayer]]]; - banana->velocity[0] = (pathPoint->posX - player->pos[0]) / 20.0; - banana->velocity[1] = ((pathPoint->posY - player->pos[1]) / 20.0) + 4.0; - banana->velocity[2] = (pathPoint->posZ - player->pos[2]) / 20.0; - banana->pos[1] = player->pos[1]; - func_800C92CC(playerId, SOUND_ARG_LOAD(0x29, 0x00, 0x80, 0x09)); - func_800C98B8(player->pos, player->velocity, SOUND_ARG_LOAD(0x19, 0x01, 0x80, 0x14)); + cpuStrategy->branch = CPU_STRATEGY_HOLD_BANANA; + cpuStrategy->timer = 0; + cpuStrategy->numItemUse += 1; + cpuStrategy->timeBeforeThrow = (random_int(3) * 20) + 10; } else { - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; - temp_s0->timer = 0; + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + cpuStrategy->timer = 0; } - break; + } + break; - case CPU_STRATEGY_HOLD_THROW_BANANA: - banana = (struct BananaActor*) GET_ACTOR(temp_s0->actorIndex); - if ((((!(banana->flags & 0x8000)) || (banana->type != ACTOR_BANANA)) || - (banana->state != BANANA_ON_GROUND)) || - (playerId != banana->playerId)) { - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; - temp_s0->timer = 0; - player->soundEffects &= ~HOLD_BANANA_SOUND_EFFECT; - } else { - banana->velocity[1] -= 0.4; - banana->pos[0] += banana->velocity[0]; - banana->pos[1] += banana->velocity[1]; - banana->pos[2] += banana->velocity[2]; - if (temp_s0->timer >= 0x15) { - temp_s0->branch = CPU_STRATEGY_END_THROW_BANANA; - } - } - break; + case CPU_STRATEGY_HOLD_BANANA: + actor = GET_ACTOR(cpuStrategy->actorIndex); + if ((!(BANANA_ACTOR(actor)->flags & 0x8000)) || (BANANA_ACTOR(actor)->type != ACTOR_BANANA) || + (BANANA_ACTOR(actor)->state != HELD_BANANA) || (playerId != BANANA_ACTOR(actor)->playerId)) { - case CPU_STRATEGY_END_THROW_BANANA: - banana = (struct BananaActor*) GET_ACTOR(temp_s0->actorIndex); - if ((((!(banana->flags & 0x8000)) || (banana->type != ACTOR_BANANA)) || - (banana->state != BANANA_ON_GROUND)) || - (playerId != banana->playerId)) { - if (playerId != banana->playerId) {} - } else { - banana->state = DROPPED_BANANA; - banana->velocity[0] = 0.0f; - banana->velocity[1] = 0.0f; - banana->velocity[2] = 0.0f; - banana->pos[1] = - spawn_actor_on_surface(banana->pos[0], (f32) (((f64) banana->pos[1]) + 30.0), banana->pos[2]) + - (banana->boundingBoxSize + 1.0f); - } + // FAKE + if (!(BANANA_ACTOR(actor)->flags & 0x8000)) {} + if (BANANA_ACTOR(actor)->type != 6) {} + if (BANANA_ACTOR(actor)->state != 0) {} + if (BANANA_ACTOR(actor)->rot[0] != playerId) {} + + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + cpuStrategy->timer = 0; player->soundEffects &= ~HOLD_BANANA_SOUND_EFFECT; - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; - temp_s0->timer = 0; - break; + } else if (cpuStrategy->timeBeforeThrow < cpuStrategy->timer) { + cpuStrategy->branch = CPU_STRATEGY_DROP_BANANA; + } + break; - case CPU_STRATEGY_ITEM_GREEN_SHELL: - if (((s32) gNumActors) < 0x50) { - temp_s0->actorIndex = use_green_shell_item(player); - if ((temp_s0->actorIndex >= 0) && (temp_s0->actorIndex < 0x64)) { - temp_s0->branch = CPU_STRATEGY_HOLD_GREEN_SHELL; - temp_s0->timer = 0; - temp_s0->numItemUse += 1; - temp_s0->timeBeforeThrow = (random_int(3U) * 0x14) + 0xA; - } else { - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; - } + case CPU_STRATEGY_DROP_BANANA: + actor = GET_ACTOR(cpuStrategy->actorIndex); + if ((((!(BANANA_ACTOR(actor)->flags & 0x8000)) || (BANANA_ACTOR(actor)->type != ACTOR_BANANA)) || + (BANANA_ACTOR(actor)->state != HELD_BANANA)) || + (playerId != BANANA_ACTOR(actor)->playerId)) { + + // FAKE + if (!(BANANA_ACTOR(actor)->flags & 0x8000)) {} + if (BANANA_ACTOR(actor)->type != 6) {} + if (BANANA_ACTOR(actor)->state != 0) {} + if (BANANA_ACTOR(actor)->rot[0] != playerId) {} + + } else { + BANANA_ACTOR(actor)->state = DROPPED_BANANA; + BANANA_ACTOR(actor)->velocity[0] = 0.0f; + BANANA_ACTOR(actor)->velocity[1] = 0.0f; + BANANA_ACTOR(actor)->velocity[2] = 0.0f; + if (D_801631E0[playerId] == true) { + BANANA_ACTOR(actor)->pos[1] = + spawn_actor_on_surface(player->pos[0], player->pos[1] + 30.0, player->pos[2]) + + (BANANA_ACTOR(actor)->boundingBoxSize + 1.0f); + } + } + player->soundEffects &= ~HOLD_BANANA_SOUND_EFFECT; + cpuStrategy->timer = 0; + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + break; + + case CPU_STRATEGY_THROW_BANANA: + cpuStrategy->actorIndex = use_banana_item(player); + if ((cpuStrategy->actorIndex >= 0) && (cpuStrategy->actorIndex < 100)) { + actor = GET_ACTOR(cpuStrategy->actorIndex); + BANANA_ACTOR(actor)->state = BANANA_ON_GROUND; + player->soundEffects |= HOLD_BANANA_SOUND_EFFECT; + cpuStrategy->branch = CPU_STRATEGY_HOLD_THROW_BANANA; + cpuStrategy->timer = 0; + cpuStrategy->numItemUse += 1; + pathPoint = &gTrackPaths[gPathIndexByPlayerId[0]] + [(gNearestPathPointByPlayerId[gBestRankedHumanPlayer] + 30) % + gPathCountByPathIndex[gPathIndexByPlayerId[gBestRankedHumanPlayer]]]; + BANANA_ACTOR(actor)->velocity[0] = (pathPoint->posX - player->pos[0]) / 20.0; + BANANA_ACTOR(actor)->velocity[1] = ((pathPoint->posY - player->pos[1]) / 20.0) + 4.0; + BANANA_ACTOR(actor)->velocity[2] = (pathPoint->posZ - player->pos[2]) / 20.0; + BANANA_ACTOR(actor)->pos[1] = player->pos[1]; + func_800C92CC(playerId, SOUND_ARG_LOAD(0x29, 0x00, 0x80, 0x09)); + func_800C98B8(player->pos, player->velocity, SOUND_ARG_LOAD(0x19, 0x01, 0x80, 0x14)); + } else { + cpuStrategy->timer = 0; + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + } + break; + + case CPU_STRATEGY_HOLD_THROW_BANANA: + actor = GET_ACTOR(cpuStrategy->actorIndex); + if ((((!(BANANA_ACTOR(actor)->flags & 0x8000)) || (BANANA_ACTOR(actor)->type != ACTOR_BANANA)) || + (BANANA_ACTOR(actor)->state != BANANA_ON_GROUND)) || + (playerId != BANANA_ACTOR(actor)->playerId)) { + + // FAKE + if (!(BANANA_ACTOR(actor)->flags & 0x8000)) {} + if (BANANA_ACTOR(actor)->type != 6) {} + if (BANANA_ACTOR(actor)->state != 0) {} + if (BANANA_ACTOR(actor)->rot[0] != playerId) {} + + cpuStrategy->timer = 0; + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + player->soundEffects &= ~HOLD_BANANA_SOUND_EFFECT; + } else { + BANANA_ACTOR(actor)->velocity[1] -= 0.4; + BANANA_ACTOR(actor)->pos[0] += BANANA_ACTOR(actor)->velocity[0]; + BANANA_ACTOR(actor)->pos[1] += BANANA_ACTOR(actor)->velocity[1]; + BANANA_ACTOR(actor)->pos[2] += BANANA_ACTOR(actor)->velocity[2]; + if (cpuStrategy->timer > 20) { + cpuStrategy->branch = CPU_STRATEGY_END_THROW_BANANA; + } + } + break; + + case CPU_STRATEGY_END_THROW_BANANA: + actor = GET_ACTOR(cpuStrategy->actorIndex); + if ((((!(BANANA_ACTOR(actor)->flags & 0x8000)) || (BANANA_ACTOR(actor)->type != ACTOR_BANANA)) || + (BANANA_ACTOR(actor)->state != BANANA_ON_GROUND)) || + (playerId != BANANA_ACTOR(actor)->playerId)) { + + // FAKE + if (!(BANANA_ACTOR(actor)->flags & 0x8000)) {} + if (BANANA_ACTOR(actor)->type != 6) {} + if (BANANA_ACTOR(actor)->state != 0) {} + if (BANANA_ACTOR(actor)->rot[0] != playerId) {} + + } else { + BANANA_ACTOR(actor)->state = DROPPED_BANANA; + BANANA_ACTOR(actor)->velocity[0] = 0.0f; + BANANA_ACTOR(actor)->velocity[1] = 0.0f; + BANANA_ACTOR(actor)->velocity[2] = 0.0f; + BANANA_ACTOR(actor)->pos[1] = + spawn_actor_on_surface(BANANA_ACTOR(actor)->pos[0], BANANA_ACTOR(actor)->pos[1] + 30.0, + BANANA_ACTOR(actor)->pos[2]) + + (BANANA_ACTOR(actor)->boundingBoxSize + 1.0f); + } + player->soundEffects &= ~HOLD_BANANA_SOUND_EFFECT; + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + cpuStrategy->timer = 0; + break; + + case CPU_STRATEGY_ITEM_GREEN_SHELL: + if (gNumActors < 80) { + cpuStrategy->actorIndex = use_green_shell_item(player); + if ((cpuStrategy->actorIndex >= 0) && (cpuStrategy->actorIndex < 100)) { + cpuStrategy->branch = CPU_STRATEGY_HOLD_GREEN_SHELL; + cpuStrategy->timer = 0; + cpuStrategy->numItemUse += 1; + cpuStrategy->timeBeforeThrow = (random_int(3) * 20) + 10; } else { - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; } - break; + } else { + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + } + break; - case CPU_STRATEGY_HOLD_GREEN_SHELL: - actor = GET_ACTOR(temp_s0->actorIndex); - if ((((!(actor->flags & 0x8000)) || (actor->type != ACTOR_GREEN_SHELL)) || - (actor->state != HELD_SHELL)) || - (playerId != actor->rot[2])) { - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; - temp_s0->timer = 0; - } else if (temp_s0->timeBeforeThrow < temp_s0->timer) { - temp_s0->branch = CPU_STRATEGY_THROW_GREEN_SHELL; - temp_s0->timer = 0; - } - break; + case CPU_STRATEGY_HOLD_GREEN_SHELL: + actor = GET_ACTOR(cpuStrategy->actorIndex); + if ((((!(SHELL_ACTOR(actor)->flags & 0x8000)) || (actor->type != ACTOR_GREEN_SHELL)) || + (SHELL_ACTOR(actor)->state != HELD_SHELL)) || + (playerId != SHELL_ACTOR(actor)->playerId)) { - case CPU_STRATEGY_THROW_GREEN_SHELL: - actor = GET_ACTOR(temp_s0->actorIndex); - if ((((!(actor->flags & 0x8000)) || (actor->type != ACTOR_GREEN_SHELL)) || - (actor->state != HELD_SHELL)) || - (playerId != actor->rot[2])) { - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; - temp_s0->timer = 0; + // FAKE + if (!(SHELL_ACTOR(actor)->flags & 0x8000)) {} + if (SHELL_ACTOR(actor)->type != 7) {} + if (SHELL_ACTOR(actor)->state != 0) {} + if (SHELL_ACTOR(actor)->rotVelocity != playerId) {} + + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + cpuStrategy->timer = 0; + } else if (cpuStrategy->timeBeforeThrow < cpuStrategy->timer) { + cpuStrategy->branch = CPU_STRATEGY_THROW_GREEN_SHELL; + cpuStrategy->timer = 0; + } + break; + + case CPU_STRATEGY_THROW_GREEN_SHELL: + actor = GET_ACTOR(cpuStrategy->actorIndex); + if ((((!(SHELL_ACTOR(actor)->flags & 0x8000)) || (actor->type != ACTOR_GREEN_SHELL)) || + (SHELL_ACTOR(actor)->state != HELD_SHELL)) || + (playerId != SHELL_ACTOR(actor)->playerId)) { + + // FAKE + if (!(actor->flags & 0x8000)) {} + if (actor->type != 7) {} + if (actor->state != 0) {} + if (actor->rot[0] != playerId) {} + + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + cpuStrategy->timer = 0; + } else { + SHELL_ACTOR(actor)->state = RELEASED_SHELL; + cpuStrategy->timer = 0; + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + } + break; + + case CPU_STRATEGY_ITEM_RED_SHELL: + if (gNumActors < 80) { + cpuStrategy->actorIndex = use_red_shell_item(player); + if ((cpuStrategy->actorIndex >= 0) && (cpuStrategy->actorIndex < 100)) { + cpuStrategy->branch = CPU_STRATEGY_HOLD_RED_SHELL; + cpuStrategy->timer = 0; + cpuStrategy->numItemUse += 1; + cpuStrategy->timeBeforeThrow = (random_int(3) * 20) + 10; } else { - actor->state = RELEASED_SHELL; - temp_s0->timer = 0; - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; } - break; + } else { + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + } + break; - case CPU_STRATEGY_ITEM_RED_SHELL: - if (((s32) gNumActors) < 0x50) { - temp_s0->actorIndex = use_red_shell_item(player); - if ((temp_s0->actorIndex >= 0) && (temp_s0->actorIndex < 0x64)) { - temp_s0->branch = CPU_STRATEGY_HOLD_RED_SHELL; - temp_s0->timer = 0; - temp_s0->numItemUse += 1; - temp_s0->timeBeforeThrow = (random_int(3U) * 0x14) + 0xA; - } else { - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; - } + case CPU_STRATEGY_HOLD_RED_SHELL: + actor = GET_ACTOR(cpuStrategy->actorIndex); + if ((((!(SHELL_ACTOR(actor)->flags & 0x8000)) || (SHELL_ACTOR(actor)->type != ACTOR_RED_SHELL)) || + (SHELL_ACTOR(actor)->state != HELD_SHELL)) || + (playerId != SHELL_ACTOR(actor)->playerId)) { + + // FAKE + if (!(actor->flags & 0x8000)) {} + if (actor->type != 8) {} + if (actor->state != 0) {} + if (actor->rot[0] != playerId) {} + + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + cpuStrategy->timer = 0; + } else if (cpuStrategy->timeBeforeThrow < cpuStrategy->timer) { + cpuStrategy->branch = CPU_STRATEGY_THROW_RED_SHELL; + } + break; + + case CPU_STRATEGY_THROW_RED_SHELL: + clear_expired_strategies(cpuStrategy); + actor = GET_ACTOR(cpuStrategy->actorIndex); + if ((((!(SHELL_ACTOR(actor)->flags & 0x8000)) || (SHELL_ACTOR(actor)->type != ACTOR_RED_SHELL)) || + (SHELL_ACTOR(actor)->state != HELD_SHELL)) || + (playerId != SHELL_ACTOR(actor)->playerId)) { + + // FAKE + if (!(actor->flags & 0x8000)) {} + if (actor->type != 8) {} + if (actor->state != 0) {} + if (actor->rot[0] != playerId) {} + + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + cpuStrategy->timer = 0; + } else { + SHELL_ACTOR(actor)->state = RELEASED_SHELL; + cpuStrategy->timer = 0; + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + } + break; + + case CPU_STRATEGY_ITEM_BANANA_BUNCH: + if (gNumActors < 80) { + cpuStrategy->actorIndex = use_banana_bunch_item(player); + if ((cpuStrategy->actorIndex >= 0) && (cpuStrategy->actorIndex < 100)) { + cpuStrategy->branch = CPU_STRATEGY_WAIT_INIT_BANANA_BUNCH; + cpuStrategy->timer = 0; + cpuStrategy->numItemUse += 1; + cpuStrategy->timeBeforeThrow = (random_int(3) * 20) + 60; } else { - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; } - break; + } else { + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + } + break; - case CPU_STRATEGY_HOLD_RED_SHELL: - shell = (struct ShellActor*) GET_ACTOR(temp_s0->actorIndex); - if ((((!(shell->flags & 0x8000)) || (shell->type != ACTOR_RED_SHELL)) || - (shell->state != HELD_SHELL)) || - (playerId != shell->playerId)) { - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; - temp_s0->timer = 0; - } else if (temp_s0->timeBeforeThrow < temp_s0->timer) { - temp_s0->branch = CPU_STRATEGY_THROW_RED_SHELL; + case CPU_STRATEGY_WAIT_INIT_BANANA_BUNCH: + actor = GET_ACTOR(cpuStrategy->actorIndex); + if (BANANA_BUNCH_ACTOR(actor)->state == 6) { + + // FAKE + if (BANANA_BUNCH_ACTOR(actor)->state != -1) {} + if (BANANA_BUNCH_ACTOR(actor)->state == 6) {} + + isValidBanana2 = false; + + if (BANANA_BUNCH_ACTOR(actor)->bananaIndices[4] != (-1)) { + isValidBanana2 = true; } - break; + if (BANANA_BUNCH_ACTOR(actor)->bananaIndices[3] != (-1)) { + isValidBanana2 = true; + } + if (BANANA_BUNCH_ACTOR(actor)->bananaIndices[2] != (-1)) { + isValidBanana2 = true; + } + if (BANANA_BUNCH_ACTOR(actor)->bananaIndices[1] != (-1)) { + isValidBanana2 = true; + } + if (BANANA_BUNCH_ACTOR(actor)->bananaIndices[0] != (-1)) { + isValidBanana2 = true; + } + if ((BANANA_BUNCH_ACTOR(actor)->type != ACTOR_BANANA_BUNCH) || (isValidBanana2 == false)) { + if (BANANA_BUNCH_ACTOR(actor)->type != 14) {} + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + cpuStrategy->timer = 0; + } else if (cpuStrategy->timeBeforeThrow < cpuStrategy->timer) { + cpuStrategy->branch = CPU_STRATEGY_DROP_BANANA_BUNCH; + cpuStrategy->numDroppedBananaBunch = 0; + cpuStrategy->timer = 0; + } + } + break; - case CPU_STRATEGY_THROW_RED_SHELL: - clear_expired_strategies(temp_s0); - shell = (struct ShellActor*) GET_ACTOR(temp_s0->actorIndex); - if ((((!(shell->flags & 0x8000)) || (shell->type != ACTOR_RED_SHELL)) || - (shell->state != HELD_SHELL)) || - (playerId != shell->playerId)) { - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; - temp_s0->timer = 0; + case CPU_STRATEGY_DROP_BANANA_BUNCH: + if (((cpuStrategy->timer) % 10) == 0) { + if (cpuStrategy->numDroppedBananaBunch < 5) { + isValidBanana1 = 0; + actor = GET_ACTOR(cpuStrategy->actorIndex); + switch (cpuStrategy->numDroppedBananaBunch) { + case 0: + if (BANANA_BUNCH_ACTOR(actor)->bananaIndices[4] != (-1)) { + isValidBanana1 = true; + } + break; + + case 1: + if (BANANA_BUNCH_ACTOR(actor)->bananaIndices[3] != (-1)) { + isValidBanana1 = true; + } + break; + + case 2: + if (BANANA_BUNCH_ACTOR(actor)->bananaIndices[2] != (-1)) { + isValidBanana1 = true; + } + break; + + case 3: + if (BANANA_BUNCH_ACTOR(actor)->bananaIndices[1] != (-1)) { + isValidBanana1 = true; + } + break; + + case 4: + if (BANANA_BUNCH_ACTOR(actor)->bananaIndices[0] != (-1)) { + isValidBanana1 = true; + } + break; + } + + if (((BANANA_BUNCH_ACTOR(actor)->type == ACTOR_BANANA_BUNCH) && + (BANANA_BUNCH_ACTOR(actor)->state == 6)) && + (isValidBanana1 == true)) { + drop_banana_in_banana_bunch((struct BananaBunchParent*) actor); + } + cpuStrategy->numDroppedBananaBunch += 1; } else { - shell->state = RELEASED_SHELL; - temp_s0->timer = 0; - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + cpuStrategy->timer = 0; } - break; + } + break; - case CPU_STRATEGY_ITEM_BANANA_BUNCH: - if (((s32) gNumActors) < 0x50) { - temp_s0->actorIndex = use_banana_bunch_item(player); - if ((temp_s0->actorIndex >= 0) && (temp_s0->actorIndex < 0x64)) { - temp_s0->branch = CPU_STRATEGY_WAIT_INIT_BANANA_BUNCH; - temp_s0->timer = 0; - temp_s0->numItemUse += 1; - temp_s0->timeBeforeThrow = (random_int(3U) * 0x14) + 0x3C; - } else { - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; - } - } else { - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + case CPU_STRATEGY_ITEM_FAKE_ITEM_BOX: + cpuStrategy->actorIndex = use_fake_itembox_item(player); + if ((cpuStrategy->actorIndex >= 0) && (cpuStrategy->actorIndex < 100)) { + cpuStrategy->branch = CPU_STRATEGY_HOLD_FAKE_ITEM_BOX; + cpuStrategy->timer = 0; + cpuStrategy->numItemUse += 1; + cpuStrategy->timeBeforeThrow = (random_int(3) * 20) + 10; + } else { + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + } + break; + + case CPU_STRATEGY_HOLD_FAKE_ITEM_BOX: + actor = GET_ACTOR(cpuStrategy->actorIndex); + if ((((!(FAKE_ITEMBOX_ACTOR(actor)->flags & 0x8000)) || + (FAKE_ITEMBOX_ACTOR(actor)->type != ACTOR_FAKE_ITEM_BOX)) || + (FAKE_ITEMBOX_ACTOR(actor)->state != 0)) || + (playerId != ((s32) FAKE_ITEMBOX_ACTOR(actor)->playerId))) { + + // FAKE + if (!(actor->flags & 0x8000)) {} + if (actor->type != 13) {} + if (actor->state != 0) {} + if (actor->rot[0] != playerId) {} + + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + cpuStrategy->timer = 0; + } else if (cpuStrategy->timeBeforeThrow < cpuStrategy->timer) { + cpuStrategy->branch = CPU_STRATEGY_THROW_FAKE_ITEM_BOX; + } + break; + + case CPU_STRATEGY_THROW_FAKE_ITEM_BOX: + actor = GET_ACTOR(cpuStrategy->actorIndex); + if ((((!(FAKE_ITEMBOX_ACTOR(actor)->flags & 0x8000)) || + (FAKE_ITEMBOX_ACTOR(actor)->type != ACTOR_FAKE_ITEM_BOX)) || + (FAKE_ITEMBOX_ACTOR(actor)->state != 0)) || + (playerId != ((s32) FAKE_ITEMBOX_ACTOR(actor)->playerId))) { + + // FAKE + if (!(FAKE_ITEMBOX_ACTOR(actor)->flags & 0x8000)) {} + if (FAKE_ITEMBOX_ACTOR(actor)->type != 13) {} + if (FAKE_ITEMBOX_ACTOR(actor)->state != 0) {} + if (FAKE_ITEMBOX_ACTOR(actor)->rot[0] != playerId) {} + + } else { + func_802A1064((struct FakeItemBox*) actor); + if (D_801631E0[playerId] == true) { + FAKE_ITEMBOX_ACTOR(actor)->pos[1] = spawn_actor_on_surface(FAKE_ITEMBOX_ACTOR(actor)->pos[0], + FAKE_ITEMBOX_ACTOR(actor)->pos[1] + 30.0, + FAKE_ITEMBOX_ACTOR(actor)->pos[2]) + + FAKE_ITEMBOX_ACTOR(actor)->boundingBoxSize; } - break; + } + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + cpuStrategy->timer = 0; + break; - case CPU_STRATEGY_WAIT_INIT_BANANA_BUNCH: - bananaBunchParent = (struct BananaBunchParent*) GET_ACTOR(temp_s0->actorIndex); - if (bananaBunchParent->state == 6) { - isNoProblem = false; - if (bananaBunchParent->bananaIndices[4] != (-1)) { - isNoProblem = true; - } - if (bananaBunchParent->bananaIndices[3] != (-1)) { - isNoProblem = true; - } - if (bananaBunchParent->bananaIndices[2] != (-1)) { - isNoProblem = true; - } - if (bananaBunchParent->bananaIndices[1] != (-1)) { - isNoProblem = true; - } - if (bananaBunchParent->bananaIndices[0] != (-1)) { - isNoProblem = true; - } - if ((bananaBunchParent->type != ACTOR_BANANA_BUNCH) || (isNoProblem == false)) { - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; - temp_s0->timer = 0; - } else if (temp_s0->timeBeforeThrow < temp_s0->timer) { - temp_s0->branch = CPU_STRATEGY_DROP_BANANA_BUNCH; - temp_s0->numDroppedBananaBunch = 0; - temp_s0->timer = 0; - } - } - break; + case CPU_STRATEGY_ITEM_THUNDERBOLT: + use_thunder_item(player); + func_800CAC60(playerId); + func_8009E5BC(); + cpuStrategy->branch = CPU_STRATEGY_END_THUNDERBOLT; + cpuStrategy->timer = 0; + cpuStrategy->numItemUse += 1; + break; - case CPU_STRATEGY_DROP_BANANA_BUNCH: - if ((((s16) temp_s0->timer) % 10) == 0) { - if (temp_s0->numDroppedBananaBunch < 5) { - bananaBunchParent = (struct BananaBunchParent*) GET_ACTOR(temp_s0->actorIndex); - isNoProblem = 0; - switch (temp_s0->numDroppedBananaBunch) { - case 0: - if (bananaBunchParent->bananaIndices[4] != (-1)) { - isNoProblem = true; - } - break; + case CPU_STRATEGY_END_THUNDERBOLT: + if (cpuStrategy->timer >= 0xF1) { + func_800CAD40((s32) ((u8) playerId)); + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + cpuStrategy->timer = 0; + } + break; - case 1: - if (bananaBunchParent->bananaIndices[3] != (-1)) { - isNoProblem = true; - } - break; + case CPU_STRATEGY_ITEM_STAR: + player->soundEffects |= STAR_SOUND_EFFECT; + cpuStrategy->branch = CPU_STRATEGY_END_ITEM_STAR; + cpuStrategy->timer = 0; + cpuStrategy->numItemUse += 1; + break; - case 2: - if (bananaBunchParent->bananaIndices[2] != (-1)) { - isNoProblem = true; - } - break; + case CPU_STRATEGY_END_ITEM_STAR: + if (!(player->effects & STAR_EFFECT)) { + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + } + cpuStrategy->timer = 0; + break; - case 3: - if (bananaBunchParent->bananaIndices[1] != (-1)) { - isNoProblem = true; - } - break; + case CPU_STRATEGY_ITEM_BOO: + player->soundEffects |= BOO_SOUND_EFFECT; + cpuStrategy->branch = CPU_STRATEGY_WAIT_END_BOO; + cpuStrategy->timer = 0; + cpuStrategy->numItemUse += 1; + break; - case 4: - if (bananaBunchParent->bananaIndices[0] != (-1)) { - isNoProblem = true; - } - break; - } + case CPU_STRATEGY_WAIT_END_BOO: + if (!(player->effects & BOO_EFFECT)) { + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + } + cpuStrategy->timer = 0; + break; - if (((bananaBunchParent->type == ACTOR_BANANA_BUNCH) && (bananaBunchParent->state == 6)) && - (isNoProblem == true)) { - drop_banana_in_banana_bunch(bananaBunchParent); - } - temp_s0->numDroppedBananaBunch += 1; - } else { - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; - temp_s0->timer = 0; - } - } - break; + case CPU_STRATEGY_ITEM_MUSHROOM: + player->soundEffects |= BOOST_SOUND_EFFECT; + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + cpuStrategy->timer = 0; + cpuStrategy->numItemUse += 1; + break; - case CPU_STRATEGY_ITEM_FAKE_ITEM_BOX: - temp_s0->actorIndex = use_fake_itembox_item(player); - if ((temp_s0->actorIndex >= 0) && (temp_s0->actorIndex < 0x64)) { - temp_s0->branch = CPU_STRATEGY_HOLD_FAKE_ITEM_BOX; - temp_s0->timer = 0; - temp_s0->numItemUse += 1; - temp_s0->timeBeforeThrow = (random_int(3U) * 0x14) + 0xA; - } else { - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; - } - break; - - case CPU_STRATEGY_HOLD_FAKE_ITEM_BOX: - fakeItemBox = (struct FakeItemBox*) GET_ACTOR(temp_s0->actorIndex); - if ((((!(fakeItemBox->flags & 0x8000)) || (fakeItemBox->type != ACTOR_FAKE_ITEM_BOX)) || - (fakeItemBox->state != 0)) || - (playerId != ((s32) fakeItemBox->playerId))) { - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; - temp_s0->timer = 0; - } else if (temp_s0->timeBeforeThrow < temp_s0->timer) { - temp_s0->branch = CPU_STRATEGY_THROW_FAKE_ITEM_BOX; - } - break; - - case CPU_STRATEGY_THROW_FAKE_ITEM_BOX: - fakeItemBox = (struct FakeItemBox*) GET_ACTOR(temp_s0->actorIndex); - if ((((!(fakeItemBox->flags & 0x8000)) || (fakeItemBox->type != ACTOR_FAKE_ITEM_BOX)) || - (fakeItemBox->state != 0)) || - (playerId != ((s32) fakeItemBox->playerId))) { - if (playerId != fakeItemBox->rot[0]) {} - } else { - func_802A1064(fakeItemBox); - if (D_801631E0[playerId] == true) { - fakeItemBox->pos[1] = spawn_actor_on_surface(fakeItemBox->pos[0], fakeItemBox->pos[1] + 30.0, - fakeItemBox->pos[2]) + - fakeItemBox->boundingBoxSize; - } - } - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; - temp_s0->timer = 0; - break; - - case CPU_STRATEGY_ITEM_THUNDERBOLT: - use_thunder_item(player); - func_800CAC60(playerId); - func_8009E5BC(); - temp_s0->branch = CPU_STRATEGY_END_THUNDERBOLT; - temp_s0->timer = 0; - temp_s0->numItemUse += 1; - break; - - case CPU_STRATEGY_END_THUNDERBOLT: - if (temp_s0->timer >= 0xF1) { - func_800CAD40((s32) ((u8) playerId)); - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; - temp_s0->timer = 0; - } - break; - - case CPU_STRATEGY_ITEM_STAR: - player->soundEffects |= STAR_SOUND_EFFECT; - temp_s0->branch = CPU_STRATEGY_END_ITEM_STAR; - temp_s0->timer = 0; - temp_s0->numItemUse += 1; - break; - - case CPU_STRATEGY_END_ITEM_STAR: - if (!(player->effects & STAR_EFFECT)) { - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; - } - temp_s0->timer = 0; - break; - - case CPU_STRATEGY_ITEM_BOO: - player->soundEffects |= BOO_SOUND_EFFECT; - temp_s0->branch = CPU_STRATEGY_WAIT_END_BOO; - temp_s0->timer = 0; - temp_s0->numItemUse += 1; - break; - - case CPU_STRATEGY_WAIT_END_BOO: - if (!(player->effects & BOO_EFFECT)) { - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; - } - temp_s0->timer = 0; - break; - - case CPU_STRATEGY_ITEM_MUSHROOM: + case CPU_STRATEGY_ITEM_DOUBLE_MUSHROOM: + if (cpuStrategy->timer >= 0x3D) { player->soundEffects |= BOOST_SOUND_EFFECT; - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; - temp_s0->timer = 0; - temp_s0->numItemUse += 1; - break; + cpuStrategy->branch = CPU_STRATEGY_ITEM_MUSHROOM; + cpuStrategy->timer = 0; + } + break; - case CPU_STRATEGY_ITEM_DOUBLE_MUSHROOM: - if (temp_s0->timer >= 0x3D) { - player->soundEffects |= BOOST_SOUND_EFFECT; - temp_s0->branch = CPU_STRATEGY_ITEM_MUSHROOM; - temp_s0->timer = 0; + case CPU_STRATEGY_ITEM_TRIPLE_MUSHROOM: + if (cpuStrategy->timer >= 0x3D) { + player->soundEffects |= BOOST_SOUND_EFFECT; + cpuStrategy->branch = CPU_STRATEGY_ITEM_DOUBLE_MUSHROOM; + cpuStrategy->timer = 0; + } + break; + + case CPU_STRATEGY_ITEM_SUPER_MUSHROOM: + cpuStrategy->branch = CPU_STRATEGY_USE_SUPER_MUSHROOM; + cpuStrategy->timer = 0; + cpuStrategy->timeBeforeThrow = 0x0258; + break; + + case CPU_STRATEGY_USE_SUPER_MUSHROOM: + if ((((s16) cpuStrategy->timer) % 60) == 0) { + player->soundEffects |= BOOST_SOUND_EFFECT; + if (cpuStrategy->timeBeforeThrow < cpuStrategy->timer) { + cpuStrategy->timer = 0; + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; } - break; - - case CPU_STRATEGY_ITEM_TRIPLE_MUSHROOM: - if (temp_s0->timer >= 0x3D) { - player->soundEffects |= BOOST_SOUND_EFFECT; - temp_s0->branch = CPU_STRATEGY_ITEM_DOUBLE_MUSHROOM; - temp_s0->timer = 0; - } - break; - - case CPU_STRATEGY_ITEM_SUPER_MUSHROOM: - temp_s0->branch = CPU_STRATEGY_USE_SUPER_MUSHROOM; - temp_s0->timer = 0; - temp_s0->timeBeforeThrow = 0x0258; - break; - - case CPU_STRATEGY_USE_SUPER_MUSHROOM: - if ((((s16) temp_s0->timer) % 60) == 0) { - player->soundEffects |= BOOST_SOUND_EFFECT; - if (temp_s0->timeBeforeThrow < temp_s0->timer) { - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; - temp_s0->timer = 0; - } - } - break; - case CPU_STRATEGY_ITEM_BLUE_SPINY_SHELL: - if (((s32) gNumActors) < 0x50) { - temp_s0->actorIndex = use_blue_shell_item(player); - if ((temp_s0->actorIndex >= 0) && (temp_s0->actorIndex < 0x64)) { - temp_s0->branch = CPU_STRATEGY_HOLD_BLUE_SPINY_SHELL; - temp_s0->timer = 0; - temp_s0->numItemUse += 1; - temp_s0->timeBeforeThrow = (random_int(3U) * 0x14) + 0xA; - } else { - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; - } + } + break; + case CPU_STRATEGY_ITEM_BLUE_SPINY_SHELL: + if (((s32) gNumActors) < 80) { + cpuStrategy->actorIndex = use_blue_shell_item(player); + if ((cpuStrategy->actorIndex >= 0) && (cpuStrategy->actorIndex < 0x64)) { + cpuStrategy->branch = CPU_STRATEGY_HOLD_BLUE_SPINY_SHELL; + cpuStrategy->timer = 0; + cpuStrategy->numItemUse += 1; + cpuStrategy->timeBeforeThrow = (random_int(3U) * 0x14) + 0xA; } else { - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; } - break; - case CPU_STRATEGY_HOLD_BLUE_SPINY_SHELL: - shell = (struct ShellActor*) GET_ACTOR(temp_s0->actorIndex); - if ((((!(shell->flags & 0x8000)) || (shell->type != ACTOR_BLUE_SPINY_SHELL)) || - (shell->state != HELD_SHELL)) || - (playerId != shell->playerId)) { - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; - temp_s0->timer = 0; - } else if (temp_s0->timeBeforeThrow < temp_s0->timer) { - temp_s0->branch = CPU_STRATEGY_THROW_BLUE_SPINY_SHELL; - } - break; - case CPU_STRATEGY_THROW_BLUE_SPINY_SHELL: - clear_expired_strategies(temp_s0); - shell = (struct ShellActor*) GET_ACTOR(temp_s0->actorIndex); - if ((((!(shell->flags & 0x8000)) || (shell->type != ACTOR_BLUE_SPINY_SHELL)) || - (shell->state != HELD_SHELL)) || - (playerId != shell->playerId)) { - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; - temp_s0->timer = 0; - } else { - shell->state = RELEASED_SHELL; - temp_s0->timer = 0; - temp_s0->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; - } - break; + } else { + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + } + break; + case CPU_STRATEGY_HOLD_BLUE_SPINY_SHELL: + actor = GET_ACTOR(cpuStrategy->actorIndex); + if ((((!(SHELL_ACTOR(actor)->flags & 0x8000)) || (actor->type != ACTOR_BLUE_SPINY_SHELL)) || + (SHELL_ACTOR(actor)->state != HELD_SHELL)) || + (playerId != SHELL_ACTOR(actor)->playerId)) { + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + cpuStrategy->timer = 0; + } else if (cpuStrategy->timeBeforeThrow < cpuStrategy->timer) { + cpuStrategy->branch = CPU_STRATEGY_THROW_BLUE_SPINY_SHELL; + } + break; + case CPU_STRATEGY_THROW_BLUE_SPINY_SHELL: + clear_expired_strategies(cpuStrategy); + actor = GET_ACTOR(cpuStrategy->actorIndex); + if ((((!(SHELL_ACTOR(actor)->flags & 0x8000)) || (SHELL_ACTOR(actor)->type != ACTOR_BLUE_SPINY_SHELL)) || + (SHELL_ACTOR(actor)->state != HELD_SHELL)) || + (playerId != SHELL_ACTOR(actor)->playerId)) { + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + cpuStrategy->timer = 0; + } else { + SHELL_ACTOR(actor)->state = RELEASED_SHELL; + cpuStrategy->timer = 0; + cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM; + } + break; - default: - break; - } + default: + break; + } - if (temp_s0->timer < 0x2710) { - temp_s0->timer += 1; - } - if (player->effects & (BOO_EFFECT | BOOST_EFFECT | STAR_EFFECT)) { // 0x80002200 - temp_s0->timer = 0; - } + if (cpuStrategy->timer < 10000) { + cpuStrategy->timer += 1; + } + if (player->effects & (BOO_EFFECT | BOOST_EFFECT | STAR_EFFECT)) { + cpuStrategy->timer = 0; } } -#else -GLOBAL_ASM("asm/non_matchings/code_80005FD0/cpu_use_item_strategy.s") -#endif + +#undef BANANA_ACTOR +#undef SHELL_ACTOR +#undef FAKE_ITEMBOX_ACTOR +#undef BANANA_BUNCH void func_8001BE78(void) { Player* temp_s1;