diff --git a/decompile/General/LOAD/LOAD_A33_LangFile.c b/decompile/General/LOAD/LOAD_A33_LangFile.c index 9246e1e09..be60d5c88 100644 --- a/decompile/General/LOAD/LOAD_A33_LangFile.c +++ b/decompile/General/LOAD/LOAD_A33_LangFile.c @@ -19,7 +19,7 @@ void DECOMP_LOAD_LangFile(int bigfilePtr, int lang) char **strArray; #if BUILD == EurRetail - // This is (probably) to turn the screen black for a bit until lng is loaded. + // This is to turn the screen black for a bit (optional) DECOMP_CTR_ErrorScreen(0, 0, 0); VSync(0); #endif @@ -51,6 +51,7 @@ void DECOMP_LOAD_LangFile(int bigfilePtr, int lang) (unsigned int)lngFile; } #if BUILD == EurRetail + // set voicelines to new lang DECOMP_CDSYS_SetXAToLang(lang); #endif } \ No newline at end of file diff --git a/decompile/General/MAIN/MainMain.c b/decompile/General/MAIN/MainMain.c index 25f8f3711..213141d3e 100644 --- a/decompile/General/MAIN/MainMain.c +++ b/decompile/General/MAIN/MainMain.c @@ -120,6 +120,12 @@ u_int DECOMP_main() // Main Gameplay Update // Makes up all normal interaction with the game case 3: + #ifdef USE_LANG + if ((gGT->gameMode2 & LNG_CHANGE) != 0) { + LOAD_LangFile(sdata->ptrBigfileCdPos_2, gGT->langIndex); + gGT->gameMode2 &= ~(LNG_CHANGE); + } + #endif // if loading, or gameplay interrupted if (sdata->Loading.stage != -1) { diff --git a/decompile/General/Vehicle/VehAfterColl_GetTerrain.c b/decompile/General/Vehicle/VehAfterColl_GetTerrain.c index 25c3eeaaa..633671b2e 100644 --- a/decompile/General/Vehicle/VehAfterColl_GetTerrain.c +++ b/decompile/General/Vehicle/VehAfterColl_GetTerrain.c @@ -4,8 +4,9 @@ struct Terrain* DECOMP_VehAfterColl_GetTerrain(u_char terrainType) { struct Terrain* ter = &data.MetaDataTerrain[0]; - if (terrainType < 0x15) + // if terrain is valid + if (terrainType < 21) return &ter[terrainType]; - + return ter; } diff --git a/decompile/General/Vehicle/VehBirth_TireSprites.c b/decompile/General/Vehicle/VehBirth_TireSprites.c index 7677e8014..29e5a38a8 100644 --- a/decompile/General/Vehicle/VehBirth_TireSprites.c +++ b/decompile/General/Vehicle/VehBirth_TireSprites.c @@ -41,7 +41,7 @@ void DECOMP_VehBirth_TireSprites(struct Thread *t) d->numFramesSpentSteering = 10000; #ifndef REBUILD_PS1 - d->terrainMeta1 = VehAfterColl_GetTerrain(10); + d->terrainMeta1 = VehAfterColl_GetTerrain(TERRAIN_NONE); #endif d->BattleHUD.numLives = gGT->battleLifeLimit; diff --git a/decompile/WorkInProgress/src/231/231_028_RB_Warpball_NewPathNode.c b/decompile/WorkInProgress/src/231/231_028_RB_Warpball_NewPathNode.c new file mode 100644 index 000000000..f679b1283 --- /dev/null +++ b/decompile/WorkInProgress/src/231/231_028_RB_Warpball_NewPathNode.c @@ -0,0 +1,60 @@ +#include + +struct CheckpointNode* DECOMP_RB_Warpball_NewPathNode(struct CheckpointNode *cn, struct Driver *d) +{ + u_char currPoint; + u_int currIndex; + u_char boolPointExists = false; + + struct GameTracker *gGT = sdata->gGT; + + // if no driver is chased + if (d == NULL) + { + RETURN_NEXT_INDEX: + return &gGT->level1->ptr_restart_points[cn->nextIndex_forward]; + } + + // pathPoint -> left index + currIndex = cn->nextIndex_left; + + // if driver is not near that point + if (d->unknown_lap_related[0] != currIndex) + { + // if left point is valid + if (cn->nextIndex_left != 0xff) + { + struct CheckpointNode *currNode = cn; + for (int i = 0; i < 3; i++) + { + // path index + if (currNode->nextIndex_left == -1) + { + currPoint = currNode->nextIndex_forward; + } + + // path index + else + { + currPoint = currNode->nextIndex_left; + } + + // path node + currNode = gGT->level1->ptr_restart_points[currPoint]; + + // compare path index + if (d->unknown_lap_related[0] == currNode->nextIndex_forward) + { + boolPointExists = true; + break; + } + } + } + if (!boolPointExists) + goto RETURN_NEXT_INDEX; + currIndex = cn->nextIndex_left; + } + + // new path node + return &gGT->level1->ptr_restart_points[currIndex]; +} \ No newline at end of file diff --git a/decompile/WorkInProgress/src/231/231_030_RB_Warpball_GetDriverTarget.c b/decompile/WorkInProgress/src/231/231_030_RB_Warpball_GetDriverTarget.c new file mode 100644 index 000000000..4e6e8eaa8 --- /dev/null +++ b/decompile/WorkInProgress/src/231/231_030_RB_Warpball_GetDriverTarget.c @@ -0,0 +1,119 @@ +#include + +struct Driver* RB_Warpball_GetDriverTarget(struct TrackerWeapon *tw, struct Instance *inst) +{ + u_int distToFinish; + int currDistance; + int index; + int iVar4; + + struct Driver* currDriver = NULL; + struct Driver* hitDriver = NULL; + + // if 10 wumpa fruit were not used + if ((tw->flags & 1) == 0) + { + for (index = 0; index < 8; index++) + { + // check next driver until you get the driver + // farthest in the lead, that has not finished race + currDriver = sdata->gGT->drivers[index]; + + // if driver is valid + if (((currDriver != NULL) && + + // if driver is not the same as driver that fired warpball + (currDriver != tw->driverParent)) && + + // if the race is not over for this driver + ((currDriver->actionsFlagSet & 0x2000000) == 0)) + { + return currDriver; + } + } + } + + // if 10 wumpa fruit were used + else + { + // start of lev->path + struct CheckpointNode* cn = &sdata->gGT->level1->ptr_restart_points[0]; + + // node1 + struct CheckpointNode* node1 = &cn[tw->ptrNodeCurr->nextIndex_forward]; + + // node2 + struct CheckpointNode* node2 = &cn[node1->nextIndex_forward]; + + u_int distToFinish = cn->distToFinish * 8; + + short vec1[4]; + // direction from node1 to node2 + vec1[0] = node1->pos[0] - node2->pos[0]; + vec1[1] = node1->pos[1] - node2->pos[1]; + vec1[2] = node1->pos[2] - node2->pos[2]; + + MATH_VectorNormalize(&vec1[0]); + + short vec2[4]; + // direction from orb to node1 + vec2[0] = inst->matrix.t[0] - node1.pos[0]; + vec2[1] = inst->matrix.t[1] - node1.pos[1]; + vec2[2] = inst->matrix.t[2] - node1.pos[2]; + + // replace R11R12 and R13R21 + gte_ldsvrtrow0(&vec1[0]); + + gte_ldv0(&vec2[0]); + + gte_mvmva(0,0,0,3,0); + + // replace stMAC1 + gte_stlvnl0(&iVar4); + + u_int maxDistance = 0x7fffffff; + + iVar4 = node1->distanceToFinish * 8 + (iVar4 >> 0xc) + 0x200; + + #if 0 + if (uVar1 == 0) + { + trap(0x1c00); + } + if ((distToFinish == -1) && (iVar4 == -0x80000000)) + { + trap(0x1800); + } + #endif + + for (index = 0; index < 8; index++) + { + // pointer to structure of each player + currDriver = sdata->gGT->drivers[index]; + + // if driver is valid + if (((currDriver != NULL) && + ((tw->driversHit & 1 << (index & 0x1fU)) == 0)) && + (( + // If the race is not over for this player + (currDriver->actionsFlagSet & 0x2000000) == 0 && + + // If you are not being mask-grabbed + (currDriver->kartState != KS_MASK_GRABBED)))) + { + currDistance = iVar4 % distToFinish - currDriver->distanceToFinish_curr; + + if (currDistance < 0) + { + currDistance += distToFinish; + } + if (currDistance < maxDistance) + { + maxDistance = currDistance; + hitDriver = currDriver; + } + } + } + } + return hitDriver; +} diff --git a/decompile/WorkInProgress/src/231/231_031_RB_Warpball_SetTargetDriver.c b/decompile/WorkInProgress/src/231/231_031_RB_Warpball_SetTargetDriver.c new file mode 100644 index 000000000..b8c0fb6e2 --- /dev/null +++ b/decompile/WorkInProgress/src/231/231_031_RB_Warpball_SetTargetDriver.c @@ -0,0 +1,79 @@ +#include + +void RB_Warpball_SetTargetDriver(struct TrackerWeapon *tw) +{ + int distance; + int i, j; + int local_20; + int local_1c; + + struct GameTracker *gGT = sdata->gGT; + + // driver being chased + struct Driver *target = tw->driverTarget; + + // if driver is valid + if (target == NULL) + return; + + distance = target->distanceToFinish_curr; + + // path node + struct CheckpointNode *firstNode = &gGT->level->ptr_restart_points[0]; + struct CheckpointNode *currNode = &first[target->unknown_lap_related]; + + // distance is less than path node distance + while ((distance <= (thisNode->distToFinish << 3) && + + // path node is not first node + (currNode != firstNode))) + { + currNode = RB_Warpball_NewPathNode(currNode, tw->driverTarget); + } + + target = NULL; + local_1c = 0; + thisNode = tw->ptrNodeCurr; + + if ((tw->flags & 4) == 0) + { + for (i = 0; i < 2; i++) + { + distance = *(int *)((int)&local_20 + (distance >> 0xe)); + if (distance != 0) + { + thisNode = 0; + for (j = 0; j < 3; j++) + { + if (distance == currNode) + { + tw->flags = tw->flags & 0xfff7 | 4; + break; + } + if (*(byte *)(distance + 0xb) != 0xff) + { + // path node + local_1c = *(int *)(*(int *)(gGT + 0x160) + 0x14c) + + (uint) * (byte *)(distance + 0xb) * 0xc; + } + + // path node + distance = *(int *)(*(int *)(gGT + 0x160) + 0x14c) + (uint) * (byte *)(distance + 10) * 0xc; + } + } + } + } + + // path node + thisNode = tw->ptrNodeCurr; + + for (i = 0; i < 3; i++) + { + if (thisNode == currNode) + { + tw->flags = tw->flags & ~(8) | 4; + return; + } + target = RB_Warpball_NewPathNode(target, tw->driverTarget); + } +} \ No newline at end of file diff --git a/decompile/WorkInProgress/src/CAM/CAM_18_MapRange_PosPoints.c b/decompile/WorkInProgress/src/CAM/CAM_18_MapRange_PosPoints.c index d056f82f9..1b8d9d7ef 100644 --- a/decompile/WorkInProgress/src/CAM/CAM_18_MapRange_PosPoints.c +++ b/decompile/WorkInProgress/src/CAM/CAM_18_MapRange_PosPoints.c @@ -1,30 +1,31 @@ #include // get percentage [0 to 0x1000] of Driver between pos1 and pos2 -int DECOMP_CAM_MapRange_PosPoints(short *pos1, short *pos2, short *currPos) +int DECOMP_CAM_MapRange_PosPoints(SVec3 *pos1, SVec3 *pos2, SVec3 *currPos) { int percent; - int vectorDistMax; - int vectorDistCurr; + SVec3 vec1; + SVec3 vec2; short distY; // vector distance between position1 and position2. - vectorDistMax = CONCAT22(pos1[1] - pos2[1], pos1[0] - pos2[0]); - - distY = pos1[2] - pos2[2]; - - MATH_VectorNormalize(&vectorDistMax); + vec1.x = pos1->x - pos2->x; + vec1.y = pos1->y - pos2->y; + vec1.z = pos1->z - pos2->z; + MATH_VectorNormalize(&vec1); + // vector distance between position1 and currentPosition. - vectorDistCurr = CONCAT22(currPos[1] - pos1[1], currPos[0] - pos1[0]); + vec2.x = pos1->x - currPos->x; + vec2.y = pos1->y - currPos->y; + vec2.z = pos1->z - currPos->z; - gte_ldR11R12(vectorDistMax); - gte_ldR13R21((int)distY); - gte_ldVXY0(vectorDistCurr); - gte_ldVZ0((int)(short)(currPos[2] - pos1[2])); + // replace R11R12 and R13R21 + gte_ldsvrtrow0(&vec1); + gte_ldv0(&vec2); gte_mvmva(0, 0, 0, 3, 0); - percent = gte_stMAC1(); + gte_stlvnl0(&percent); // Shift by 12 bits to get the percentage between 0 and 0x1000. - return percent >> 0xc; + return FP_INT(percent); } \ No newline at end of file diff --git a/decompile/WorkInProgress/src/MATH.c b/decompile/WorkInProgress/src/MATH.c index 34940aeae..e2050c139 100644 --- a/decompile/WorkInProgress/src/MATH.c +++ b/decompile/WorkInProgress/src/MATH.c @@ -1,5 +1,7 @@ #include +#define PSYQ_FP_DIV(x, y) (((x) << PSYQ_FRACTIONAL_BITS) / (y)) + // only used by flamejet and PapuPyramidPlant for hitbox collision, // also used by missile, probably hitbox again MATRIX* DECOMP_MATH_HitboxMatrix(MATRIX* output, MATRIX* input) @@ -40,37 +42,39 @@ MATRIX* DECOMP_MATH_HitboxMatrix(MATRIX* output, MATRIX* input) return; } -void DECOMP_MATH_VectorLength(VECTOR* input) +void DECOMP_MATH_VectorLength(SVec3* input) { - unsigned int uVar1; + unsigned int length; - gte_ldR11R12(input->vx); - gte_ldR13R21(input->vy); - gte_ldVXY0(input->vx); - gte_ldVZ0(input->vy); + gte_ldR11R12(input->x); + gte_ldR13R21(input->y); + gte_ldVXY0(input->x); + gte_ldVZ0(input->y); gte_mvmva(0,0,0,3,0); - uVar1 = gte_stMAC1(); - SquareRoot0(uVar1); + gte_stlvnl0(&length); + SquareRoot0(length); return; } -int DECOMP_MATH_VectorNormalize(VECTOR* input) +int DECOMP_MATH_VectorNormalize(SVec3* input) { int length; - length = MATH_VectorLength(); + length = MATH_VectorLength(input); if (length != 0) { + #if 0 if (length == 0) { trap(0x1c00); } if ((length == -1) && (input->vx | input->vy | input->vz) == 0x8000) { trap(0x1800); } - input->vx = (short)((input->vx << 0xc) / length); - input->vy = (short)((input->vy << 0xc) / length); - input->vz = (short)((input->vz << 0xc) / length); + #endif + input->x = (short)(FP_Div(input->x, length)); + input->y = (short)(FP_Div(input->y, length)); + input->z = (short)(FP_Div(input->z, length)); } return length; } diff --git a/decompile/WorkInProgress/src/PickupBots_UpdateAll.c b/decompile/WorkInProgress/src/PickupBots_UpdateAll.c index 0d719e0b9..35fb52d6a 100644 --- a/decompile/WorkInProgress/src/PickupBots_UpdateAll.c +++ b/decompile/WorkInProgress/src/PickupBots_UpdateAll.c @@ -3,11 +3,12 @@ void DECOMP_PickupBots_Update(void) { // handles which weapons bosses use - char *meta; char i; u_char backupWumpa; + u_char weaponID; + u_char enemyID; + u_char playerID; char numPlyrCurrGame; - short sVar2; u_short uVar3; int iVar4; uint uVar5; @@ -15,15 +16,14 @@ void DECOMP_PickupBots_Update(void) int iVar7; char bVar8; u_char uVar9; - u_int uVar10; + u_int voiceID; short sVar11; - struct Driver *currDriver; - struct Driver *nextDriver; + struct Driver *thisDriver; + struct Driver *botDriver; struct GameTracker* gGT = sdata->gGT; // pointer to boss meta - // sdata->bossWeaponMeta - meta = (int *)0x8008d8e8; + struct MetaDataBOSS* bossMeta = sdata->ptrBossMeta; // If number of AIs is zero, or time on clock is less than 4b00 if ((gGT->numBotsNextGame == 0) || (gGT->elapsedEventTime < 0x4b00)) @@ -52,47 +52,47 @@ void DECOMP_PickupBots_Update(void) for (i = 0; i < gGT->numPlyrCurrGame; i++) { // get the player structure of each human player - currDriver = gGT.drivers[i]; + thisDriver = gGT.drivers[i]; // if racer is not in first place - if (currDriver->driverRank != 0) + if (thisDriver->driverRank != 0) { // driver in front of the player - nextDriver = gGT->driversInRaceOrder[currDriver->driverRank - 1]; + botDriver = gGT->driversInRaceOrder[thisDriver->driverRank - 1]; if ( ( ( ( // If this is an AI and not a human - (nextDriver->actionsFlagSet & 0x100000) != 0) && + (botDriver->actionsFlagSet & 0x100000) != 0) && ( // if AI is not blasted or spinning out - (nextDriver->botFlags & 2) == 0)) && + (botDriver->botFlags & 2) == 0)) && ( // if racer hasn't finished the race - (nextDriver->actionsFlagSet & 0x2000000) == 0)) && + (botDriver->actionsFlagSet & 0x2000000) == 0)) && (( ( // If there is no AI weapon cooldown - nextDriver->weaponCooldown == 0 && + botDriver->weaponCooldown == 0 && // If you dont have a tnt on your head - (nextDriver->instTntRecv == 0) + (botDriver->instTntRecv == 0) ) && (( // if there is no clock weapon in effect - nextDriver->clockReceive == 0 && + botDriver->clockReceive == 0 && ( // driver1x - driver2x - iVar6 = *(int *)(currDriver->instSelf->matrix.t[0]) - - *(int *)(nextDriver->instSelf->matrix.t[0]), + iVar6 = *(int *)(thisDriver->instSelf->matrix.t[0]) - + *(int *)(botDriver->instSelf->matrix.t[0]), // driver1z - driver2z - iVar7 = *(int *)(currDriver->instSelf->matrix.t[2]) - - *(int *)(nextDriver->instSelf->matrix.t[2]), + iVar7 = *(int *)(thisDriver->instSelf->matrix.t[2]) - + *(int *)(botDriver->instSelf->matrix.t[2]), // check if distance between drivers is small (iVar6 * iVar6 + iVar7 * iVar7) - 0x90001U < 0x13affff @@ -111,7 +111,7 @@ void DECOMP_PickupBots_Update(void) if (iVar6 == 0) { if ( - (*(char *)(nextDriver->matrix.t[0]) != 0) && + (*(char *)(botDriver->matrix.t[0]) != 0) && ( // Get random number @@ -121,51 +121,51 @@ void DECOMP_PickupBots_Update(void) iVar6 % 100 < 0x32)) { // Set number of wumpa to 10 - nextDriver->numWumpas = 10; + botDriver->numWumpas = 10; } // if time on the clock is an even number if ((gGT->elapsedEventTime & 1) == 0) { // Set weapon to potion - nextDriver->heldItemID = 4; + botDriver->heldItemID = 4; // If this is human and not AI - if ((currDriver->actionsFlagSet & 0x100000) == 0) + if ((thisDriver->actionsFlagSet & 0x100000) == 0) { // Make driver talk Voiceline_RequestPlay(0xf, - data.characterIDs[nextDriver->driverID], - data.characterIDs[currDriver->driverID]); + data.characterIDs[botDriver->driverID], + data.characterIDs[thisDriver->driverID]); } // potion - uVar10 = 4; + weaponID = 4; } // if time on the clock is an odd number else { // Set weapon to tnt/nitro - nextDriver->heldItemID = 3; + botDriver->heldItemID = 3; // If this is human and not AI - if ((currDriver->actionsFlagSet & 0x100000) == 0) + if ((thisDriver->actionsFlagSet & 0x100000) == 0) { // Make driver talk - Voiceline_RequestPlay(0xf, (int)(short)data.characterIDs[nextDriver->driverID], - (int)(short)data.characterIDs[currDriver->driverID]); + Voiceline_RequestPlay(0xf, (int)(short)data.characterIDs[botDriver->driverID], + (int)(short)data.characterIDs[thisDriver->driverID]); } // tnt/nitro - uVar10 = 3; + weaponID = 3; } // VehPickupItem_ShootNow (Arcade/Adv) - VehPickupItem_ShootNow(nextDriver, uVar10, 0); + VehPickupItem_ShootNow(botDriver, weaponID, 0); // set wumpa to zero - nextDriver->numWumpas = 0; + botDriver->numWumpas = 0; LAB_800412a4: @@ -173,7 +173,7 @@ void DECOMP_PickupBots_Update(void) uVar3 = MixRNG_Scramble(); // weapon cooldown - nextDriver->weaponCooldown = (uVar3 & 0xff) + 0xf0; + botDriver->weaponCooldown = (uVar3 & 0xff) + 0xf0; } else { @@ -181,24 +181,24 @@ void DECOMP_PickupBots_Update(void) if (iVar6 == 1) { // Set weapon to bomb - nextDriver->heldItemID = (char)iVar6; + botDriver->heldItemID = (char)iVar6; // If this is human and not AI - if ((currDriver->actionsFlagSet & 0x100000) == 0) + if ((thisDriver->actionsFlagSet & 0x100000) == 0) { // Player / AI structure + 0x4a shows driver index (0-7) // Get character ID of two player/AI structures: iVar4 and iVar14 - sVar11 = data.characterIDs[nextDriver->driverID]; - sVar2 = data.characterIDs[currDriver->driverID]; - uVar10 = 10; + enemyID = data.characterIDs[botDriver->driverID]; + playerID = data.characterIDs[thisDriver->driverID]; + voiceID = 10; LAB_8004128c: // Make driver talk - Voiceline_RequestPlay(uVar10, (int)sVar11, (int)sVar2); + Voiceline_RequestPlay(voiceID, enemyID, playerID); } LAB_80041298: - VehPickupItem_ShootNow(nextDriver, 2, 0); + VehPickupItem_ShootNow(botDriver, 2, 0); goto LAB_800412a4; } @@ -206,19 +206,19 @@ void DECOMP_PickupBots_Update(void) if (iVar6 == 2) { // Set weapon to 2 - nextDriver->heldItemID = (char)iVar6; + botDriver->heldItemID = (char)iVar6; // if this is human and not AI - if ((currDriver->actionsFlagSet & 0x100000) == 0) + if ((thisDriver->actionsFlagSet & 0x100000) == 0) { // Player / AI structure + 0x4a shows driver index (0-7) // Get character ID of two player/AI structures: iVar4 and iVar14 - sVar11 = data.characterIDs[nextDriver->driverID]; - sVar2 = data.characterIDs[currDriver->driverID]; - uVar10 = 0xb; + enemyID = data.characterIDs[botDriver->driverID]; + playerID = data.characterIDs[thisDriver->driverID]; + voiceID = 11; goto LAB_8004128c; } goto LAB_80041298; @@ -226,50 +226,50 @@ void DECOMP_PickupBots_Update(void) } // You have no weapon - nextDriver->heldItemID = 0xf; + botDriver->heldItemID = 0xf; } } // If racer is in the top 3 places of the race (1st, 2nd, 3rd) - if (currDriver->driverRank < 3) + if (thisDriver->driverRank < 3) { // driver in the position behind player - nextDriver = gGT->driversInRaceOrder[currDriver->driverRank + 1]; + botDriver = gGT->driversInRaceOrder[thisDriver->driverRank + 1]; if ( ( ( ( // If this is an AI, and not human - ((nextDriver->actionsFlagSet & 0x100000) != 0) && + ((botDriver->actionsFlagSet & 0x100000) != 0) && // if AI is not blasted or spinning out - ((nextDriver->botFlags & 2) == 0)) && + ((botDriver->botFlags & 2) == 0)) && // if racer hasn't finished the race - ((nextDriver->actionsFlagSet & 0x2000000) == 0)) && + ((botDriver->actionsFlagSet & 0x2000000) == 0)) && (( ( // If there is no AI weapon cooldown - nextDriver->weaponCooldown == 0 && + botDriver->weaponCooldown == 0 && // If there is no TNT on your head - (nextDriver->instTntRecv == 0)) && + (botDriver->instTntRecv == 0)) && (( // If there is no clock weapon in effect - nextDriver->clockReceive == 0 && + botDriver->clockReceive == 0 && (( // this driver's lap count less than number of laps in race, // (this is false if you finish race) - currDriver->lapIndex < gGT->numLaps || + thisDriver->lapIndex < gGT->numLaps || // distToFinish more than 16000 - (16000 < currDriver->distanceToFinish_curr))))))) && + (16000 < thisDriver->distanceToFinish_curr))))))) && ( // driver1x - driver2x - iVar6 = currDriver->instSelf->matrix.t[0] - nextDriver->instSelf->matrix.t[0], + iVar6 = thisDriver->instSelf->matrix.t[0] - botDriver->instSelf->matrix.t[0], // driver1z - driver2z - iVar7 = currDriver->instSelf->matrix.t[2] - nextDriver->instSelf->matrix.t[2], + iVar7 = thisDriver->instSelf->matrix.t[2] - botDriver->instSelf->matrix.t[2], // check if distance between drivers is small (iVar6 * iVar6 + iVar7 * iVar7) - 0x90001U < 0x13affff))) @@ -286,7 +286,7 @@ void DECOMP_PickupBots_Update(void) uVar9 = 2, // if driver's lap is not last lap - nextDriver->matrix.t[0] != gGT->numLaps - 1U)) || + botDriver->matrix.t[0] != gGT->numLaps - 1U)) || ( // override weapon to bomb uVar9 = 1, @@ -295,29 +295,29 @@ void DECOMP_PickupBots_Update(void) iVar6 % 800 < 4)) { // set weapon - nextDriver->heldItemID = uVar9; + botDriver->heldItemID = uVar9; // If this is an AI and not human - if ((currDriver->actionsFlagSet & 0x100000) == 0) + if ((thisDriver->actionsFlagSet & 0x100000) == 0) { // Make driver talk Voiceline_RequestPlay(0xb, - data.characterIDs[nextDriver->driverID], - data.characterIDs[currDriver->driverID]); + data.characterIDs[botDriver->driverID], + data.characterIDs[thisDriver->driverID]); } // (Arcade/Adv) Missile - VehPickupItem_ShootNow(nextDriver, 2, 0); + VehPickupItem_ShootNow(botDriver, 2, 0); // Get random number uVar3 = MixRNG_Scramble(); // cooldown before next weapon - nextDriver->weaponCooldown = (uVar3 & 0xff) + 0xf0; + botDriver->weaponCooldown = (uVar3 & 0xff) + 0xf0; } // You have no weapon - nextDriver->heldItemID = 0xf; + botDriver->heldItemID = 0xf; } } } @@ -330,73 +330,70 @@ void DECOMP_PickupBots_Update(void) // ============================= // pointer to player structure (P2 or boss) - nextDriver = gGT->drivers[1]; + botDriver = gGT->drivers[1]; // pointer to player structure (P1) - currDriver = gGT.drivers[0]; + thisDriver = gGT.drivers[0]; if ( ( - ((nextDriver->botFlags & 2) != 0) || + ((botDriver->botFlags & 2) != 0) || // if racer finished this race - ((nextDriver->actionsFlagSet & 0x2000000) != 0)) || + ((botDriver->actionsFlagSet & 0x2000000) != 0)) || (( // if boss has tnt on their head - nextDriver->instTntRecv != 0 || + botDriver->instTntRecv != 0 || (( // victim of clock weapon - nextDriver->clockReceive != 0 || + botDriver->clockReceive != 0 || // if boss has not reached high speed - (*(int *)(nextDriver + 0x5d4) < 0x1f41)))))) + (*(int *)(botDriver + 0x5d4) < 0x1f41)))))) { - // some kind of RNG with 0xdeadc0ed - uVar3 = RngDeadCoed(&bss); - // new cooldown - *(int *)0x8008d8e4 = + sdata->bossCooldown = // random [0 to 16] + - (uVar3 & 0x10) + + (RngDeadCoed(&bss) & 0x10) + // min cooldown for boss - *(short *)(meta + 4) + 0xc + + bossMeta->weaponCooldown + 12 + // number of times you lost the event - sdata->advProgress.timesLostBossRace[gGT->bossID] * 4; + sdata->advProgress.timesLostBossRace[gGT->bossID]; return; } // if this is the last weapon set (next is nullptr) - if ((meta)[9] == 0) + if (((struct MetaDataBOSS*)(int)bossMeta + sizeof(struct MetaDataBOSS))->throwFlag == NULL) { if ( // track progress of NEXT set // percentage of track length - (gGT.level1.ptr_restart_points[(meta)[8]].distToFinish << 3)) + (gGT.level1.ptr_restart_points[((struct MetaDataBOSS*)(int)bossMeta + sizeof(struct MetaDataBOSS))->trackCheckpoint].distToFinish << 3)) { uVar3 = 0xffff; if ( ( - ((meta)[2] == 0x66) || - ((meta)[2] == 100)) && + ((bossMeta)[2] == 0x66) || + ((bossMeta)[2] == 100)) && (sdata->unk_8008d42C == 5)) { - uVar3 = (meta)[1]; + uVar3 = (bossMeta)[1]; } - meta = data.bossWeaponMetaPtr[0]; + bossMeta = data.bossWeaponMetaPtr[0]; // if levelID is not oxide station if (gGT->levelID != 0xd) { // set boss weapon meta to the one type it can be on this hub - meta = data.bossWeaponMetaPtr[data.metaDataLEV[gGT->levelID].hubID]; + bossMeta = data.bossWeaponMetaPtr[data.metaDataLEV[gGT->levelID].hubID]; } if (uVar3 != 0xffff) { - meta[1] = (char)uVar3; + bossMeta->throwFlag = (char)uVar3; } } } @@ -405,75 +402,75 @@ void DECOMP_PickupBots_Update(void) else { // distToFinish less than... - if (nextDriver->distanceToFinish_curr < + if (botDriver->distanceToFinish_curr < // track progress of NEXT set // percentage of track length - (gGT.level1.ptr_restart_points[(meta)[8]].distToFinish) << 3) + (gGT.level1.ptr_restart_points[((struct MetaDataBOSS*)(int)bossMeta + 8)->trackCheckpoint].distToFinish) << 3) { bVar8 = 0xff; if ( ( - ((meta)[2] == 0x66) || - (iVar4 = -0x10000, (meta)[2] == 100)) && + ((bossMeta)[2] == 0x66) || + (iVar4 = -0x10000, (bossMeta)[2] == 100)) && (iVar4 = -0x10000, sdata->unk_8008d42C == 5)) { - bVar8 = (meta)[1]; + bVar8 = (bossMeta)[1]; iVar4 = (uint)bVar8 << 0x10; } // next set - meta = (meta)[8]; + bossMeta = ((struct MetaDataBOSS*)(int)bossMeta + 8); if (iVar4 >> 0x10 != -1) { - (meta)[9] = bVar8; + (bossMeta)[9] = bVar8; } } } // set new boss meta - (meta)[0] = meta; + (bossMeta)[0] = bossMeta; - if (meta[3] == 0) + if (bossMeta[3] == 0) { // run this once per second if (sdata->unk_8008d428 == 0x1e) { - if ((nextDriver->botFlags & 0x80) == 0) + if ((botDriver->botFlags & 0x80) == 0) { if (*(short*)0x8008d42a == 0) { - sVar11 = *(short *)(nextDriver + 0x5b8); + sVar11 = botDriver->botPath; if (sVar11 == 2) goto LAB_80040ba0; if (sVar11 == 1) { - *(char *)(nextDriver + 0x627) = 0; + *(char *)(botDriver + 0x627) = 0; sdata->unk_8008d428 = 0; *(short*)0x8008d42a = sVar11; - nextDriver->botFlags |= 0x40; + botDriver->botFlags |= 0x40; } } else { - if (*(short *)(nextDriver + 0x5b8) == 0) + if (botDriver->botPath == NULL) { LAB_80040ba0: - uVar5 = nextDriver->botFlags; - *(char *)(nextDriver + 0x627) = 1; + uVar5 = botDriver->botFlags; + *(char *)(botDriver + 0x627) = 1; } else { - if (*(short *)(nextDriver + 0x5b8) != 1) + if (botDriver->botPath != 1) goto LAB_80040bf8; - uVar5 = nextDriver->botFlags; - *(char *)(nextDriver + 0x627) = 2; + uVar5 = botDriver->botFlags; + *(char *)(botDriver + 0x627) = 2; *(short*)0x8008d42a = 0; } sdata->unk_8008d428 = 0; - nextDriver->botFlags = uVar5 | 0x40; + botDriver->botFlags = uVar5 | 0x40; } } } @@ -481,7 +478,7 @@ void DECOMP_PickupBots_Update(void) // count up else { - if ((nextDriver->botFlags & 0x40) == 0) + if ((botDriver->botFlags & 0x40) == 0) { sdata->unk_8008d428 += 1; } @@ -490,9 +487,9 @@ void DECOMP_PickupBots_Update(void) LAB_80040bf8: // cooldown, cant shoot weapons till finished - if (0 < *(int *)0x8008d8e4) + if (0 < sdata->bossCooldown) { - *(int *)0x8008d8e4 -= 1; + sdata->bossCooldown -= 1; return; } @@ -500,48 +497,48 @@ void DECOMP_PickupBots_Update(void) uVar3 = RngDeadCoed(&bss); // new cooldown - *(int *)0x8008d8e4 = + sdata->bossCooldown = // random [0 to 16] + (uVar3 & 0x10) + // min cooldown for boss - *(short *)(meta + 4) + 0xc + + bossMeta->weaponCooldown // number of times you lost the event - sdata->advProgress.timesLostBossRace[gGT->bossID] * 4; + sdata->advProgress.timesLostBossRace[gGT->bossID]]; - bVar8 = meta[2]; - uVar5 = bVar8; - if (bVar8 == 100) + u_char weaponType = bossMeta->weaponType; + weaponID = weaponType; + if (weaponType == 0x64) { // weapon (tnt) - uVar5 = 3; + weaponID = 3; } else { - if (bVar8 == 0x65) + if (weaponType == 0x65) { // weapon (bomb) - uVar5 = 1; + weaponID = 1; } else { - if (bVar8 == 0x66) + if (weaponType == 0x66) { // weapon (potion) - uVar5 = 4; + weaponID = 4; } else { - if (bVar8 == 0xf) + if (weaponType == 0xf) { - uVar5 = 0xffffffff; + weaponID = 0xffffffff; } } } } - uVar3 = *(u_short *)(meta + 6); + uVar3 = bossMeta->juiceFlag; if ((uVar3 & 2) == 0) { LAB_80040d9c: @@ -553,163 +550,165 @@ void DECOMP_PickupBots_Update(void) sVar11 = sdata->unk_8008d42C + 1; if (sdata->unk_8008d42C < 5) goto LAB_80040da0; - bVar8 = meta[2]; - if (bVar8 == 100) + weaponType = bossMeta->weaponType; + if (weaponType == 0x64) { // weapon (tnt) - uVar5 = 3; + weaponID = 3; - if (meta[1] != 3) + if (bossMeta->throwFlag != 3) { - meta[1] = 3; + bossMeta->throwFlag = 3; sdata->unk_8008d42C = 5; - *(u_short *)(meta + 6) = uVar3 | 1; + bossMeta->juiceFlag = uVar3 | 1; sVar11 = sdata->unk_8008d42C; goto LAB_80040da0; } } else { - if (bVar8 == 0x65) + if (weaponType == 0x65) { // weapon (bomb) - uVar5 = 1; + weaponID = 1; // swap each frame between juiced and not juiced // not juiced, then juiced up if ((uVar3 & 1) == 0) { - *(u_short *)(meta + 6) = uVar3 | 1; + bossMeta->juiceFlag = uVar3 | 1; sdata->unk_8008d42C = 5; // weapon (tnt) - uVar5 = 3; + weaponID = 3; sVar11 = sdata->unk_8008d42C; goto LAB_80040da0; } // already juiced, unjuice - *(u_short *)(meta + 6) = uVar3 & 0xfffe; + bossMeta->juiceFlag = uVar3 & ~1; goto LAB_80040d9c; } sVar11 = sdata->unk_8008d42C; - if (bVar8 != 0x66) + if (weaponType != 0x66) goto LAB_80040da0; // weapon (potion) - uVar5 = 4; + weaponID = 4; - if (meta[1] != 3) + if (bossMeta->throwFlag != 3) { - meta[1] = 3; + bossMeta->throwFlag = 3; sdata->unk_8008d42C = 5; // give 10 wumpa - *(u_short *)(meta + 6) |= 1; + bossMeta->juiceFlag |= 1; sVar11 = sdata->unk_8008d42C; goto LAB_80040da0; } } - meta[1] = 2; + bossMeta->throwFlag = 2; sdata->unk_8008d42C = 0; // dont use 10 wumpa - *(u_short *)(meta + 6) &= 0xfffe; + bossMeta->juiceFlag &= 0xfffe; sVar11 = sdata->unk_8008d42C; } LAB_80040da0: sdata->unk_8008d42C = sVar11; - bVar8 = meta[1]; - uVar3 = (u_short)(bVar8 == 2); + u_char throwFlag = bossMeta->throwFlag; + u_short weaponFlags = (throwFlag == 2); uVar9 = 0; - if (-1 < (int)(uVar5 << 0x10)) + + // if weapon ID is valid + if (-1 < (int)(weaponID << 0x10)) { // backup numWumpa - backupWumpa = nextDriver->numWumpas; + backupWumpa = botDriver->numWumpas; - if ((*(u_short *)(meta + 6) & 1) != 0) + if ((bossMeta->juiceFlag & 1) != 0) { // 10 wumpa uVar9 = 10; } // wumpa - nextDriver->numWumpas = uVar9; + botDriver->numWumpas = uVar9; // weaponID - nextDriver->heldItemID = uVar5; + botDriver->heldItemID = weaponID; - if ((uVar5 - 3 & 0xffff) < 2) + if ((weaponID - 3 & 0xffff) < 2) { // Player / AI structure + 0x4a shows driver index (0-7) // get the character ID of P1 and P2 (or boss) - sVar11 = data.characterIDs[nextDriver->driverID]; - sVar2 = data.characterIDs[currDriver->driverID]; + enemyID = data.characterIDs[botDriver->driverID]; + playerID = data.characterIDs[thisDriver->driverID]; - uVar10 = 0xf; + voiceID = 15; } else { // Player / AI structure + 0x4a shows driver index (0-7) - uVar10 = 10; + voiceID = 10; // get the character ID of P1 and P2 (or boss) - sVar11 = data.characterIDs[nextDriver->driverID]; - sVar2 = data.characterIDs[currDriver->driverID]; + enemyID = data.characterIDs[botDriver->driverID]; + playerID = data.characterIDs[thisDriver->driverID]; - uVar3 = (u_short)(bVar8 == 2) | 2; + // shoot backwards + weaponFlags = (u_short)(throwFlag == 2) | 2; } // Make driver talk - Voiceline_RequestPlay(uVar10, sVar11, sVar2); + Voiceline_RequestPlay(voiceID, enemyID, playerID); // If weapon is bomb - if (nextDriver->heldItemID == 1) + if (bossDrivers->heldItemID == 1) { // Pinstripe or Oxide // VehPickupItem_ShootNow (boss) - VehPickupItem_ShootNow(nextDriver, 2, uVar3); + VehPickupItem_ShootNow(botDriver, 2, weaponFlags); } else { - sVar11 =uVar5; if ( ( // Papu or Oxide // If your weapon is potion - (nextDriver->heldItemID == 4) && + (botDriver->heldItemID == 4) && - (uVar3 == 1)) && + (weaponFlags == 1)) && // If you are on oxide station (gGT->levelID == 0xd)) { // VehPickupItem_ShootNow (boss) // Fire two potions (see oxide boss challenge) - VehPickupItem_ShootNow(nextDriver, sVar11, 1); - VehPickupItem_ShootNow(nextDriver,sVar11, 1); + VehPickupItem_ShootNow(botDriver, weaponID, 1); + VehPickupItem_ShootNow(botDriver, weaponID, 1); } else { // VehPickupItem_ShootNow (boss) - VehPickupItem_ShootNow(nextDriver, sVar11, uVar3); + VehPickupItem_ShootNow(botDriver, weaponID, weaponFlags); if (// Roo, Joe, Oxide ( // If your weapon is TNT or Nitro - (nextDriver->heldItemID == 3) && + (botDriver->heldItemID == 3) && - (meta[1] == 3)) && + (bossMeta->throwFlag == 3)) && (sdata->unk_8008d42C != 5)) { @@ -719,10 +718,10 @@ void DECOMP_PickupBots_Update(void) } // You have no weapon - nextDriver->heldItemID = 0xf; + botDriver->heldItemID = 0xf; // Set number of wumpa fruit - nextDriver->numWumpas = backupWumpa; + botDriver->numWumpas = backupWumpa; } return; } diff --git a/decompile/WorkInProgress/src/RefreshCard/RefreshCard_BoolGhostForLEV.c b/decompile/WorkInProgress/src/RefreshCard/RefreshCard_BoolGhostForLEV.c new file mode 100644 index 000000000..7a01f91d7 --- /dev/null +++ b/decompile/WorkInProgress/src/RefreshCard/RefreshCard_BoolGhostForLEV.c @@ -0,0 +1,18 @@ +int RefreshCard_BoolGhostForLEV(u_short trackID) +{ + short numGhost = 0; + + // if ghost profiles are present + if (sdata->numGhostProfilesSaved){ + // loop through ghost profiles + for (char i = 0; i < sdata->numGhostProfilesSaved - 1; i++) + { + // Check trackID of each profile + if (sdata->ghostProfile_memcard[i].trackID == trackID) + { + numGhost++; + } + } + } + return numGhost; +} \ No newline at end of file diff --git a/decompile/WorkInProgress/src/RefreshCard/RefreshCard_GetResult.c b/decompile/WorkInProgress/src/RefreshCard/RefreshCard_GetResult.c new file mode 100644 index 000000000..24906c222 --- /dev/null +++ b/decompile/WorkInProgress/src/RefreshCard/RefreshCard_GetResult.c @@ -0,0 +1,23 @@ +#include + +u_int RefreshCard_GetResult(short searchResult) +{ + // MC_RESULT_FINISHED + if ((searchResult == 8) && + ((sdata->memcardUnk1 & 6) != 0)) + { + return true; + } + + u_int boolFound = false; + + if (((sdata->memcardUnk1 & 6) == 0) && + // if frame3 == frame4 + (sdata->frame3_memcardAction == sdata->frame4_memcardAction) && + (sdata->frame3_memcardSlot == sdata->frame4_memcardSlot)) + { + // is desired_memcardResult == WhatYouLookFor? + boolFound = (sdata->desired_memcardResult == searchResult); + } + return boolFound; +} \ No newline at end of file diff --git a/decompile/WorkInProgress/src/RefreshCard/RefreshCard_GhostEncodeByte.c b/decompile/WorkInProgress/src/RefreshCard/RefreshCard_GhostEncodeByte.c new file mode 100644 index 000000000..3ca5ff12a --- /dev/null +++ b/decompile/WorkInProgress/src/RefreshCard/RefreshCard_GhostEncodeByte.c @@ -0,0 +1,44 @@ +#include + +u_int RefreshCard_GhostEncodeByte(int currByte) +{ + // only called from RefreshCard_GhostEncodeProfile + + u_int uVar1; + short sVar2; + + sVar2 = (short)currByte; + if (sVar2 < 10) + { + return currByte + 0x30U & 0xff; + } + if (sVar2 < 0x24) + { + return currByte + 0x37U & 0xff; + } + if (sVar2 < 0x3e) + { + uVar1 = currByte + 0x3dU & 0xff; + } + else + { + uVar1 = 0x2d; + if (sVar2 != 0x3e) + { + return 0x5f; + } + } + return uVar1; +} + +int RefreshCard_GhostDecodeByte(char currByte) +{ + // only called from RefreshCard_GhostDecodeProfile + + if (currByte == 0x2d) return 0x3e; + if (currByte == 0x5f) return 0x3f; + if (currByte < 0x3a) return (short)(currByte - 0x30); + if (0x5a < currByte) return (short)(currByte - 0x3d); + + return (short)(currByte - 0x37); +} \ No newline at end of file diff --git a/decompile/WorkInProgress/src/RefreshCard/RefreshCard_NextMemcardAction.c b/decompile/WorkInProgress/src/RefreshCard/RefreshCard_NextMemcardAction.c new file mode 100644 index 000000000..06bd0ee0c --- /dev/null +++ b/decompile/WorkInProgress/src/RefreshCard/RefreshCard_NextMemcardAction.c @@ -0,0 +1,24 @@ +#include + +void RefreshCard_NextMemcardAction(u_short memcardSlot, u_short memcardAction, u_char* filename, u_char* memcardIcon, struct GhostHeader* ghost, u_short filesize) +{ + sdata->memcardUnk1 &= ~(0x8); + + sdata->frame2_memcardAction = memcardAction; + sdata->frame2_memcardSlot = memcardSlot; + + sdata->frame4_memcardAction = memcardAction; + sdata->frame4_memcardSlot = memcardSlot; + + // Save filename (BASCUS...) + sdata->ghostProfile_fileName = filename; + + // Save icon (crash/ghost/psyqhand) + sdata->ghostProfile_fileIconHeader = memcardIcon; + + // pointer to ghostHeader (not memcard) + sdata->ghostProfile_ptrGhostHeader = ghost; + + // size (3E00) + sdata->ghostProfile_size3E00 = filesize; +} \ No newline at end of file diff --git a/decompile/WorkInProgress/src/VEHICLE/VehPhysCrash_AI.c b/decompile/WorkInProgress/src/VEHICLE/VehPhysCrash_AI.c new file mode 100644 index 000000000..f5a19b428 --- /dev/null +++ b/decompile/WorkInProgress/src/VEHICLE/VehPhysCrash_AI.c @@ -0,0 +1,26 @@ +#include + +void VehPhysCrash_AI(struct Driver* bot, Vec3 *v) +{ + sdata->unk_rot[0] = (u_short)bot->botNavFrame->rot[0] << 4; + sdata->unk_rot[1] = (u_short)bot->botNavFrame->rot[1] << 4; + sdata->unk_rot[2] = (u_short)bot->botNavFrame->rot[2] << 4; + + // convert 3 rotation shorts into rotation matrix + ConvertRotToMatrix((MATRIX*)0x8009ae38, &sdata->unk_rot[0]); + + *(int*)0x8009ae28 = (int)(((MATRIX*)0x8009ae38)->m[0][2] << 0x10) >> 0x14; + *(int*)0x8009ae2c = (int)(((MATRIX*)0x8009ae38)->m[1][2] << 0x10) >> 0x14; + *(int*)0x8009ae30 = (int)((MATRIX*)0x8009ae38)->m[2][2] >> 0x14; + + int botSpeed = FP8_INT(*(int*)0x8009ae28 * v->x + *(int*)0x8009ae2c * v->y + *(int*)0x8009ae30 * v->z); + + *(int *)(bot + 0x5d4) = botSpeed; + *(int *)(bot + 0x5d8) = v->x - (*(int*)0x8009ae28 * FP8_INT(botSpeed)); + + int projSpeed = *(int*)0x8009ae30 * botSpeed; + + bot->botFlags |= 8; + + *(int *)(bot + 0x5e0) = v->y - FP8_INT(projSpeed); +} \ No newline at end of file diff --git a/decompile/WorkInProgress/src/VEHICLE/VehPhysCrash_Attack.c b/decompile/WorkInProgress/src/VEHICLE/VehPhysCrash_Attack.c new file mode 100644 index 000000000..d6cc76bc9 --- /dev/null +++ b/decompile/WorkInProgress/src/VEHICLE/VehPhysCrash_Attack.c @@ -0,0 +1,99 @@ +#include + +int VehPhysCrash_Attack(struct Driver *driver1, struct Driver *driver2, int param_3, int param_4) +{ + // if driver (1) is not using mask weapon + if ((driver1->actionsFlagSet & 0x800000) == 0) + { + // if driver (2) is using mask weapon + if ((driver2->actionsFlagSet & 0x800000) != 0) + { + // param_1 was hit with a mask weapon + driver1->ChangeState_param2 = 2; + driver1->ChangeState_param4 = 6; + driver1->ChangeState_param3 = driver2; + + if (((param_3 != 0) && (driver1->kartState != KS_BLASTED)) && + (driver1->invincibleTimer == 0)) + { + OtherFX_DriverCrashing( + + // if driver is supposed to echo + *(u_short *)((int)driver1 + 0x2ca) & 1, + + 0xff); + + // Make driver talk + Voiceline_RequestPlay(1, data.characterIDs[driver1->driverID], 0x10); + } + } + + // if one driver has a bubble, and the other does not + if ((driver2->instBubbleHold != 0) && (driver1->instBubbleHold == 0)) + { + // driver -> bubbleInst -> thread -> object + struct Shield *bubble = driver2->instBubbleHold->thread->object; + + bubble->flags |= 8; + + // clear bubbleInst pointer + driver2->instBubbleHold = 0; + + driver1->ChangeState_param2 = 2; + driver1->ChangeState_param4 = 0; + driver1->ChangeState_param3 = driver2; + + if ((param_3 != 0) && + + (( + // if driver is not blasted + driver1->kartState != KS_BLASTED && + + // if driver is not invincible + (driver1->invincibleTimer == 0)))) + { + OtherFX_DriverCrashing( + + // if driver is supposed to echo + (uint) * (u_short *)((int)driver1 + 0x2ca) & 1, + + 0xff); + + if (param_4 != 0) + { + OtherFX_Play(0x4f, 1); + } + + // Make driver talk + Voiceline_RequestPlay(1, data.characterIDs[driver1->driverID], 0x10); + } + } + + // if one driver squished the other with turbo + if ( + ( + ( + // force that the drivers collided is high + (0xa00 < sdata->unk_8008d9f4[0]) && + + // attacking driver has reserves + (driver2->reserves != 0)) && + + // attacking driver is using turbo weapon + ((driver2->actionsFlagSet & 0x200) != 0)) && + + // attacked driver has no reserves + (driver1->reserves == 0)) + { + // set forcedJump_trampoline on attacking driver + driver2->forcedJump_trampoline = 2; + + // attacked driver has been squished by attacking driver, + // this happens when one driver uses turbo weapon on another + driver1->ChangeState_param2 = 3; + driver1->ChangeState_param4 = 5; + driver1->ChangeState_param3 = driver2; + } + } + return param_3; +} \ No newline at end of file diff --git a/decompile/WorkInProgress/src/VEHICLE/VehPhysCrash_ConvertVecToSpeed.c b/decompile/WorkInProgress/src/VEHICLE/VehPhysCrash_ConvertVecToSpeed.c new file mode 100644 index 000000000..92e0336ca --- /dev/null +++ b/decompile/WorkInProgress/src/VEHICLE/VehPhysCrash_ConvertVecToSpeed.c @@ -0,0 +1,64 @@ +#include + +void DECOMP_VehPhysCrash_ConvertVecToSpeed(struct Driver* d, Vec3 *v) +{ + short speed3D; + long speed2D; + int projX; + int projY; + int projZ; + int projOnMovingDirAxis; + + // 2D movement: sqrt(x^2 + z^2 << 0x10) + speed2D = VehCalc_FastSqrt(v->x * v->x + v->z * v->z, 0x10); + + // 3D movement: sqrt(x^2 + y^2 + z^2 << 0x10) + speed3D = FP8(VehCalc_FastSqrt(v->x * v->x + v->y * v->y + v->z * v->z, 0x10)); + + // Set driver's 3D speed + d->speed = speed3D; + + // Calculate vertical axis rotation (y-axis) + speed2D = ratan2(FP8(v->y), speed2D); + d->axisRotationY = (short)speed2D; + + // Calculate horizontal axis rotation (x-axis) + speed2D = ratan2(v->x, v->z); + d->axisRotationX = (short)speed2D; + + // Project the velocity vector onto the moving direction axis + projOnMovingDirAxis = FP_INT( + v->x * (int)d->matrixMovingDir.m[0][1] + + v->y * (int)d->matrixMovingDir.m[1][1] + + v->z * (int)d->matrixMovingDir.m[2][1]); + + projX = (int)FP_INT(d->matrixMovingDir.m[0][1] * projOnMovingDirAxis); + projY = (int)FP_INT(d->matrixMovingDir.m[1][1] * projOnMovingDirAxis); + projZ = (int)FP_INT(d->matrixMovingDir.m[2][1] * projOnMovingDirAxis); + + // Calculate 3D projection speed + speed3D = FP8(VehCalc_FastSqrt(projX * projX + projY * projY + projZ * projZ, 0x10)); + + d->jumpHeightCurr = speed3D; + if (projOnMovingDirAxis < 0) { + d->jumpHeightCurr = -speed3D; + } + + // Calculate deviation from projection + projX = v->x - projX; + projY = v->y - projY; + projZ = v->z - projZ; + + // Compute approximate speed based on deviation + speed3D = FP8(VehCalc_FastSqrt(projX * projX + projY * projY + projZ * projZ, 0x10)); + + d->speedApprox = speed3D; + + if ( + projX * d->matrixMovingDir[0][2] + + projY * d->matrixMovingDir[1][2] + + projZ * d->matrixMovingDir[2][2] < 0) + { + d->speedApprox = -speed3D; + } +} diff --git a/include/namespace_Level.h b/include/namespace_Level.h index a16793848..d659a63fc 100644 --- a/include/namespace_Level.h +++ b/include/namespace_Level.h @@ -69,7 +69,27 @@ enum LevelID enum TerrainType { - TERRAIN_MUD = 14, + TERRAIN_ASPHALT, + TERRAIN_DIRT, + TERRAIN_GRASS, + TERRAIN_WOOD, + TERRAIN_WATER, + TERRAIN_STONE, + TERRAIN_ICE, + TERRAIN_TRACK, + TERRAIN_ICY_ROAD, + TERRAIN_SNOW, + TERRAIN_NONE, + TERRAIN_HARDPACK, + TERRAIN_METAL, + TERRAIN_FASTWATER, + TERRAIN_MUD, + TERRAIN_SIDESLIP, + TERRAIN_RIVERASPHALT, + TERRAIN_STEAMASPHALT, + TERRAIN_OCEANASPHALT, + TERRAIN_SLOWGRASS, + TERRAIN_SLOWDIRT }; // transparent parameter of getTPage() diff --git a/include/namespace_Main.h b/include/namespace_Main.h index 806b55ccf..88c689f54 100644 --- a/include/namespace_Main.h +++ b/include/namespace_Main.h @@ -68,8 +68,8 @@ enum GameMode2 INC_RELIC = 0x1000000, INC_KEY = 0x2000000, INC_TROPHY = 0x4000000, - CHEAT_TURBOCOUNT= 0x8000000 - // & 0x10000000 - LNG_CHANGE (EurRetail Only) + CHEAT_TURBOCOUNT= 0x8000000, + LNG_CHANGE = 0x10000000 // (EurRetail Only) }; // real ND name