mirror of
https://github.com/CTR-tools/CTR-ModSDK.git
synced 2025-02-23 23:00:57 +00:00
17229 lines
441 KiB
C
17229 lines
441 KiB
C
|
|
// VehAfterColl_GetSurface
|
|
int FUN_80057c44(uint param_1)
|
|
|
|
{
|
|
int iVar1;
|
|
|
|
iVar1 = param_1 << 4;
|
|
if (6 < param_1) {
|
|
iVar1 = 0;
|
|
}
|
|
return (int)&PTR_s_SOLID_80087f94 + iVar1;
|
|
}
|
|
|
|
|
|
// VehAfterColl_GetTerrain
|
|
int FUN_80057c68(uint param_1)
|
|
|
|
{
|
|
int iVar1;
|
|
|
|
iVar1 = param_1 << 6;
|
|
if (0x14 < param_1) {
|
|
iVar1 = 0;
|
|
}
|
|
return (int)&PTR_s_asphalt_800884cc + iVar1;
|
|
}
|
|
|
|
|
|
// VehBirth_TeleportSelf
|
|
void FUN_80057c8c(int param_1,uint param_2,int param_3)
|
|
|
|
{
|
|
byte bVar1;
|
|
short sVar2;
|
|
bool bVar3;
|
|
undefined *puVar4;
|
|
undefined uVar5;
|
|
undefined2 uVar6;
|
|
undefined4 uVar7;
|
|
code *pcVar8;
|
|
int iVar9;
|
|
undefined *puVar10;
|
|
uint uVar11;
|
|
int *piVar12;
|
|
ushort uVar13;
|
|
int iVar14;
|
|
int *piVar15;
|
|
undefined2 *puVar16;
|
|
short local_40;
|
|
short local_3e;
|
|
short local_3c;
|
|
short local_38;
|
|
short local_36;
|
|
short local_34;
|
|
short local_30;
|
|
short local_2e;
|
|
short local_2c;
|
|
|
|
puVar4 = PTR_DAT_8008d2ac;
|
|
puVar16 = (undefined2 *)0x0;
|
|
bVar3 = false;
|
|
|
|
// by default, dont spawn by a hub door
|
|
piVar15 = (int *)0x0;
|
|
|
|
// Check LEV data for nullptr
|
|
if (*(int **)(PTR_DAT_8008d2ac + 0x160) == (int *)0x0) {
|
|
return;
|
|
}
|
|
if (**(int **)(PTR_DAT_8008d2ac + 0x160) == 0) {
|
|
return;
|
|
}
|
|
|
|
// ground and wall quadblock flags
|
|
DAT_1f80012c = 0x3000;
|
|
|
|
DAT_1f800130 = 0;
|
|
|
|
// low-LOD collision (2 triangles)
|
|
DAT_1f80012a = 0;
|
|
|
|
// if numPlyrCurrGame is less than 3
|
|
if ((byte)PTR_DAT_8008d2ac[0x1ca8] < 3)
|
|
{
|
|
// high-LOD collision (8 triangles)
|
|
DAT_1f80012a = 2;
|
|
}
|
|
|
|
DAT_1f800134 = **(undefined4 **)(PTR_DAT_8008d2ac + 0x160);
|
|
*(uint *)(PTR_DAT_8008d2ac + 8) = *(uint *)(PTR_DAT_8008d2ac + 8) & 0xffffbfff;
|
|
puVar10 = PTR_DAT_8008d2ac;
|
|
|
|
// if you are mask grabbed
|
|
if ((param_2 & 1) == 0)
|
|
{
|
|
// Ordinary player position
|
|
local_38 = (short)((uint)*(undefined4 *)(param_1 + 0x2d4) >> 8);
|
|
local_36 = (short)((uint)*(undefined4 *)(param_1 + 0x2d8) >> 8) + 0x80;
|
|
local_34 = (short)((uint)*(undefined4 *)(param_1 + 0x2dc) >> 8);
|
|
}
|
|
|
|
// if you are spawning into the world for the first time,
|
|
// could be startline, or adv hub spawn in several places
|
|
else
|
|
{
|
|
// spawn in front of hub door, beach-to-gemstone
|
|
if (
|
|
// If you are at podium after winning a Key
|
|
(*(short *)(puVar4 + 0x2572) == 99) &&
|
|
|
|
// If you have one boss key
|
|
(*(int *)(puVar4 + 0x1e38) == 1)
|
|
)
|
|
{
|
|
// lev number instDef
|
|
iVar9 = *(int *)(*(int *)(puVar4 + 0x160) + 0xc);
|
|
|
|
// lev instDefs
|
|
piVar15 = *(int **)(*(int *)(puVar4 + 0x160) + 0x10);
|
|
|
|
iVar14 = 0;
|
|
|
|
// if there are instDefs
|
|
if (0 < iVar9)
|
|
{
|
|
// waste of addition
|
|
piVar12 = piVar15 + 3;
|
|
|
|
// loop through instDefs
|
|
do
|
|
{
|
|
// if door is found
|
|
if (
|
|
(
|
|
(
|
|
// InstDef+0xC+0xC (modelID) == 0x7a (STATIC_DOOR)
|
|
(*(short *)(piVar12 + 0xc) == 0x7a) &&
|
|
|
|
// if name == "door"
|
|
(*piVar15 == 0x726f6f64)
|
|
) &&
|
|
|
|
// InstDef+0xC-0x8 (name) == "#5"
|
|
(piVar12[-2] == 0x3523)
|
|
) &&
|
|
|
|
// last 8 bytes of 16-byte name, all zeros
|
|
((piVar12[-1] == 0 && (*piVar12 == 0)))
|
|
|
|
// then leave loop
|
|
) break;
|
|
|
|
// next InstDef
|
|
piVar12 = piVar12 + 0x10;
|
|
|
|
// loop counter
|
|
iVar14 = iVar14 + 1;
|
|
|
|
// next InstDef (0x10*4)
|
|
piVar15 = piVar15 + 0x10;
|
|
|
|
} while (iVar14 < iVar9);
|
|
|
|
// if the hub door was found, because not all instDefs were checked, then go to spawn
|
|
if (iVar14 < *(int *)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0xc)) goto code_r0x80057f18;
|
|
}
|
|
|
|
// no InstDef found with "door" title,
|
|
// so spawn outside boss door instead
|
|
piVar15 = (int *)0x0;
|
|
}
|
|
|
|
// If you not at hub-door after beating Roo
|
|
else
|
|
{
|
|
// if you are at podium for winning a trophy
|
|
if (*(short *)(PTR_DAT_8008d2ac + 0x2572) == 0x62)
|
|
{
|
|
// By default, you have all 4 trophies on a hub,
|
|
// but we are about to determine if that's true
|
|
bVar3 = true;
|
|
|
|
// loop counter
|
|
iVar14 = 0;
|
|
// Level ID
|
|
iVar9 = (*(int *)(PTR_DAT_8008d2ac + 0x1a10) + -0x1a) * 8;
|
|
|
|
// for iVar14 = 0; iVar14 < 4; iVar14++
|
|
do
|
|
{
|
|
// increment loop counter
|
|
iVar14 = iVar14 + 1;
|
|
|
|
// 0x8fba4 is where the adventure profile (currently loaded) begins
|
|
|
|
// if you do not have a trophy on this track
|
|
if (((uint)(&DAT_8008fba4)[(int)((int)*(short *)(&DAT_800840f4 + iVar9) + 6U) >> 5] >>
|
|
((int)*(short *)(&DAT_800840f4 + iVar9) + 6U & 0x1f) & 1) == 0)
|
|
{
|
|
// record that not all 4 trophies are collected on this hub
|
|
bVar3 = false;
|
|
break;
|
|
}
|
|
iVar9 = iVar9 + 2;
|
|
} while (iVar14 < 4);
|
|
|
|
// if you have all 4 trophies on a hub
|
|
if ((bVar3) &&
|
|
|
|
// 0x8fba4 is where the adventure profile (currently loaded) begins
|
|
// Level ID
|
|
(((uint)(&DAT_8008fba4)[(int)(*(int *)(PTR_DAT_8008d2ac + 0x1a10) + 0x44U) >> 5] >>
|
|
(*(int *)(PTR_DAT_8008d2ac + 0x1a10) + 0x44U & 0x1f) & 1) != 0)) {
|
|
|
|
// dont spawn outside boss garage
|
|
bVar3 = false;
|
|
}
|
|
}
|
|
}
|
|
code_r0x80057f18:
|
|
|
|
// if you just exited boss race
|
|
if ((*(uint *)(PTR_DAT_8008d2ac + 8) & 1) != 0)
|
|
{
|
|
// spawn outside boss door
|
|
bVar3 = true;
|
|
}
|
|
|
|
// if not spawning at hub door
|
|
if (piVar15 == (int *)0x0)
|
|
{
|
|
// if you want to spawn outside boss door
|
|
if (bVar3)
|
|
{
|
|
// position outside boss door
|
|
local_38 = *(short *)(*(int *)(*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0x144) + 0xc) +
|
|
0xc);
|
|
local_36 = *(short *)(*(int *)(*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0x144) + 0xc) +
|
|
0xe) + 0x80;
|
|
local_34 = *(short *)(*(int *)(*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0x144) + 0xc) +
|
|
0x10);
|
|
}
|
|
|
|
// If spawning anywhere else
|
|
else {
|
|
|
|
// If you're not in Adventure Arena,
|
|
// Therefore, if spawning at startline of race track
|
|
if ((*(uint *)PTR_DAT_8008d2ac & 0x100000) == 0) {
|
|
LAB_80058158:
|
|
// get index where driver should spawn (0-7)
|
|
bVar1 = (&DAT_8008d69c)[*(byte *)(param_1 + 0x4a)];
|
|
|
|
// racer crossed the start line backwards,
|
|
// so lap doesn't count when race starts
|
|
*(uint *)(param_1 + 0x2c8) = *(uint *)(param_1 + 0x2c8) | 0x1000000;
|
|
|
|
// set distToFinish_checkpoint = level -> distSpawnToFinish
|
|
*(int *)(param_1 + 0x48c) =
|
|
(uint)*(ushort *)(*(int *)(*(int *)(puVar10 + 0x160) + 0x14c) + 6) << 3;
|
|
|
|
// convert spawn index to byte index,
|
|
// each spawn position is 3 ints (x,y,z)
|
|
iVar9 = (uint)bVar1 * 0xc;
|
|
|
|
// get position where each of the 8 drivers should spawn, from LEV
|
|
local_38 = *(short *)(*(int *)(puVar10 + 0x160) + iVar9 + 0x6c);
|
|
local_36 = *(short *)(*(int *)(puVar10 + 0x160) + iVar9 + 0x6e) + 0x80;
|
|
local_34 = *(short *)(*(int *)(puVar10 + 0x160) + iVar9 + 0x70);
|
|
}
|
|
|
|
// if you are in adventure arena
|
|
else
|
|
{
|
|
// if no podium reward
|
|
if (*(short *)(PTR_DAT_8008d2ac + 0x2572) == 0) {
|
|
|
|
// ivar9 = level you were in previously
|
|
iVar9 = *(int *)(PTR_DAT_8008d2ac + 0x1eb4);
|
|
|
|
// if you just came from any of these...
|
|
if (
|
|
|
|
// main menu, or adv character garage
|
|
((iVar9 == 0x27) || (iVar9 == 0x28)) ||
|
|
|
|
// nowhere?, or cutscene?
|
|
((iVar9 == -1 || ((iVar9 == 0x40 || (iVar9 - 0x2cU < 0x14)))))) goto LAB_80058158;
|
|
|
|
// get position where driver should spawn on map,
|
|
// outside warppad they previously entered
|
|
|
|
// AH_WarpPad_GetSpawnPosRot
|
|
puVar16 = (undefined2 *)FUN_800abafc(&local_30);
|
|
local_38 = local_30;
|
|
local_36 = local_2e + 0x80;
|
|
local_34 = local_2c;
|
|
}
|
|
|
|
// if you have a podium reward
|
|
else
|
|
{
|
|
// spawn on the podium in the adv hub
|
|
local_38 = **(short **)(*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0x144) + 0xc);
|
|
local_36 = *(short *)(*(int *)(*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0x144) +
|
|
0xc) + 2) + 0x80;
|
|
local_34 = *(short *)(*(int *)(*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0x144) +
|
|
0xc) + 4);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// if spawning at hub door
|
|
else
|
|
{
|
|
// do trigonometry to take hub door
|
|
|
|
*(uint *)(PTR_DAT_8008d2ac + 8) = *(uint *)(PTR_DAT_8008d2ac + 8) | 0x4000;
|
|
|
|
// Cosine(angle)
|
|
// instDef rotY
|
|
iVar9 = FUN_8003d1c0((int)*(short *)(piVar15 + 0xe));
|
|
|
|
// Cosine(angle)
|
|
// instDef rotY+400 (perpendicular)
|
|
iVar14 = FUN_8003d1c0((int)*(short *)(piVar15 + 0xe) + 0x400);
|
|
|
|
// posX =
|
|
// instDef posX + (where door starts)
|
|
// doorLengthX + (to get to midpoint between two doors)
|
|
// perpendicularX (to spawn away from door)
|
|
local_38 = *(short *)(piVar15 + 0xc) + (short)(iVar9 * 800 >> 0xc) +
|
|
(short)((iVar14 << 9) >> 0xc);
|
|
|
|
// posY = instDef posY + random height offset
|
|
local_36 = *(short *)((int)piVar15 + 0x32) + 0x17a;
|
|
|
|
// Sine(angle)
|
|
// instDef rotY
|
|
iVar9 = FUN_8003d184((int)*(short *)(piVar15 + 0xe));
|
|
|
|
// Sine(angle)
|
|
// instDef rotY+400 (perpendicular)
|
|
iVar14 = FUN_8003d184((int)*(short *)(piVar15 + 0xe) + 0x400);
|
|
|
|
// posZ =
|
|
// instDef posZ + (where door starts)
|
|
// doorLengthZ + (to get to midpoint between two doors)
|
|
// perpendicularZ (to spawn away from door)
|
|
local_34 = *(short *)(piVar15 + 0xd) + (short)(iVar9 * 800 >> 0xc) +
|
|
(short)((iVar14 << 9) >> 0xc);
|
|
}
|
|
}
|
|
local_40 = local_38;
|
|
local_3c = local_34;
|
|
local_3e = local_36 + -0x100;
|
|
|
|
// COLL_SearchTree_FindQuadblock_Touching
|
|
FUN_8001eb0c(&local_40,&local_38,&DAT_1f800108,0);
|
|
|
|
// if collision was not found
|
|
if (DAT_1f800146 == 0) {
|
|
*(undefined2 *)(param_1 + 0x370) = 0;
|
|
*(undefined2 *)(param_1 + 0x372) = 0x1000;
|
|
*(undefined2 *)(param_1 + 0x374) = 0;
|
|
}
|
|
|
|
// if it was found
|
|
else {
|
|
*(undefined2 *)(param_1 + 0x370) = DAT_1f800178;
|
|
*(undefined2 *)(param_1 + 0x372) = DAT_1f80017a;
|
|
*(undefined2 *)(param_1 + 0x374) = DAT_1f80017c;
|
|
*(undefined4 *)(param_1 + 0x354) = DAT_1f800188;
|
|
}
|
|
|
|
// loop counter
|
|
iVar14 = 0;
|
|
|
|
// set all normal vectors to spawn
|
|
*(undefined2 *)(param_1 + 0x360) = *(undefined2 *)(param_1 + 0x370);
|
|
*(undefined2 *)(param_1 + 0x368) = *(undefined2 *)(param_1 + 0x370);
|
|
*(undefined2 *)(param_1 + 0x362) = *(undefined2 *)(param_1 + 0x372);
|
|
*(undefined2 *)(param_1 + 0x36a) = *(undefined2 *)(param_1 + 0x372);
|
|
*(undefined2 *)(param_1 + 0x364) = *(undefined2 *)(param_1 + 0x374);
|
|
*(undefined2 *)(param_1 + 0x36c) = *(undefined2 *)(param_1 + 0x374);
|
|
|
|
iVar9 = param_1;
|
|
|
|
// for iVar14 = 0; iVar14 < 1; iVar14++
|
|
do
|
|
{
|
|
// set normal vector to spawn
|
|
*(undefined2 *)(iVar9 + 0x378) = *(undefined2 *)(param_1 + 0x368);
|
|
*(undefined2 *)(iVar9 + 0x37a) = *(undefined2 *)(param_1 + 0x36a);
|
|
iVar14 = iVar14 + 1; // increment loop counter
|
|
*(undefined2 *)(iVar9 + 0x37c) = *(undefined2 *)(param_1 + 0x36c);
|
|
|
|
iVar9 = iVar9 + 8;
|
|
|
|
} while (iVar14 < 1);
|
|
|
|
// player structure X, Y, Z
|
|
*(int *)(param_1 + 0x2d4) = (int)(short)DAT_1f800124 << 8;
|
|
*(int *)(param_1 + 0x2d8) = (DAT_1f800124._2_2_ + param_3) * 0x100;
|
|
*(int *)(param_1 + 0x2dc) = (int)((uint)DAT_1f800128 << 0x10) >> 8;
|
|
|
|
// duplicate of coordinate variables
|
|
*(undefined4 *)(param_1 + 0x2e4) = *(undefined4 *)(param_1 + 0x2d8);
|
|
*(undefined4 *)(param_1 + 0x2e0) = *(undefined4 *)(param_1 + 0x2d4);
|
|
*(undefined4 *)(param_1 + 0x2e8) = *(undefined4 *)(param_1 + 0x2dc);
|
|
|
|
// save quadblock height
|
|
*(int *)(param_1 + 0x2d0) = (int)DAT_1f800124._2_2_ << 8;
|
|
|
|
puVar4 = PTR_DAT_8008d2ac;
|
|
|
|
// if you are spawning into the world for the first time,
|
|
// could be startline, or adv hub spawn in several places
|
|
if ((param_2 & 1) != 0)
|
|
{
|
|
if (piVar15 == (int *)0x0)
|
|
{
|
|
// if spawning outside boss door
|
|
if (bVar3)
|
|
{
|
|
// get desired rotation of driver when leaving portal, or spawning at startline
|
|
uVar13 = *(short *)(*(int *)(*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0x144) + 0xc) +
|
|
0x14) + 0x400U & 0xfff;
|
|
|
|
*(ushort *)(param_1 + 0x2ee) = uVar13;
|
|
|
|
// if just finished a boss race
|
|
if ((*(uint *)(puVar4 + 8) & 1) != 0) {
|
|
|
|
// Level ID is citadel city
|
|
if (*(int *)(puVar4 + 0x1a10) == 0x1d)
|
|
{
|
|
// rotate 90 degrees to the right,
|
|
// so you dont have a wall in your face
|
|
uVar13 = uVar13 + 0x400;
|
|
}
|
|
|
|
// if not...
|
|
else
|
|
{
|
|
// Level ID == 25
|
|
// Level ID == GemStone Valley
|
|
if ((*(int *)(puVar4 + 0x1a10) == 0x19) &&
|
|
|
|
// If you just exited hot air skyway,
|
|
// just finished pinstripe boss,
|
|
// spawned by oxide's door
|
|
(*(int *)(puVar4 + 0x1eb4) == 7)
|
|
)
|
|
{
|
|
// use default rotation, face oxide's door
|
|
*(ushort *)(param_1 + 0x2ee) = uVar13;
|
|
|
|
goto LAB_80058438;
|
|
}
|
|
|
|
// If driver spawned to any other boss,
|
|
// for any other reason
|
|
|
|
// rotate 180 degrees, facing away from boss door
|
|
uVar13 = *(short *)(param_1 + 0x2ee) + 0x800;
|
|
}
|
|
|
|
// bitwise AND, do not go over 0x1000 (360 degrees)
|
|
*(ushort *)(param_1 + 0x2ee) = uVar13 & 0xfff;
|
|
}
|
|
LAB_80058438:
|
|
*(uint *)(PTR_DAT_8008d2ac + 8) = *(uint *)(PTR_DAT_8008d2ac + 8) & 0xfffffffc;
|
|
}
|
|
|
|
// if not outside boss door
|
|
else {
|
|
|
|
// If you're not in Adventure Arena
|
|
if ((*(uint *)PTR_DAT_8008d2ac & 0x100000) == 0)
|
|
{
|
|
LAB_800584f8:
|
|
|
|
// position index on starting line
|
|
iVar9 = (uint)(byte)(&DAT_8008d69c)[*(byte *)(param_1 + 0x4a)] * 0xc;
|
|
|
|
// rotation data of all 8 drivers on starting line
|
|
*(undefined2 *)(param_1 + 0x2ec) =
|
|
*(undefined2 *)(*(int *)(PTR_DAT_8008d2ac + 0x160) + iVar9 + 0x72);
|
|
sVar2 = *(short *)(*(int *)(puVar4 + 0x160) + iVar9 + 0x74);
|
|
*(short *)(param_1 + 0x2ee) = sVar2;
|
|
uVar6 = *(undefined2 *)(*(int *)(puVar4 + 0x160) + iVar9 + 0x76);
|
|
}
|
|
|
|
// if on adv hub
|
|
else
|
|
{
|
|
// podium reward
|
|
if (*(short *)(PTR_DAT_8008d2ac + 0x2572) != 0)
|
|
{
|
|
// set rotation, expecting driver to spawn on podium
|
|
*(ushort *)(param_1 + 0x2ee) =
|
|
*(ushort *)
|
|
(*(int *)(*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0x144) + 0xc) + 8) & 0xfff
|
|
;
|
|
goto LAB_80058568;
|
|
}
|
|
|
|
|
|
if (
|
|
(
|
|
// If you just came from the main menu
|
|
(*(int *)(PTR_DAT_8008d2ac + 0x1eb4) == 0x27) ||
|
|
|
|
// If you just came from "nothing"
|
|
(*(int *)(PTR_DAT_8008d2ac + 0x1eb4) == -1)
|
|
|
|
// if WarpPad_ReturnToMap failed to find a matching portal
|
|
) || (puVar16 == (undefined2 *)0x0))
|
|
|
|
// skip
|
|
goto LAB_800584f8;
|
|
|
|
// rotation data from spawning near hub warppad,
|
|
// after leaving a race or event
|
|
*(undefined2 *)(param_1 + 0x2ec) = *puVar16;
|
|
sVar2 = puVar16[1];
|
|
*(short *)(param_1 + 0x2ee) = sVar2;
|
|
uVar6 = puVar16[2];
|
|
}
|
|
*(ushort *)(param_1 + 0x2ee) = sVar2 + 0x400U & 0xfff;
|
|
*(undefined2 *)(param_1 + 0x2f0) = uVar6;
|
|
}
|
|
}
|
|
else {
|
|
*(ushort *)(param_1 + 0x2ee) = *(short *)(piVar15 + 0xe) + 0x800U & 0xfff;
|
|
*(uint *)(puVar4 + 8) = *(uint *)(puVar4 + 8) & 0xfffffffc;
|
|
}
|
|
}
|
|
LAB_80058568:
|
|
|
|
// set speed to zero
|
|
*(undefined2 *)(param_1 + 0x38c) = 0;
|
|
|
|
*(undefined2 *)(param_1 + 0x38e) = 0;
|
|
*(undefined2 *)(param_1 + 0x390) = 0;
|
|
*(undefined2 *)(param_1 + 0x392) = 0;
|
|
*(undefined2 *)(param_1 + 0x3b2) = 0;
|
|
*(undefined2 *)(param_1 + 0x39a) = *(undefined2 *)(param_1 + 0x2ee);
|
|
*(undefined2 *)(param_1 + 0x2f4) = *(undefined2 *)(param_1 + 0x2ec);
|
|
*(undefined2 *)(param_1 + 0x2f6) = *(undefined2 *)(param_1 + 0x2ee);
|
|
*(undefined2 *)(param_1 + 0x2f8) = *(undefined2 *)(param_1 + 0x2f0);
|
|
|
|
if (
|
|
(piVar15 != (int *)0x0) &&
|
|
|
|
// if spawning into world (not mask grab)
|
|
((param_2 & 1) != 0)
|
|
)
|
|
{
|
|
// spawn with speed (what? when does that ever happen?)
|
|
*(undefined2 *)(param_1 + 0x38c) = 0xa00;
|
|
}
|
|
|
|
// set animation to zero
|
|
*(undefined *)(*(int *)(param_1 + 0x1c) + 0x52) = 0;
|
|
|
|
// get number of frames in animation
|
|
uVar7 = FUN_8005b0f4(*(undefined4 *)(param_1 + 0x1c),0);
|
|
|
|
// VehFrameInst_GetStartFrame
|
|
uVar6 = FUN_8005b0c4(0,uVar7);
|
|
|
|
// Animation frame
|
|
*(undefined2 *)(*(int *)(param_1 + 0x1c) + 0x54) = uVar6;
|
|
|
|
// Set Scale (x, y, z)
|
|
*(undefined2 *)(*(int *)(param_1 + 0x1c) + 0x1c) = 0xccc;
|
|
*(undefined2 *)(*(int *)(param_1 + 0x1c) + 0x1e) = 0xccc;
|
|
*(undefined2 *)(*(int *)(param_1 + 0x1c) + 0x20) = 0xccc;
|
|
|
|
*(undefined *)(param_1 + 0x4c) = 0;
|
|
*(undefined *)(param_1 + 0x4d) = 0;
|
|
*(undefined2 *)(param_1 + 0x3fc) = 0;
|
|
*(undefined2 *)(param_1 + 0x46) = 0;
|
|
*(undefined2 *)(param_1 + 0x48) = 0;
|
|
*(undefined2 *)(param_1 + 0x3c6) = 0;
|
|
*(undefined2 *)(param_1 + 0x3d2) = 0;
|
|
*(undefined2 *)(param_1 + 0x3c8) = 0;
|
|
*(undefined2 *)(param_1 + 0x2f2) = 0;
|
|
*(undefined2 *)(param_1 + 0x2fa) = 0;
|
|
*(undefined *)(param_1 + 0x4ff) = 0;
|
|
*(undefined2 *)(param_1 + 0x40c) = 0;
|
|
*(undefined4 *)(param_1 + 0x350) = 0;
|
|
*(undefined4 *)(param_1 + 0x490) = 0;
|
|
*(undefined2 *)(param_1 + 0xc) = 0;
|
|
*(undefined *)(param_1 + 0x4fe) = 0;
|
|
|
|
//turn off 7th and 20th bits of Actions Flag set (means ? (7) and racer is not in the air (20))
|
|
*(uint *)(param_1 + 0x2c8) = *(uint *)(param_1 + 0x2c8) & 0xfff7ffbf;
|
|
if ((param_2 & 2) == 0) {
|
|
return;
|
|
}
|
|
iVar9 = 0xc;
|
|
|
|
// driver -> instane -> thread -> modelIndex == "player" of any kind
|
|
if (*(short *)(*(int *)(*(int *)(param_1 + 0x1c) + 0x6c) + 0x44) == 0x18)
|
|
{
|
|
// This erases all driver funcPtrs, 12 funcPtrs, 0x30 bytes total,
|
|
// it is the strangest way to do it, but that's what it does
|
|
|
|
// pointer = driver + 0x30
|
|
iVar14 = param_1 + 0x30;
|
|
|
|
// erase 12 (0xC) function pointers from
|
|
// driver struct, 0x54 - 0x84 (0x30 bytes),
|
|
// but erase them backwards
|
|
do {
|
|
*(undefined4 *)(iVar14 + 0x54) = 0;
|
|
iVar9 = iVar9 + -1;
|
|
iVar14 = iVar14 + -4;
|
|
} while (-1 < iVar9);
|
|
|
|
// CAM_StartOfRace
|
|
FUN_80018d20(PTR_DAT_8008d2ac + (uint)*(byte *)(param_1 + 0x4a) * 0xdc + 0x1498);
|
|
|
|
puVar4 = PTR_DAT_8008d2ac;
|
|
|
|
// if you are not in cutscene and not in main menu
|
|
if ((*(uint *)PTR_DAT_8008d2ac & 0x20002000) == 0) {
|
|
puVar10 = (undefined *)0x0;
|
|
}
|
|
|
|
// if you are in cutscene or main menu
|
|
else
|
|
{
|
|
// 0x80058c44 is an empty function that does nothing
|
|
puVar10 = &FUN_80058c44;
|
|
}
|
|
|
|
// driver -> instance -> thread -> funcThTick = puVar10
|
|
*(undefined **)(*(int *)(*(int *)(param_1 + 0x1c) + 0x6c) + 0x2c) = puVar10;
|
|
|
|
|
|
// If you're not in Adventure Arena
|
|
if ((*(uint *)puVar4 & 0x100000) == 0)
|
|
{
|
|
// VehStuckProc_RevEngine_Init
|
|
pcVar8 = FUN_80067f4c;
|
|
}
|
|
|
|
// If you're in Adventure Arena
|
|
else
|
|
{
|
|
// VehPhysProc_Driving_Init
|
|
pcVar8 = FUN_80062b74;
|
|
}
|
|
|
|
// set OnInit function
|
|
*(code **)(param_1 + 0x54) = pcVar8;
|
|
}
|
|
|
|
// lapIndex = 0
|
|
*(undefined *)(param_1 + 0x44) = 0;
|
|
|
|
// numWumpa = 0
|
|
*(undefined *)(param_1 + 0x30) = 0;
|
|
|
|
puVar4 = PTR_DAT_8008d2ac;
|
|
|
|
// lapTime = 0
|
|
*(undefined4 *)(param_1 + 0x40) = 0;
|
|
|
|
// no lap progress
|
|
*(undefined4 *)(param_1 + 0x488) = 0;
|
|
|
|
//turn off 21th and 26th flags of Actions Flag set
|
|
//(means ? (21) and racer hasn't finished the race)
|
|
*(uint *)(param_1 + 0x2c8) = *(uint *)(param_1 + 0x2c8) & 0xfdefffff;
|
|
|
|
// If unlimited wumpa cheat is enabled
|
|
if ((*(uint *)(puVar4 + 8) & 0x200) != 0)
|
|
{
|
|
// Set wumpa to 99
|
|
*(undefined *)(param_1 + 0x30) = 99;
|
|
}
|
|
|
|
//set Held item to none
|
|
*(undefined *)(param_1 + 0x36) = 0xf;
|
|
|
|
//set Held item Quantity to 0
|
|
*(undefined *)(param_1 + 0x37) = 0;
|
|
|
|
puVar4 = PTR_DAT_8008d2ac;
|
|
|
|
// collected zero C-T-R letters
|
|
*(undefined4 *)(param_1 + 0x4cc) = 0;
|
|
|
|
// cheat flags
|
|
uVar11 = *(uint *)(puVar4 + 8);
|
|
|
|
// set weaponID to mask
|
|
uVar5 = 7;
|
|
|
|
// if unlimited masks is disabled
|
|
if ((uVar11 & 0x400) == 0)
|
|
{
|
|
// if unlimited turbos is disabled
|
|
if ((uVar11 & 0x800) == 0)
|
|
{
|
|
// set weaponID to bomb
|
|
uVar5 = 1;
|
|
|
|
// if infinite bombs is disabled
|
|
if ((uVar11 & 0x400000) == 0) goto LAB_800587cc;
|
|
|
|
goto LAB_800587c0;
|
|
}
|
|
|
|
// set weaponID to turbo
|
|
*(undefined *)(param_1 + 0x36) = 0;
|
|
}
|
|
else
|
|
{
|
|
LAB_800587c0:
|
|
// set weaponID
|
|
*(undefined *)(param_1 + 0x36) = uVar5;
|
|
}
|
|
|
|
//set Held item Quantity to 9 (Cheat related)
|
|
*(undefined *)(param_1 + 0x37) = 9;
|
|
|
|
LAB_800587cc:
|
|
puVar4 = PTR_DAT_8008d2ac;
|
|
|
|
// set driver's life limit to the global life limit
|
|
*(undefined4 *)(param_1 + 0x4e4) = *(undefined4 *)(PTR_DAT_8008d2ac + 0x1d88);
|
|
|
|
if (
|
|
// If Permanent Invisibility Cheat is Enabled
|
|
((*(uint *)(puVar4 + 8) & 0x8000) != 0) &&
|
|
|
|
// Player / AI structure + 0x4a shows driver index (0-7)
|
|
|
|
// driver ID must be less than numPlyrCurrGame,
|
|
// which makes the cheat apply to players and not AIs
|
|
(*(byte *)(param_1 + 0x4a) < (byte)puVar4[0x1ca8]))
|
|
{
|
|
// instance flags
|
|
*(uint *)(*(int *)(param_1 + 0x1c) + 0x28) =
|
|
*(uint *)(*(int *)(param_1 + 0x1c) + 0x28) & 0xfff8ffff;
|
|
|
|
// instance flags
|
|
*(uint *)(*(int *)(param_1 + 0x1c) + 0x28) =
|
|
*(uint *)(*(int *)(param_1 + 0x1c) + 0x28) | 0x60000;
|
|
|
|
// invisible timer
|
|
*(undefined4 *)(param_1 + 0x28) = 0x2d00;
|
|
}
|
|
|
|
|
|
// If Super Engine Cheat is enabled
|
|
if ((*(uint *)(PTR_DAT_8008d2ac + 8) & 0x10000) != 0) {
|
|
*(undefined2 *)(param_1 + 0x38) = 0x2d00;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// VehBirth_TeleportAll
|
|
void FUN_80058898(undefined4 param_1,uint param_2)
|
|
|
|
{
|
|
// pointer to player address
|
|
int iVar1;
|
|
|
|
// iteration counter
|
|
int iVar2;
|
|
iVar2 = 0;
|
|
|
|
do
|
|
{
|
|
// address of player structure, idk which
|
|
iVar1 = *(int *)(PTR_DAT_8008d2ac + ((iVar2 << 0x10) >> 0xe) + 0x24ec);
|
|
|
|
// if player structure is not nullptr
|
|
if (iVar1 != 0)
|
|
{
|
|
// driver -> instance -> thread -> modelIndex == "robotcar" of any kind
|
|
if (*(short *)(*(int *)(*(int *)(iVar1 + 0x1c) + 0x6c) + 0x44) == 0x3f)
|
|
{
|
|
// BOTS_GotoStartingLine
|
|
FUN_8001702c();
|
|
}
|
|
else
|
|
{
|
|
// VehBirth_TeleportSelf (startline)
|
|
FUN_80057c8c(iVar1,param_2 | 1,0);
|
|
}
|
|
}
|
|
|
|
// increment loop iteration counter
|
|
iVar2 = iVar2 + 1;
|
|
|
|
} while (iVar2 * 0x10000 >> 0x10 < 8);
|
|
return;
|
|
}
|
|
|
|
|
|
// VehBirth_GetModelByName
|
|
int * FUN_80058948(int *param_1)
|
|
|
|
{
|
|
int *piVar1;
|
|
int **ppiVar2;
|
|
int *piVar3;
|
|
int iVar4;
|
|
|
|
piVar3 = (int *)0x0;
|
|
|
|
// loop counter
|
|
iVar4 = 0;
|
|
|
|
// array to character models loaded,
|
|
// maximum of 4, used in VS mode
|
|
ppiVar2 = (int **)&DAT_80083a10;
|
|
|
|
// for iVar4 = 0; iVar4 < 3; iVar4++
|
|
do {
|
|
|
|
// dereference model pointer
|
|
piVar1 = *ppiVar2;
|
|
|
|
// if model pointer exists,
|
|
// check first 16 bytes of model
|
|
// for a matching string
|
|
if (
|
|
(
|
|
(
|
|
// if model pointer exists
|
|
(piVar1 != (int *)0x0) &&
|
|
|
|
// 0-3
|
|
(*piVar1 == *param_1)
|
|
) &&
|
|
|
|
// 4-7
|
|
(piVar1[1] == param_1[1])
|
|
) &&
|
|
(
|
|
(
|
|
// 8-11
|
|
piVar1[2] == param_1[2] &&
|
|
|
|
// 12-15
|
|
(piVar1[3] == param_1[3])
|
|
)
|
|
)
|
|
)
|
|
{
|
|
// character found, return pointer
|
|
return piVar1;
|
|
}
|
|
|
|
// loop counter
|
|
iVar4 = iVar4 + 1;
|
|
|
|
// pointer to next model
|
|
ppiVar2 = ppiVar2 + 1;
|
|
|
|
} while (iVar4 < 3);
|
|
|
|
if (
|
|
// if PLYROBJECTLIST is not nullptr
|
|
(DAT_8008d870 != (int **)0x0) &&
|
|
|
|
// make sure elements of PLYROBJECTLIST are valid
|
|
(piVar3 = *DAT_8008d870, piVar3 != (int *)0x0)
|
|
|
|
)
|
|
{
|
|
// PLYROBJECTLIST, used for arcade (6-8 players)
|
|
ppiVar2 = DAT_8008d870;
|
|
|
|
// loop until all strings are checked (until current is not nullptr)
|
|
do
|
|
{
|
|
// if model pointer exists,
|
|
// check first 16 bytes of model
|
|
// for a matching string
|
|
if (
|
|
(
|
|
(
|
|
// if model exists
|
|
(*piVar3 == *param_1) &&
|
|
|
|
// 0-3
|
|
(piVar3[1] == param_1[1])
|
|
) &&
|
|
|
|
// 4-7
|
|
(piVar3[2] == param_1[2])
|
|
) &&
|
|
|
|
// 8-11
|
|
(piVar3[3] == param_1[3])
|
|
)
|
|
{
|
|
// character found, return pointer
|
|
return piVar3;
|
|
}
|
|
|
|
// increment pointer
|
|
ppiVar2 = ppiVar2 + 1;
|
|
|
|
// set to pointer
|
|
piVar3 = *ppiVar2;
|
|
|
|
} while (piVar3 != (int *)0x0);
|
|
}
|
|
return piVar3;
|
|
}
|
|
|
|
|
|
|
|
// VehBirth_SetConsts(driver*), based on driver class
|
|
void FUN_80058a60(int param_1)
|
|
{
|
|
|
|
uint uVar1;
|
|
int iVar2;
|
|
uint uVar3;
|
|
int iVar4;
|
|
|
|
// loop counter
|
|
uVar3 = 0;
|
|
|
|
// array of structure indexes
|
|
// 0x80088A0C
|
|
iVar4 = -0x7ff775f4;
|
|
|
|
// 0x1c * loop counter
|
|
iVar2 = 0;
|
|
|
|
// for uVar3 = 0; uVar3 < 0x41 (65); uVar3++
|
|
do {
|
|
|
|
// Get the size of the variable
|
|
uVar1 = *(uint *)(iVar4 + 8);
|
|
|
|
// If variable size == 2 bytes
|
|
if (uVar1 == 2) {
|
|
|
|
// *(2 bytes *) (driver + metaPhys[i]->driverOffset) =
|
|
*(undefined2 *)(param_1 + *(int *)(iVar4 + 4)) =
|
|
|
|
// *(2 bytes *) (metaPhys[i]->value[meta[charID].engineID])
|
|
*(undefined2 *)(&DAT_80088a18 + *(int *)(&DAT_80086d90 + (int)(short)(&DAT_80086e84)[*(byte *)(param_1 + 0x4a)] * 0x10) * 4 + iVar2);
|
|
}
|
|
|
|
// if variable size != 2 bytes
|
|
else {
|
|
|
|
// if variable size < 3 bytes
|
|
if (uVar1 < 3) {
|
|
|
|
|
|
// If variable size == 1 byte
|
|
if (uVar1 == 1) {
|
|
|
|
// *(1 byte *) (driver + metaPhys[i]->driverOffset) =
|
|
*(undefined *)(param_1 + *(int *)(iVar4 + 4)) =
|
|
|
|
// *(byte *) (metaPhys[i]->value[meta[charID].engineID])
|
|
(&DAT_80088a18)[*(int *)(&DAT_80086d90 + (int)(short)(&DAT_80086e84)[*(byte *)(param_1 + 0x4a)] * 0x10) * 4 + iVar2];
|
|
}
|
|
|
|
/*
|
|
Sep3
|
|
else
|
|
printf("**error** invalid phys size \'%s\' %ld\n",*puVar3,puVar3[2]);
|
|
*/
|
|
|
|
}
|
|
|
|
// if variable size >= 3 bytes
|
|
else {
|
|
|
|
// if variable size == 4 bytes
|
|
if (uVar1 == 4) {
|
|
|
|
// *(4 bytes *) (driver + metaPhys[i]->driverOffset) =
|
|
*(undefined4 *)(param_1 + *(int *)(iVar4 + 4)) =
|
|
|
|
// *(4 bytes *) (metaPhys[i]->value[meta[charID].engineID])
|
|
*(undefined4 *) (&DAT_80088a18 + *(int *)(&DAT_80086d90 + (int)(short)(&DAT_80086e84)[*(byte *)(param_1 + 0x4a)] * 0x10) * 4 + iVar2);
|
|
}
|
|
}
|
|
}
|
|
|
|
// array of structure indexes += 0x1C
|
|
iVar4 = iVar4 + 0x1c;
|
|
|
|
// loop counter
|
|
uVar3 = uVar3 + 1;
|
|
|
|
iVar2 = iVar2 + 0x1c;
|
|
|
|
} while (uVar3 < 0x41);
|
|
|
|
return;
|
|
}
|
|
|
|
// VehBirth_EngineAudio_AllPlayers
|
|
void FUN_80058ba4(void)
|
|
|
|
{
|
|
uint uVar1;
|
|
int iVar2;
|
|
|
|
// pointer to first Player thread
|
|
iVar2 = *(int *)(PTR_DAT_8008d2ac + 0x1b2c);
|
|
|
|
// while pointer is valid
|
|
while (iVar2 != 0)
|
|
{
|
|
// Player / AI structure + 0x4a shows driver index (0-7)
|
|
|
|
// thread -> driver -> driverID
|
|
uVar1 = (uint)*(byte *)(*(int *)(iVar2 + 0x30) + 0x4a);
|
|
|
|
// Initialize car engine sound
|
|
FUN_80028880(
|
|
|
|
// engineID from metadata, given characterID
|
|
*(int *)(&DAT_80086d90 + (int)(short)(&DAT_80086e84)[uVar1] * 0x10) * 4 + uVar1 &
|
|
0xffff,0x8080);
|
|
|
|
// go to next Player in linked list
|
|
iVar2 = *(int *)(iVar2 + 0x10);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Veh_NullThread
|
|
void FUN_80058c44()
|
|
{
|
|
return;
|
|
}
|
|
|
|
// VehBirth_TireSprites
|
|
void FUN_80058c4c(int param_1)
|
|
|
|
{
|
|
undefined *puVar1;
|
|
int iVar2;
|
|
int *piVar3;
|
|
|
|
puVar1 = PTR_DAT_8008d2ac;
|
|
|
|
// thread -> driver object
|
|
piVar3 = *(int **)(param_1 + 0x30);
|
|
|
|
// IconGroup* tireAnim
|
|
iVar2 = *(int *)(PTR_DAT_8008d2ac + 0x2114);
|
|
|
|
// wheel scale
|
|
*(undefined2 *)(piVar3 + 1) = 0xccc;
|
|
|
|
// wheelSprites = tireAnim->icons
|
|
*piVar3 = iVar2 + 0x14;
|
|
|
|
if (
|
|
// Player / AI structure + 0x4a shows driver index (0-7)
|
|
|
|
// if character ID is oxide
|
|
((&DAT_80086e84)[*(byte *)((int)piVar3 + 0x4a)] == 0xf) &&
|
|
|
|
// Level ID != 39
|
|
// Not in Main Menu
|
|
(*(int *)(puVar1 + 0x1a10) != 0x27)
|
|
)
|
|
{
|
|
*(undefined2 *)(piVar3 + 1) = 0;
|
|
}
|
|
|
|
piVar3[2] = 0x2e808080;
|
|
*(undefined2 *)(piVar3 + 0xef) = 0xa00;
|
|
|
|
// item held to 0xF (nothing)
|
|
*(undefined *)((int)piVar3 + 0x36) = 0xf;
|
|
|
|
// related to engine sound
|
|
*(undefined *)((int)piVar3 + 0x47b) = 2;
|
|
|
|
*(undefined2 *)((int)piVar3 + 0x362) = 0x1000;
|
|
*(undefined2 *)((int)piVar3 + 0x36a) = 0x1000;
|
|
*(undefined2 *)((int)piVar3 + 0x412) = 0x600;
|
|
*(undefined2 *)((int)piVar3 + 0x3e6) = 10000;
|
|
|
|
// VehAfterColl_GetTerrain (air)
|
|
iVar2 = FUN_80057c68(10);
|
|
piVar3[0xd6] = iVar2;
|
|
|
|
// get number of lives in battle
|
|
iVar2 = *(int *)(PTR_DAT_8008d2ac + 0x1d80);
|
|
|
|
// 0x4e8
|
|
// team in battle mode
|
|
piVar3[0x13a] = (uint)*(byte *)((int)piVar3 + 0x4a);
|
|
|
|
*(undefined2 *)(piVar3 + 0x13c) = 0xffff;
|
|
*(undefined2 *)(piVar3 + 0x13d) = 0xffff;
|
|
|
|
// 0x4e4
|
|
// player lives in battle mode
|
|
piVar3[0x139] = iVar2;
|
|
|
|
return;
|
|
}
|
|
|
|
// VehBirth_NonGhost
|
|
// param1 is thread
|
|
// param2 is driverID (0-7)
|
|
void FUN_80058d2c(int param_1,int param_2)
|
|
|
|
{
|
|
short sVar1;
|
|
undefined *puVar2;
|
|
undefined4 uVar3;
|
|
int iVar4;
|
|
int iVar5;
|
|
|
|
// model index = DYNAMIC_PLAYER,
|
|
// AI will override this right after
|
|
// the end of the function
|
|
*(undefined2 *)(param_1 + 0x44) = 0x18;
|
|
|
|
// unknown thread variables?
|
|
*(undefined2 *)(param_1 + 0x42) = 0x40;
|
|
*(undefined4 *)(param_1 + 0x38) = 0x1000;
|
|
*(undefined2 *)(param_1 + 0x3e) = 0x40;
|
|
|
|
// get pointer to game config
|
|
puVar2 = PTR_DAT_8008d2ac;
|
|
|
|
// unknown thread variables?
|
|
*(undefined2 *)(param_1 + 0x3c) = 0;
|
|
*(undefined2 *)(param_1 + 0x40) = 0;
|
|
|
|
// get object from thread
|
|
iVar5 = *(int *)(param_1 + 0x30);
|
|
|
|
// by default, get ID of first character
|
|
sVar1 = DAT_80086e84;
|
|
|
|
// if you are not in the main menu
|
|
if ((*(uint *)puVar2 & 0x2000) == 0)
|
|
{
|
|
// get ID of character, given param2
|
|
sVar1 = (&DAT_80086e84)[param_2];
|
|
}
|
|
|
|
// VehBirth_GetModelByName
|
|
uVar3 = FUN_80058948((&PTR_s_crash_80086d84)[(int)sVar1 * 4]);
|
|
|
|
// INSTANCE_Birth3D -- ptrModel, name, thread
|
|
uVar3 = FUN_8003086c(uVar3,uVar3,param_1);
|
|
|
|
// get pointer to game config
|
|
puVar2 = PTR_DAT_8008d2ac;
|
|
|
|
// give instance to thread
|
|
*(undefined4 *)(param_1 + 0x34) = uVar3;
|
|
|
|
// Ptr Model "Wake"
|
|
iVar4 = *(int *)(puVar2 + 0x226c);
|
|
|
|
// if "Wake" exists
|
|
if (iVar4 != 0)
|
|
{
|
|
// INSTANCE_Birth3D -- ptrModel, name, thread
|
|
iVar4 = FUN_8003086c(iVar4,iVar4,0);
|
|
|
|
// pointer to "Wake" instance
|
|
*(int *)(iVar5 + 0x4f8) = iVar4;
|
|
|
|
// instance flags
|
|
if (iVar4 != 0)
|
|
{
|
|
// make invisible, set to anim 1
|
|
*(uint *)(iVar4 + 0x28) = *(uint *)(iVar4 + 0x28) | 0x90;
|
|
}
|
|
|
|
// sep 3
|
|
// else
|
|
// player %d wake create failed
|
|
}
|
|
|
|
/*
|
|
sep 3
|
|
else
|
|
printf("wake not in level\n");
|
|
*/
|
|
|
|
// get instance from thread
|
|
iVar4 = *(int *)(param_1 + 0x34);
|
|
|
|
// if driverID is less than numPlyrCurrGame,
|
|
// "If driver belongs to human player"
|
|
if (param_2 < (int)(uint)(byte)PTR_DAT_8008d2ac[0x1ca8])
|
|
{
|
|
// instance flag
|
|
*(uint *)(iVar4 + 0x28) = *(uint *)(iVar4 + 0x28) | 0x4000000;
|
|
}
|
|
|
|
// give driverID to driver
|
|
*(undefined *)(iVar5 + 0x4a) = (char)param_2;
|
|
|
|
// give instance to driver
|
|
*(int *)(iVar5 + 0x1c) = iVar4;
|
|
|
|
// VehBirth_TireSprites
|
|
FUN_80058c4c(param_1);
|
|
|
|
// VehBirth_SetConsts(driver*), based on driver class
|
|
FUN_80058a60(iVar5);
|
|
|
|
// if you are in cutscene or in main menu
|
|
if ((*(uint *)PTR_DAT_8008d2ac & 0x20002000) != 0)
|
|
{
|
|
// funcThTick
|
|
// 0x80058c44 is an empty function that does nothing
|
|
*(undefined4 *)(param_1 + 0x2c) = 0x80058c44;
|
|
|
|
// make invisible
|
|
*(uint *)(iVar4 + 0x28) = *(uint *)(iVar4 + 0x28) | 0x80;
|
|
}
|
|
return;
|
|
}
|
|
|
|
// VehBirth_Player
|
|
struct Driver* FUN_80058ec0(int param_1)
|
|
|
|
{
|
|
char cVar1;
|
|
int iVar2;
|
|
struct Driver* iVar3;
|
|
|
|
// s_player_8008d614
|
|
// "player"
|
|
|
|
// PROC_BirthWithObject
|
|
// 0x62c = size
|
|
// 0 = no relation to param4
|
|
// 0x100 flag = LargeStackPool
|
|
// 0 = player thread bucket
|
|
iVar2 = FUN_8004205c(0x62c0100,0,s_player_8008d614,0);
|
|
|
|
// Get player pointer from the thread
|
|
iVar3 = *(int *)(iVar2 + 0x30);
|
|
|
|
// player Driver is 0x62C bytes large
|
|
memset(iVar3,0,0x62c);
|
|
|
|
// VehBirth_NonGhost
|
|
FUN_80058d2c(iVar2,param_1);
|
|
|
|
// Get Team that player chose from Battle Setup menu
|
|
cVar1 = PTR_DAT_8008d2ac[param_1 + 0x1da4];
|
|
|
|
// VehPhysProc_Driving_Init
|
|
*(undefined4 *)(iVar3 + 0x54) = 0x80062b74;
|
|
|
|
// Battle Team that the player is on
|
|
*(int *)(iVar3 + 0x4e8) = (int)cVar1;
|
|
|
|
return iVar3;
|
|
}
|
|
|
|
|
|
// VehCalc_InterpBySpeed
|
|
// param1 is current rotation
|
|
// param2 is speed of rotation
|
|
// param3 is desired rotation
|
|
int FUN_80058f54(int param_1,int param_2,int param_3)
|
|
|
|
{
|
|
int iVar1;
|
|
int iVar2;
|
|
|
|
// if desired rotation is less than current
|
|
if (param_3 < param_1)
|
|
{
|
|
// subtract current by a rate of "speed"
|
|
iVar2 = param_1 - param_2;
|
|
|
|
// if new rotation is less than desired
|
|
if (param_1 - param_2 < param_3)
|
|
{
|
|
// Just use desired rotation
|
|
return param_3;
|
|
}
|
|
}
|
|
|
|
// if desired rotation is not less than current
|
|
else
|
|
{
|
|
// make a copy of current
|
|
iVar1 = param_1;
|
|
if (
|
|
// desired <= current,
|
|
// we know desired is not less than current,
|
|
// so this really checks if it is current
|
|
(param_3 <= param_1) ||
|
|
(
|
|
// copy desired
|
|
iVar2 = param_3,
|
|
|
|
// add to rotation at rate of "speed"
|
|
iVar1 = param_1 + param_2,
|
|
|
|
// if new rotation overshoots desired,
|
|
// probably should say >=
|
|
param_1 + param_2 <= param_3)
|
|
)
|
|
{
|
|
// if current = desired
|
|
// if current is overshot past desired
|
|
|
|
// current = desired
|
|
iVar2 = iVar1;
|
|
}
|
|
}
|
|
|
|
// return new current
|
|
return iVar2;
|
|
}
|
|
|
|
// VehCalc_MapToRange
|
|
// Map value from [oldMin, oldMax] to [newMin, newMax]
|
|
// inverting newMin and newMax will give an inverse range mapping
|
|
int FUN_80058f9c(int param_1,int param_2,int param_3,int param_4,int param_5)
|
|
{
|
|
int iVar1;
|
|
|
|
// if value is lessor equal than oldMin, return newMin
|
|
if (param_1 <= param_2) {
|
|
return param_4;
|
|
}
|
|
|
|
// if value is less than old Max
|
|
if (param_1 < param_3)
|
|
{
|
|
|
|
// distance from old min, multiplied by new range
|
|
iVar1 = (param_1 - param_2) * (param_5 - param_4);
|
|
|
|
// get range of first min and max
|
|
param_3 = param_3 - param_2;
|
|
|
|
// if min === max, crash
|
|
if (param_3 == 0) {
|
|
trap(0x1c00);
|
|
}
|
|
|
|
// if min is less than max, crash
|
|
if ((param_3 == -1) && (iVar1 == -0x80000000)) {
|
|
trap(0x1800);
|
|
}
|
|
|
|
// new min, plus [...] / old range
|
|
return param_4 + iVar1 / param_3;
|
|
}
|
|
|
|
// return new max
|
|
return param_5;
|
|
}
|
|
|
|
|
|
// VehCalc_SteerAccel
|
|
undefined4
|
|
FUN_8005900c(int param_1,int param_2,int param_3,undefined4 param_4,undefined4 param_5,
|
|
undefined4 param_6)
|
|
|
|
{
|
|
// Crash Bandicoot:
|
|
// param_2: 0x4 SteerAccel_Stage2_FirstFrame
|
|
// param_3: 0x8 SteerAccel_Stage2_FrameLength
|
|
// param_4: 0x40 SteerAccel_Stage4_FirstFrame
|
|
// param_5: 0x800 SteerAccel_Stage1_MinSteer
|
|
// param_6: 0xC00 SteerAccel_Stage1_MaxSteer
|
|
|
|
// Steering Stage 1,
|
|
// if first 4 frames of steering
|
|
// increase steer acceleration as time passes
|
|
if (param_1 < param_2)
|
|
{
|
|
|
|
// map "frame" from [0,4] -> [0x800,0xC00]
|
|
|
|
// Map value from [oldMin, oldMax] to [newMin, newMax]
|
|
// inverting newMin and newMax will give an inverse range mapping
|
|
param_6 = FUN_80058f9c(param_1, 0,param_2, param_5,param_6);
|
|
}
|
|
|
|
else
|
|
{
|
|
// Steering Stage 3
|
|
// frames 12+
|
|
// decrease steer acceleration as time passes
|
|
if (param_2 + param_3 < param_1)
|
|
{
|
|
// map "frame" from [12,64] -> [0xC00,0]
|
|
|
|
// Map value from [oldMin, oldMax] to [newMin, newMax]
|
|
// inverting newMin and newMax will give an inverse range mapping
|
|
param_6 = FUN_80058f9c(param_1, param_2 + param_3,param_4, param_6,0);
|
|
}
|
|
}
|
|
|
|
// Steering Stage 2,
|
|
// next 0x8 frames (frame 4 to 12)
|
|
// max steer accel of 0xC00
|
|
return param_6;
|
|
|
|
// Steering Stage 4,
|
|
// part of Stage 3's mapping,
|
|
// for all steering after frame 64,
|
|
// steer acceleration is zero, so
|
|
// angular velocity is constant
|
|
}
|
|
|
|
|
|
// if you're interested in learning about the algorithm:
|
|
// https://en.wikipedia.org/wiki/Integer_square_root#Digit-by-digit_algorithm
|
|
|
|
// f(n, i) = sqrt(n<<i)
|
|
// VehCalc_FastSqrt(n, i)
|
|
uint FUN_80059070(uint param_1,uint param_2)
|
|
/*
|
|
f(n, 0) will always output the sqrt(n)
|
|
|
|
the idea for this function is to first computer the length of the square root in numbers of bits,
|
|
and then test each bit and see if it belongs to the square root. if so, keep the bit, otherwise discard.
|
|
*/
|
|
|
|
|
|
{
|
|
uint uVar1;
|
|
uint uVar2;
|
|
uint uVar3;
|
|
uint uVar4;
|
|
uint uVar5;
|
|
uint uVar6;
|
|
|
|
// result
|
|
uVar5 = 0;
|
|
|
|
// uVar4 = x + 1
|
|
uVar4 = 1;
|
|
|
|
// last_approximation = 0
|
|
uVar6 = 0;
|
|
|
|
uVar3 = 1 << (param_2 & 0x1f);
|
|
|
|
/* what this is doing is picking the least x that 4^x >= n
|
|
notice that:
|
|
4^x = n
|
|
log_4(n) = x
|
|
log_2(n) / log_2(4) = x
|
|
log_2(n) / 2 = x
|
|
x = log_2(sqrt(n))
|
|
|
|
in order words, x is the length in bits of the square root of n
|
|
*/
|
|
while ((uVar3 < param_1 && (uVar3 << 2 != 0))) {
|
|
uVar4 = uVar4 + 1;
|
|
uVar3 = uVar3 << 2;
|
|
}
|
|
|
|
uVar1 = 1 << (uVar4 + (param_2 - 1) & 0x1f);
|
|
|
|
// while 4^x != 0
|
|
while (uVar3 != 0) {
|
|
|
|
// current_approximation = result << x + 1
|
|
uVar2 = uVar5 << (uVar4 & 0x1f);
|
|
|
|
if ((int)uVar4 < 0) {
|
|
uVar2 = uVar5 >> (-uVar4 & 0x1f);
|
|
}
|
|
|
|
// current_approximation = (result << x + 1) + last_approximation + current_bit_squared
|
|
uVar2 = uVar2 + uVar6 + uVar3;
|
|
|
|
// if current_approximation <= n
|
|
if (uVar2 <= param_1) {
|
|
|
|
// result += current_bit
|
|
uVar5 = uVar5 + uVar1;
|
|
|
|
// last_approximation = current_approximation
|
|
uVar6 = uVar2;
|
|
}
|
|
|
|
// current_bit /= 2
|
|
uVar1 = uVar1 >> 1;
|
|
|
|
// current_bit_squared /= 4
|
|
uVar3 = uVar3 >> 2;
|
|
|
|
// (x + 1) -= 1
|
|
uVar4 = uVar4 - 1;
|
|
}
|
|
return uVar5;
|
|
}
|
|
|
|
|
|
// VehEmitter_Exhaust
|
|
int FUN_80059100(int param_1,int *param_2,int *param_3)
|
|
|
|
{
|
|
int iVar1;
|
|
undefined *puVar2;
|
|
int iVar3;
|
|
|
|
if (
|
|
// if driver is not using invisibility powerup
|
|
(*(int *)(param_1 + 0x28) == 0) &&
|
|
|
|
// if driver -> instSelf -> instFlags & INVISIBLE is false
|
|
((*(uint *)(*(int *)(param_1 + 0x1c) + 0x28) & 0x80) == 0)
|
|
)
|
|
{
|
|
// If you're in 1P mode
|
|
// high LOD exhaust
|
|
puVar2 = (undefined *)0x80089224;
|
|
|
|
// if numPlyrCurrGame is less than 3
|
|
if ((byte)PTR_DAT_8008d2ac[0x1ca8] < 3) {
|
|
|
|
// if numPlyrCurrGame is more than 1
|
|
if (1 < (byte)PTR_DAT_8008d2ac[0x1ca8]) {
|
|
|
|
// really only happens if numPlyrCurrGame is 2
|
|
// med LOD exhaust
|
|
puVar2 = (undefined *)0x80089344;
|
|
}
|
|
}
|
|
|
|
// if numPlyrCurrGame is 3 or 4
|
|
else
|
|
{
|
|
// low LOD exhaust
|
|
puVar2 = &DAT_80089464;
|
|
}
|
|
|
|
// driver -> instance -> thread -> modelIndex == "robotcar" of any kind
|
|
if (*(short *)(*(int *)(*(int *)(param_1 + 0x1c) + 0x6c) + 0x44) == 0x3f)
|
|
{
|
|
// low LOD exhaust
|
|
puVar2 = &DAT_80089464;
|
|
}
|
|
iVar3 = 1;
|
|
|
|
// driver -> instance -> flags
|
|
if (((*(uint *)(*(int *)(param_1 + 0x1c) + 0x28) & 0x2000) != 0) &&
|
|
((param_2[1] - param_3[1]) + *(int *)(param_1 + 0x2d8) < 0x100))
|
|
{
|
|
iVar3 = 7;
|
|
|
|
// exhaust when you're underwater,
|
|
// which makes bubbles comes out
|
|
puVar2 = &DAT_80089128;
|
|
}
|
|
|
|
// Create instance in particle pool
|
|
iVar1 = FUN_80040308(0,*(undefined4 *)(PTR_DAT_8008d2ac + iVar3 * 4 + 0x2114),puVar2);
|
|
|
|
// if particle exists
|
|
if (iVar1 != 0)
|
|
{
|
|
// posX
|
|
*(int *)(iVar1 + 0x24) = *(int *)(iVar1 + 0x24) + (*param_2 - *param_3);
|
|
|
|
// velX
|
|
*(undefined2 *)(iVar1 + 0x28) = *(undefined2 *)param_3;
|
|
|
|
// posY
|
|
*(int *)(iVar1 + 0x2c) = *(int *)(iVar1 + 0x2c) + (param_2[1] - param_3[1]);
|
|
|
|
// velY
|
|
*(undefined2 *)(iVar1 + 0x30) = *(undefined2 *)(param_3 + 1);
|
|
|
|
// posZ
|
|
*(int *)(iVar1 + 0x34) = *(int *)(iVar1 + 0x34) + (param_2[2] - param_3[2]);
|
|
|
|
// velZ
|
|
*(undefined2 *)(iVar1 + 0x38) = *(undefined2 *)(param_3 + 2);
|
|
|
|
*(undefined *)(iVar1 + 0x18) = *(undefined *)(*(int *)(param_1 + 0x1c) + 0x50);
|
|
|
|
// driver->instSelf
|
|
*(undefined4 *)(iVar1 + 0x20) = *(undefined4 *)(param_1 + 0x1c);
|
|
|
|
if (iVar3 == 7)
|
|
{
|
|
// Particle_FuncPtr_ExhaustUnderwater
|
|
*(undefined4 *)(iVar1 + 0x1c) = 0x8003ee20;
|
|
}
|
|
|
|
// if engine revving
|
|
if (*(char *)(param_1 + 0x376) == '\x04')
|
|
{
|
|
if (*(char *)(param_1 + 0x4fe) != '\x01') {
|
|
return iVar1;
|
|
}
|
|
}
|
|
|
|
// if not engine revving
|
|
else {
|
|
if ((int)*(short *)(param_1 + 0x3dc) < 0x81) {
|
|
return iVar1;
|
|
}
|
|
if ((int)(((uint)*(byte *)(param_1 + 0x477) + 2) * 0x20) < (int)*(short *)(param_1 + 0x3dc))
|
|
{
|
|
return iVar1;
|
|
}
|
|
}
|
|
*(ushort *)(iVar1 + 0x12) = *(ushort *)(iVar1 + 0x12) & 0xff9f | 0x40;
|
|
}
|
|
}
|
|
else {
|
|
iVar1 = 0;
|
|
}
|
|
return iVar1;
|
|
}
|
|
|
|
|
|
// VehEmitter_Sparks_Ground
|
|
void FUN_80059344(int param_1,undefined4 param_2)
|
|
|
|
{
|
|
int iVar1;
|
|
uint uVar2;
|
|
uint uVar3;
|
|
int iVar4;
|
|
int iVar5;
|
|
int iVar6;
|
|
int iVar7;
|
|
undefined4 uVar8;
|
|
undefined4 uVar9;
|
|
undefined4 uVar10;
|
|
int iVar11;
|
|
int iVar12;
|
|
int iVar13;
|
|
|
|
gte_ldVXY0(0);
|
|
gte_ldVZ0(0xffffe800);
|
|
gte_rtv0();
|
|
iVar4 = gte_stMAC1();
|
|
iVar5 = gte_stMAC2();
|
|
iVar6 = gte_stMAC3();
|
|
|
|
gte_ldVXY0(0x1800);
|
|
gte_ldVZ0(0);
|
|
gte_rtv0();
|
|
read_mt(iVar13,iVar12,iVar11);
|
|
|
|
gte_ldVXY0(0);
|
|
gte_ldVZ0(0xfffffe00);
|
|
gte_rtv0();
|
|
read_mt(uVar10,uVar9,uVar8);
|
|
|
|
iVar7 = 10;
|
|
do
|
|
{
|
|
// Create instance in particle pool
|
|
iVar1 = FUN_80040308(0,*(undefined4 *)(PTR_DAT_8008d2ac + 0x2114),param_2);
|
|
|
|
if (iVar1 != 0)
|
|
{
|
|
// RNG
|
|
uVar2 = FUN_8006c684(PTR_DAT_8008d2ac + 0x252c);
|
|
uVar3 = uVar2 & 0x7ff;
|
|
if ((uVar2 & 1) != 0) {
|
|
uVar3 = -uVar3;
|
|
}
|
|
|
|
// velocity variables
|
|
*(short *)(iVar1 + 0x28) =
|
|
*(short *)(iVar1 + 0x28) + (short)uVar10 + (short)((int)(uVar3 * iVar13) >> 0xc);
|
|
*(short *)(iVar1 + 0x30) =
|
|
*(short *)(iVar1 + 0x30) + (short)uVar9 + (short)((int)(uVar3 * iVar12) >> 0xc);
|
|
*(short *)(iVar1 + 0x38) =
|
|
*(short *)(iVar1 + 0x38) + (short)uVar8 + (short)((int)(uVar3 * iVar11) >> 0xc);
|
|
|
|
// position variables
|
|
*(int *)(iVar1 + 0x24) = *(int *)(iVar1 + 0x24) + iVar4 + *(short *)(iVar1 + 0x28);
|
|
*(int *)(iVar1 + 0x2c) = *(int *)(iVar1 + 0x2c) + iVar5 + *(short *)(iVar1 + 0x30);
|
|
*(int *)(iVar1 + 0x34) = *(int *)(iVar1 + 0x34) + iVar6 + *(short *)(iVar1 + 0x38);
|
|
|
|
// driver -> instSelf
|
|
*(undefined4 *)(iVar1 + 0x20) = *(undefined4 *)(param_1 + 0x1c);
|
|
|
|
*(undefined *)(iVar1 + 0x18) = *(undefined *)(*(int *)(param_1 + 0x1c) + 0x50);
|
|
}
|
|
iVar7 = iVar7 + -1;
|
|
} while (iVar7 != 0);
|
|
return;
|
|
}
|
|
|
|
|
|
// VehEmitter_Terrain_Ground
|
|
void FUN_80059558(int param_1,undefined4 param_2)
|
|
|
|
{
|
|
int iVar1;
|
|
int iVar2;
|
|
undefined4 uVar3;
|
|
int unaff_s0;
|
|
int unaff_s1;
|
|
int unaff_s2;
|
|
|
|
if (
|
|
// touching quadblock
|
|
((*(uint *)(param_1 + 0x2c8) & 1) != 0) &&
|
|
|
|
// not in accel prevention (not holding square)
|
|
((*(uint *)(param_1 + 0x2c8) & 8) == 0)
|
|
)
|
|
{
|
|
// abs fireSpeed
|
|
iVar1 = (int)*(short *)(param_1 + 0x39e);
|
|
if (iVar1 < 0) {
|
|
iVar1 = -iVar1;
|
|
}
|
|
|
|
if (iVar1 < 0x300)
|
|
{
|
|
// abs speedApprox
|
|
iVar1 = (int)*(short *)(param_1 + 0x38e);
|
|
if (iVar1 < 0) {
|
|
iVar1 = -iVar1;
|
|
}
|
|
|
|
if (iVar1 < 0x300) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
// if moving quickly
|
|
|
|
// 2 wheels spawn particles
|
|
iVar1 = 2;
|
|
|
|
// if sliding
|
|
if (*(char *)(param_1 + 0x376) == '\x02')
|
|
{
|
|
// 4 wheels spawn particles
|
|
iVar1 = 4;
|
|
}
|
|
|
|
// spawn particles on wheels
|
|
for (; iVar1 != 0; iVar1 = iVar1 + -1)
|
|
{
|
|
// front tire
|
|
if (iVar1 == 3)
|
|
{
|
|
// 0x1E, 0xA, 0x28
|
|
gte_ldVXY0(0xa001e);
|
|
uVar3 = 0x28;
|
|
gte_ldVZ0(0x28);
|
|
}
|
|
|
|
// back wheels
|
|
else if (iVar1 < 4) {
|
|
if (iVar1 == 2)
|
|
{
|
|
// -0x1E, 0xA, -0x28
|
|
gte_ldVXY0(0xaffe2);
|
|
uVar3 = 0xffffffec;
|
|
gte_ldVZ0(0xffffffec);
|
|
}
|
|
else
|
|
{
|
|
LAB_80059674:
|
|
// 0x1E, 0xA, -0x28
|
|
gte_ldVXY0(0xa001e);
|
|
uVar3 = 0xffffffec;
|
|
gte_ldVZ0(0xffffffec);
|
|
}
|
|
}
|
|
|
|
// == 4, (front tire)
|
|
else
|
|
{
|
|
if (iVar1 != 4) goto LAB_80059674;
|
|
|
|
// -0x1E, 0xA, 0x28
|
|
gte_ldVXY0(0xaffe2);
|
|
uVar3 = 0x28;
|
|
gte_ldVZ0(0x28);
|
|
}
|
|
gte_rtv0();
|
|
read_mt(unaff_s0,unaff_s1,unaff_s2);
|
|
|
|
// spawn particle
|
|
iVar2 = FUN_80040308(0,*(undefined4 *)(PTR_DAT_8008d2ac + 0x2114),param_2,uVar3);
|
|
|
|
if (iVar2 != 0)
|
|
{
|
|
// edit positions
|
|
*(int *)(iVar2 + 0x24) = *(int *)(iVar2 + 0x24) + unaff_s0 * 0x100;
|
|
*(int *)(iVar2 + 0x2c) = *(int *)(iVar2 + 0x2c) + unaff_s1 * 0x100;
|
|
*(int *)(iVar2 + 0x34) = *(int *)(iVar2 + 0x34) + unaff_s2 * 0x100;
|
|
|
|
gte_ldVXY0(CONCAT22(*(undefined2 *)(iVar2 + 0x30),*(undefined2 *)(iVar2 + 0x28)));
|
|
gte_ldVZ0((uint)*(ushort *)(iVar2 + 0x38));
|
|
gte_rtv0();
|
|
read_mt(unaff_s0,unaff_s1,unaff_s2);
|
|
|
|
// edit velocity
|
|
*(short *)(iVar2 + 0x28) = (short)unaff_s0;
|
|
*(short *)(iVar2 + 0x30) = (short)unaff_s1;
|
|
*(short *)(iVar2 + 0x38) = (short)unaff_s2;
|
|
|
|
// driver -> instSelf
|
|
*(undefined4 *)(iVar2 + 0x20) = *(undefined4 *)(param_1 + 0x1c);
|
|
|
|
*(undefined *)(iVar2 + 0x18) = *(undefined *)(*(int *)(param_1 + 0x1c) + 0x50);
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
// VehEmitter_Sparks_Wall
|
|
// param_1 is driver struct
|
|
// param_2 is always 0x800896c8, particle data for sparks
|
|
void FUN_80059780(int param_1,undefined4 param_2)
|
|
{
|
|
int iVar1;
|
|
int iVar2;
|
|
uint uVar3;
|
|
uint unaff_s1;
|
|
uint unaff_s2;
|
|
uint unaff_s3;
|
|
|
|
// no fire speed
|
|
if (*(short *)(param_1 + 0x39e) == 0)
|
|
{
|
|
iVar1 = (int)*(short *)(param_1 + 0x38e);
|
|
if (iVar1 < 0) {
|
|
iVar1 = -iVar1;
|
|
}
|
|
if (0x200 < iVar1) goto LAB_800597d0;
|
|
}
|
|
|
|
// fire speed
|
|
else
|
|
{
|
|
LAB_800597d0:
|
|
|
|
// if time against wall is less than 15 seconds
|
|
if (*(short *)(param_1 + 0x50) < 0x1c2)
|
|
{
|
|
// GAMEPAD_ShockFreq and GAMEPAD_ShockForce1
|
|
FUN_80026440(param_1, 8, 0);
|
|
FUN_800264c0(param_1, 8, 0x7f);
|
|
|
|
// increment time against wall
|
|
*(short *)(param_1 + 0x50) = *(short *)(param_1 + 0x50) + 1;
|
|
goto LAB_80059818;
|
|
}
|
|
}
|
|
|
|
// reset time against wall to zero
|
|
*(undefined2 *)(param_1 + 0x50) = 0;
|
|
uVar3 = param_2;
|
|
|
|
LAB_80059818:
|
|
|
|
if (*(short *)(param_1 + 0x38e) < 0x201) {
|
|
if (-0x201 < *(short *)(param_1 + 0x38e)) {
|
|
return;
|
|
}
|
|
|
|
// -0x2200, 0xa00, -0x1400
|
|
gte_ldVXY0(0xa00de00);
|
|
gte_ldVZ0(0xffffec00);
|
|
|
|
// 0x2200, 0xa00, -0x1400
|
|
gte_ldVXY1(0xa002200);
|
|
gte_ldVZ1(0xffffec00);
|
|
}
|
|
|
|
else
|
|
{
|
|
// -0x2200, 0xa00, 0x2800
|
|
gte_ldVXY0(0xa00de00);
|
|
gte_ldVZ0(0x2800);
|
|
|
|
// 0x2200, 0xa00, 0x2800
|
|
gte_ldVXY1(0xa002200);
|
|
gte_ldVZ1(0x2800);
|
|
}
|
|
|
|
gte_rtv0();
|
|
read_mt(unaff_s1,unaff_s2,unaff_s3);
|
|
gte_rtv1();
|
|
read_mt(uVar3,newVar1,newVar2);
|
|
|
|
// matrix
|
|
gte_ldL11L12(unaff_s1 & 0xffff | unaff_s2 << 0x10);
|
|
gte_ldL13L21(unaff_s3 & 0xffff | uVar3 << 0x10);
|
|
gte_ldL22L23(newVar1 & 0xffff | newVar2 << 0x10);
|
|
|
|
// driver->posWallColl - driver->posCurr
|
|
gte_ldVXY0(*(short *)(param_1 + 900) * 0x100 - *(int *)(param_1 + 0x2d4) & 0xffffU |
|
|
(*(short *)(param_1 + 0x386) * 0x100 - *(int *)(param_1 + 0x2d8)) * 0x10000);
|
|
gte_ldVZ0(*(short *)(param_1 + 0x388) * 0x100 - *(int *)(param_1 + 0x2dc));
|
|
|
|
gte_llv0();
|
|
|
|
iVar1 = gte_stMAC1();
|
|
iVar2 = gte_stMAC2();
|
|
if (iVar1 < iVar2) {
|
|
unaff_s1 = uVar3;
|
|
unaff_s2 = newVar1;
|
|
unaff_s3 = newVar2;
|
|
}
|
|
|
|
// Create instance in particle pool
|
|
iVar1 = FUN_80040308(0,*(undefined4 *)(PTR_DAT_8008d2ac + 0x2114),param_2);
|
|
if (iVar1 != 0)
|
|
{
|
|
// position variables
|
|
*(uint *)(iVar1 + 0x24) = *(int *)(iVar1 + 0x24) + unaff_s1;
|
|
*(uint *)(iVar1 + 0x34) = *(int *)(iVar1 + 0x34) + unaff_s3;
|
|
*(uint *)(iVar1 + 0x2c) = *(int *)(iVar1 + 0x2c) + unaff_s2;
|
|
|
|
gte_ldVXY0(CONCAT22(*(undefined2 *)(iVar1 + 0x30),*(undefined2 *)(iVar1 + 0x28)));
|
|
gte_ldVZ0((uint)*(ushort *)(iVar1 + 0x38));
|
|
gte_rtv0();
|
|
read_mt(unaff_s1,unaff_s2,unaff_s3);
|
|
|
|
// edit velocity
|
|
*(short *)(iVar1 + 0x28) = (short)unaff_s1;
|
|
*(short *)(iVar1 + 0x30) = (short)unaff_s2;
|
|
*(short *)(iVar1 + 0x38) = (short)unaff_s3;
|
|
|
|
// driver -> instSelf
|
|
*(undefined4 *)(iVar1 + 0x20) = *(undefined4 *)(param_1 + 0x1c);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// VehEmitter_DriverMain (calls all other SpawnParticle functions)
|
|
void FUN_80059a18(int param_1,int param_2,undefined *param_3,uint param_4)
|
|
|
|
{
|
|
byte bVar1;
|
|
short sVar2;
|
|
short sVar3;
|
|
short sVar4;
|
|
short sVar5;
|
|
short sVar6;
|
|
short sVar7;
|
|
ushort uVar8;
|
|
int iVar9;
|
|
MATRIX *pMVar10;
|
|
int iVar11;
|
|
undefined *puVar12;
|
|
uint uVar13;
|
|
undefined4 uVar14;
|
|
undefined2 uVar15;
|
|
undefined4 in_t1;
|
|
int iVar16;
|
|
int iVar17;
|
|
VECTOR *r0;
|
|
int iVar18;
|
|
undefined4 uVar19;
|
|
int iVar20;
|
|
undefined *puVar21;
|
|
int iVar22;
|
|
int iVar23;
|
|
int iVar24;
|
|
char cVar25;
|
|
byte bVar26;
|
|
int iVar27;
|
|
undefined *puVar28;
|
|
undefined8 uVar29;
|
|
undefined auStack_68 [16];
|
|
undefined4 local_58;
|
|
uint local_30;
|
|
|
|
puVar28 = auStack_68;
|
|
|
|
// driver -> terrain meta
|
|
iVar22 = *(int *)(param_2 + 0x358);
|
|
|
|
// get instance from thread
|
|
iVar27 = *(int *)(param_1 + 0x34);
|
|
|
|
// backup previous frame's skidmark flags, in the upper bits of itself
|
|
*(uint *)(param_2 + 0x2c4) = (*(uint *)(param_2 + 0x2c4) & 0xfffff) << 4;
|
|
|
|
// next slot (8-frame cycle)
|
|
*(byte *)(param_2 + 0xc3) = *(char *)(param_2 + 0xc3) - 1U & 7;
|
|
|
|
// terrain variables
|
|
local_30 = *(uint *)(iVar22 + 4);
|
|
iVar23 = (int)*(short *)(iVar22 + 0x30);
|
|
|
|
// thread -> modelIndex == "player" of any kind
|
|
if (*(short *)(param_1 + 0x44) == 0x18)
|
|
{
|
|
iVar18 = -1;
|
|
|
|
//if racer is on the ground and (?)
|
|
if (((*(uint *)(param_2 + 0x2c8) & 1) != 0) && ((*(uint *)(iVar22 + 4) & 0x20) == 0)) {
|
|
iVar18 = (int)*(short *)(iVar22 + 0x32);
|
|
}
|
|
|
|
// absolute value speedApprox
|
|
iVar11 = (int)*(short *)(param_2 + 0x38e);
|
|
if (iVar11 < 0) {
|
|
iVar11 = -iVar11;
|
|
}
|
|
|
|
// volume
|
|
// Map value from [minSpeed, maxSpeed] to [minVol, maxVol]
|
|
iVar9 = FUN_80058f9c(iVar11,0,5000,0,200);
|
|
|
|
// absolute value speedApprox
|
|
iVar11 = (int)*(short *)(param_2 + 0x38e);
|
|
if (iVar11 < 0) {
|
|
iVar11 = -iVar11;
|
|
}
|
|
|
|
// distortion
|
|
// Map value from [minSpeed, maxSpeed] to [minDistort, maxDistort]
|
|
iVar11 = FUN_80058f9c(iVar11,0,12000,0x6c,0xd2);
|
|
uVar13 = iVar11 << 8;
|
|
|
|
// if echo is required
|
|
if ((*(uint *)(param_2 + 0x2c8) & 0x10000) != 0)
|
|
{
|
|
// add echo
|
|
uVar13 = uVar13 | 0x1000000;
|
|
}
|
|
|
|
// driver audio
|
|
FUN_8002e690(param_2 + 0x304,iVar18,
|
|
|
|
// volume
|
|
iVar9 << 0x10 |
|
|
|
|
// distortion
|
|
uVar13 |
|
|
|
|
// L/R
|
|
0x80);
|
|
|
|
// If this is human and not an AI
|
|
if ((*(uint *)(param_2 + 0x2c8) & 0x100000) == 0)
|
|
{
|
|
// absolute value speedApprox
|
|
iVar18 = (int)*(short *)(param_2 + 0x38e);
|
|
if (iVar18 < 0) {
|
|
iVar18 = -iVar18;
|
|
}
|
|
|
|
// if speed high enough
|
|
if (0x200 < iVar18)
|
|
{
|
|
// GAMEPAD_ShockFreq and GAMEPAD_ShockForce2
|
|
FUN_80026440(param_2,(uint)*(byte *)(iVar22 + 0x2c),(uint)*(byte *)(iVar22 + 0x2d));
|
|
FUN_80026540(param_2,(uint)*(byte *)(iVar22 + 0x2e),(uint)*(byte *)(iVar22 + 0x2f));
|
|
}
|
|
|
|
//if racer started touching the ground in this frame
|
|
if ((*(uint *)(param_2 + 0x2c8) & 2) != 0)
|
|
{
|
|
// jumpHeightPrev
|
|
iVar18 = (int)*(short *)(param_2 + 0x392);
|
|
if (iVar18 < 0) {
|
|
iVar18 = -iVar18;
|
|
}
|
|
|
|
// jumpHeightPrev
|
|
if (0x1600 < iVar18)
|
|
{
|
|
// GAMEPAD_ShockForce1
|
|
FUN_800264c0(param_2,3,0xFF);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// if numPlyrCurrGame is less than 2
|
|
if ((byte)PTR_DAT_8008d2ac[0x1ca8] < 2)
|
|
{
|
|
// absolute value
|
|
iVar18 = (int)*(short *)(param_2 + 0x38c);
|
|
if (iVar18 < 0) {
|
|
iVar18 = -iVar18;
|
|
}
|
|
|
|
if (
|
|
// high speed
|
|
(0x500 < iVar18) &&
|
|
|
|
// current terrain
|
|
(*(char *)(param_2 + 0xc2) == '\x0e')
|
|
)
|
|
{
|
|
// number of particles
|
|
iVar20 = 10;
|
|
|
|
//if racer didn't start touching the ground in this frame
|
|
if ((*(uint *)(param_2 + 0x2c8) & 2) == 0)
|
|
{
|
|
// Create instance in particle pool (land jump in mud)
|
|
iVar18 = FUN_80040308(0,*(undefined4 *)(PTR_DAT_8008d2ac + 0x2148),&DAT_8008980c);
|
|
|
|
if (iVar18 != 0) {
|
|
*(undefined *)(iVar18 + 0x18) = *(undefined *)(*(int *)(param_2 + 0x1c) + 0x50);
|
|
|
|
// driver -> instSelf
|
|
*(undefined4 *)(iVar18 + 0x20) = *(undefined4 *)(param_2 + 0x1c);
|
|
|
|
// driverID
|
|
uVar1 = *(undefined *)(param_2 + 0x4a);
|
|
|
|
*(int *)(iVar18 + 0x24) = *(int *)(iVar18 + 0x24) + (int)*(short *)(iVar18 + 0x28) * 0x10;
|
|
|
|
// driverID
|
|
*(undefined *)(iVar18 + 0x19) = uVar1;
|
|
|
|
*(int *)(iVar18 + 0x34) = *(int *)(iVar18 + 0x34) + (int)*(short *)(iVar18 + 0x38) * 0x10;
|
|
*(short *)(iVar18 + 0x2a) = *(short *)(iVar18 + 0x2a) - (*(short *)(iVar18 + 0x28) >> 4);
|
|
*(short *)(iVar18 + 0x3a) = *(short *)(iVar18 + 0x3a) - (*(short *)(iVar18 + 0x38) >> 4);
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
do
|
|
{
|
|
// Create instance in particle pool (mud)
|
|
iVar15 = FUN_80040308(0,*(undefined4 *)(PTR_DAT_8008d2ac + 0x2148),&DAT_8008980c);
|
|
if (iVar15 != 0) {
|
|
*(undefined *)(iVar15 + 0x18) = *(undefined *)(*(int *)(param_2 + 0x1c) + 0x50);
|
|
|
|
// driver -> instSelf
|
|
*(undefined4 *)(iVar15 + 0x20) = *(undefined4 *)(param_2 + 0x1c);
|
|
|
|
// driverID
|
|
uVar1 = *(undefined *)(param_2 + 0x4a);
|
|
*(undefined *)(iVar15 + 0x19) = uVar1;
|
|
|
|
*(int *)(iVar15 + 0x24) = *(int *)(iVar15 + 0x24) + (int)*(short *)(iVar15 + 0x28) * 0x10;
|
|
*(int *)(iVar15 + 0x34) = *(int *)(iVar15 + 0x34) + (int)*(short *)(iVar15 + 0x38) * 0x10;
|
|
*(short *)(iVar15 + 0x2a) = *(short *)(iVar15 + 0x2a) - (*(short *)(iVar15 + 0x28) >> 4);
|
|
*(short *)(iVar15 + 0x3a) = *(short *)(iVar15 + 0x3a) - (*(short *)(iVar15 + 0x38) >> 4);
|
|
}
|
|
|
|
// loop count
|
|
iVar18 = iVar18 + -1;
|
|
|
|
} while (iVar18 != 0);
|
|
}
|
|
}
|
|
|
|
// if numPlyrCurrGame is less than 2 (useless if?)
|
|
if ((byte)PTR_DAT_8008d2ac[0x1ca8] < 2)
|
|
{
|
|
//if racer started touching the ground in this frame
|
|
if (((local_30 & 0x40) != 0) && ((*(uint *)(param_2 + 0x2c8) & 2) != 0))
|
|
{
|
|
// absolute value speedApprox
|
|
iVar18 = (int)*(short *)(param_2 + 0x38e);
|
|
if (iVar18 < 0) {
|
|
iVar18 = -iVar18;
|
|
}
|
|
|
|
// if speed is high enough
|
|
if (0x600 < iVar18)
|
|
{
|
|
// absolute value
|
|
iVar18 = (int)*(short *)(param_2 + 0x392);
|
|
if (iVar18 < 0) {
|
|
iVar18 = -iVar18;
|
|
}
|
|
|
|
if (0x1600 < iVar18)
|
|
{
|
|
// instance -> matrix
|
|
pMVar10 = (MATRIX *)(iVar27 + 0x30);
|
|
gte_SetRotMatrix(pMVar10);
|
|
gte_SetTransMatrix(pMVar10);
|
|
|
|
// VehEmitter_Sparks_Ground
|
|
FUN_80059344(param_2,&DAT_80089584);
|
|
}
|
|
}
|
|
}
|
|
|
|
// if terrain has particle data
|
|
if (*(int *)(iVar22 + 0x18) != 0)
|
|
{
|
|
// instance -> matrix
|
|
pMVar10 = (MATRIX *)(iVar27 + 0x30);
|
|
gte_SetRotMatrix(pMVar10);
|
|
gte_SetTransMatrix(pMVar10);
|
|
|
|
// particles even frame
|
|
iVar18 = *(int *)(iVar22 + 0x1c);
|
|
|
|
// if data is invalid, or odd-number frame
|
|
if ((iVar18 == 0) || ((*(uint *)(PTR_DAT_8008d2ac + 0x1cec) & 1) == 0))
|
|
{
|
|
// particles odd frame
|
|
iVar18 = *(int *)(iVar22 + 0x18);
|
|
}
|
|
|
|
// VehEmitter_Terrain_Ground
|
|
FUN_80059558(param_2,iVar18);
|
|
}
|
|
|
|
if (
|
|
// if wall rubbing right now
|
|
(*(short *)(param_2 + 0x3fe) == 0xf0) &&
|
|
|
|
// if you are not being mask grabbed
|
|
(*(char *)(param_2 + 0x376) != '\x05')
|
|
)
|
|
{
|
|
// instance -> matrix
|
|
pMVar10 = (MATRIX *)(iVar27 + 0x30)
|
|
gte_SetRotMatrix(pMVar10);
|
|
gte_SetTransMatrix(pMVar10);
|
|
|
|
// VehEmitter_Sparks_Wall
|
|
FUN_80059780(param_2,&DAT_800896c8);
|
|
|
|
uVar19 = 0x14;
|
|
|
|
// increase engine volume
|
|
sVar7 = *(short *)(param_2 + 0x496) + 0x14;
|
|
*(short *)(param_2 + 0x496) = sVar7;
|
|
|
|
// max engine volume
|
|
if (0xff < sVar7) {
|
|
*(undefined2 *)(param_2 + 0x496) = 0xff;
|
|
}
|
|
}
|
|
|
|
// if being mask grabbed
|
|
else
|
|
{
|
|
if (*(short *)(param_2 + 0x3fe) == 0)
|
|
{
|
|
// reset time against wall
|
|
*(undefined2 *)(param_2 + 0x50) = 0;
|
|
}
|
|
|
|
// decrease engine volume
|
|
uVar8 = *(short *)(param_2 + 0x496) - 0x14;
|
|
*(ushort *)(param_2 + 0x496) = uVar8;
|
|
|
|
// minimum engine volume
|
|
if ((int)((uint)uVar8 << 0x10) < 0) {
|
|
*(undefined2 *)(param_2 + 0x496) = 0;
|
|
}
|
|
|
|
uVar19 = 0x14;
|
|
if (*(short *)(param_2 + 0x496) == 0) {
|
|
uVar19 = 0xffffffff;
|
|
}
|
|
}
|
|
|
|
// thread -> modelIndex == "player" of any kind
|
|
if (*(short *)(*(int *)(param_1 + 0x68) + 0x44) == 0x18)
|
|
{
|
|
// volume
|
|
uVar13 = (int)*(short *)(param_2 + 0x496) << 0x10;
|
|
|
|
// if echo is not requierd
|
|
if ((*(uint *)(param_2 + 0x2c8) & 0x10000) == 0)
|
|
{
|
|
// volume, distortion, left/right
|
|
param_3 = (undefined *)(uVar13 | 0x8080);
|
|
}
|
|
|
|
// if echo
|
|
else
|
|
{
|
|
// add echo, volume, distortion, left/right
|
|
param_3 = (undefined *)(uVar13 | 0x1008080);
|
|
}
|
|
|
|
// driver audio
|
|
FUN_8002e690(param_2 + 0x308,uVar19);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((local_30 & 8) != 0)
|
|
{
|
|
// skid with front wheels, and back wheels
|
|
*(uint *)(param_2 + 0x2c8) = *(uint *)(param_2 + 0x2c8) | 0x1800;
|
|
}
|
|
|
|
// matrixArr
|
|
bVar26 = *(byte *)(param_2 + 0x4c);
|
|
|
|
// matArr02 (wheelie)
|
|
if (bVar26 == 1)
|
|
{
|
|
// back wheel skid
|
|
*(uint *)(param_2 + 0x2c8) = *(uint *)(param_2 + 0x2c8) | 0x800;
|
|
LAB_8005a094:
|
|
|
|
// no front wheel skid
|
|
*(uint *)(param_2 + 0x2c8) = *(uint *)(param_2 + 0x2c8) & 0xffffefff;
|
|
}
|
|
|
|
// if wheelie of any kind
|
|
else if ((bVar26 != 0) && (bVar26 < 4)) goto LAB_8005a094;
|
|
|
|
//if racer is not on the ground, not leaving skid marks on front or back tires
|
|
if (((*(uint *)(param_2 + 0x2c8) & 1) == 0) || ((*(uint *)(param_2 + 0x2c8) & 0x1800) == 0))
|
|
{
|
|
LAB_8005a73c:
|
|
|
|
// if driver sound exists
|
|
puVar12 = *(undefined **)(param_2 + 0x300);
|
|
if (puVar12 != (undefined *)0x0)
|
|
{
|
|
// OtherFX_Stop1
|
|
FUN_80028808();
|
|
|
|
// erase sound
|
|
*(undefined4 *)(param_2 + 0x300) = 0;
|
|
}
|
|
}
|
|
|
|
// if driver is on ground, and leaving skidmarks (or drift)
|
|
else
|
|
{
|
|
// absolute value speedApprox
|
|
iVar22 = (int)*(short *)(param_2 + 0x38e);
|
|
if (iVar22 < 0) {
|
|
iVar22 = -iVar22;
|
|
}
|
|
|
|
// if speed is low
|
|
if (iVar22 < 0x201) goto LAB_8005a73c;
|
|
|
|
// if speed is high
|
|
|
|
bVar26 = 0;
|
|
|
|
// thread -> modelIndex == "player" of any kind
|
|
if (*(short *)(param_1 + 0x44) == 0x18)
|
|
{
|
|
// absolute value
|
|
iVar18 = (int)*(char *)(param_2 + 0x4b);
|
|
if (iVar18 < 0) {
|
|
iVar18 = -iVar18;
|
|
}
|
|
|
|
// Map value from [oldMin, oldMax] to [newMin, newMax]
|
|
// inverting newMin and newMax will give an inverse range mapping
|
|
iVar11 = FUN_80058f9c(iVar22,2000,12000,0x14,0xaa);
|
|
|
|
// absolute value speedApprox
|
|
iVar22 = (int)*(short *)(param_2 + 0x38e);
|
|
if (iVar22 < 0) {
|
|
iVar22 = -iVar22;
|
|
}
|
|
|
|
// Map value from [oldMin, oldMax] to [newMin, newMax]
|
|
// inverting newMin and newMax will give an inverse range mapping
|
|
iVar22 = FUN_80058f9c(iVar22,2000,12000,0x92,0x78);
|
|
|
|
// or you are sliding
|
|
if (*(char *)(param_2 + 0x376) == '\x02') {
|
|
iVar9 = (int)*(short *)(param_2 + 0x3d4);
|
|
if (iVar9 < 0) {
|
|
iVar9 = -iVar9;
|
|
}
|
|
iVar22 = iVar22 - iVar9;
|
|
if (iVar22 < 0) {
|
|
iVar22 = 0;
|
|
}
|
|
}
|
|
iVar22 = iVar22 + iVar18;
|
|
if (0x92 < iVar22) {
|
|
iVar22 = 0x92;
|
|
}
|
|
|
|
// distortion
|
|
uVar13 = iVar22 << 8;
|
|
|
|
// if echo is required
|
|
if ((*(uint *)(param_2 + 0x2c8) & 0x10000) != 0)
|
|
{
|
|
// add echo
|
|
uVar13 = uVar13 | 0x1000000;
|
|
}
|
|
|
|
// driver audio
|
|
FUN_8002e690(
|
|
|
|
// driver audio
|
|
param_2 + 0x300,
|
|
|
|
(int)iVar23,
|
|
|
|
// volume
|
|
(iVar11 + (iVar18 >> 1)) * 0x10000 |
|
|
|
|
// echo + distort
|
|
uVar13 |
|
|
|
|
// L/R with no safeguard
|
|
0x80U - ((int)((uint)*(byte *)(param_2 + 0x4b) << 0x18) >> 0x1a));
|
|
|
|
|
|
}
|
|
if ((*(uint *)(iVar27 + 0x28) & 0x2000) == 0) {
|
|
cVar25 = *(char *)(iVar27 + 0x50);
|
|
}
|
|
else {
|
|
cVar25 = *(char *)(iVar27 + 0x51);
|
|
}
|
|
cVar25 = cVar25 + '\x02';
|
|
|
|
// Cosine(angle)
|
|
FUN_8003d1c0((int)*(short *)(param_2 + 0x396));
|
|
|
|
// Sine(angle)
|
|
iVar22 = FUN_8003d184((int)*(short *)(param_2 + 0x396));
|
|
iVar22 = iVar22 * 0xf;
|
|
|
|
// Cosine(angle)
|
|
iVar23 = FUN_8003d1c0((int)*(short *)(param_2 + 0x396));
|
|
|
|
// Sine(angle)
|
|
FUN_8003d184((int)*(short *)(param_2 + 0x396));
|
|
|
|
// Cosine(angle)
|
|
iVar18 = FUN_8003d1c0((int)*(short *)(param_2 + 0x396));
|
|
|
|
// Sine(angle)
|
|
FUN_8003d184((int)*(short *)(param_2 + 0x396));
|
|
iVar23 = iVar23 * 0xf;
|
|
iVar17 = iVar18 * 10 >> 0xc;
|
|
|
|
// Cosine(angle)
|
|
FUN_8003d1c0((int)*(short *)(param_2 + 0x396));
|
|
puVar12 = (undefined *)(int)*(short *)(param_2 + 0x396);
|
|
iVar24 = iVar23 >> 0xc;
|
|
|
|
// Sine(angle)
|
|
iVar18 = FUN_8003d184();
|
|
iVar20 = iVar22 >> 0xc;
|
|
iVar16 = iVar18 * -10 >> 0xc;
|
|
|
|
// instance -> matrix
|
|
pMVar10 = (MATRIX *)(iVar27 + 0x30);
|
|
gte_SetRotMatrix(pMVar10);
|
|
gte_SetTransMatrix(pMVar10);
|
|
|
|
iVar11 = iVar20 >> 1;
|
|
iVar18 = iVar24 >> 1;
|
|
uVar15 = (undefined2)in_t1;
|
|
iVar9 = iVar17 >> 1;
|
|
sVar5 = (short)iVar9;
|
|
sVar7 = (short)iVar17;
|
|
sVar3 = (short)iVar16;
|
|
sVar4 = (short)(iVar16 >> 1);
|
|
|
|
// back wheel skids
|
|
if ((*(uint *)(param_2 + 0x2c8) & 0x800) != 0)
|
|
{
|
|
// enable skidmarks for first tire
|
|
*(uint *)(param_2 + 0x2c4) = *(uint *)(param_2 + 0x2c4) | 1;
|
|
|
|
gte_ldVXY0(0xffe2);
|
|
gte_ldVZ0(0xffffffec);
|
|
gte_rt();
|
|
read_mt(param_3,in_t1,param_4);
|
|
|
|
iVar16 = (int)param_3 - (iVar22 >> 0xd);
|
|
|
|
// skidmark index (0-7)
|
|
bVar1 = *(byte *)(param_2 + 0xc3);
|
|
|
|
iVar23 = param_4 - (iVar23 >> 0xd);
|
|
iVar22 = param_2 + (uint)bVar1 * 0x40;
|
|
sVar6 = (short)iVar16;
|
|
|
|
// store to skidmark buffer
|
|
*(short *)(iVar22 + 0xc4) = sVar6 + sVar7;
|
|
|
|
sVar2 = (short)iVar23;
|
|
*(short *)(iVar22 + 200) = sVar2 + sVar3;
|
|
*(short *)(iVar22 + 0xcc) = sVar6 - sVar7;
|
|
*(undefined2 *)(iVar22 + 0xc6) = uVar15;
|
|
*(undefined2 *)(iVar22 + 0xce) = uVar15;
|
|
*(short *)(iVar22 + 0xd0) = sVar2 - sVar3;
|
|
*(char *)(iVar22 + 0xca) = cVar25;
|
|
|
|
if ((local_30 & 8) == 0) {
|
|
*(byte *)(iVar22 + 0xcb) = bVar26;
|
|
}
|
|
else {
|
|
*(byte *)(iVar22 + 0xcb) = bVar26 | 1;
|
|
}
|
|
|
|
iVar16 = iVar16 + iVar20;
|
|
iVar23 = iVar23 + iVar24;
|
|
|
|
// previous skidmark index
|
|
uVar13 = bVar1 - 1 & 7;
|
|
iVar22 = param_2 + uVar13 * 0x40;
|
|
|
|
// record skidmark buffer
|
|
*(short *)(iVar22 + 0xc4) = (short)iVar16 + sVar5;
|
|
*(undefined2 *)(iVar22 + 0xc6) = uVar15;
|
|
*(short *)(iVar22 + 200) = (short)iVar23 + sVar4;
|
|
*(short *)(iVar22 + 0xcc) = (short)iVar16 - sVar5;
|
|
*(undefined2 *)(iVar22 + 0xce) = uVar15;
|
|
*(short *)(iVar22 + 0xd0) = (short)iVar23 - sVar4;
|
|
*(char *)(iVar22 + 0xca) = cVar25;
|
|
|
|
if ((local_30 & 8) == 0) {
|
|
*(byte *)(iVar22 + 0xcb) = bVar26;
|
|
}
|
|
else {
|
|
*(byte *)(iVar22 + 0xcb) = bVar26 | 1;
|
|
}
|
|
|
|
// enable skidmarks for second tire
|
|
*(uint *)(param_2 + 0x2c4) = *(uint *)(param_2 + 0x2c4) | 2;
|
|
|
|
gte_ldVXY0(0x1e);
|
|
gte_ldVZ0(0xffffffec);
|
|
gte_rt();
|
|
read_mt(iVar16,in_t1,iVar23);
|
|
|
|
// next skidmark index
|
|
uVar13 = uVar13 + 1 & 7;
|
|
iVar22 = param_2 + uVar13 * 0x40;
|
|
|
|
// skidmark data
|
|
sVar6 = (short)(iVar16 - iVar11);
|
|
*(short *)(iVar22 + 0xd4) = sVar6 + sVar7;
|
|
sVar2 = (short)(iVar23 - iVar18);
|
|
*(short *)(iVar22 + 0xd8) = sVar2 + sVar3;
|
|
*(short *)(iVar22 + 0xdc) = sVar6 - sVar7;
|
|
*(undefined2 *)(iVar22 + 0xd6) = uVar15;
|
|
*(undefined2 *)(iVar22 + 0xde) = uVar15;
|
|
*(short *)(iVar22 + 0xe0) = sVar2 - sVar3;
|
|
*(char *)(iVar22 + 0xda) = cVar25;
|
|
if ((*(uint *)(puVar21 + 0x38) & 8) == 0) {
|
|
*(byte *)(iVar22 + 0xdb) = bVar26;
|
|
}
|
|
else {
|
|
*(byte *)(iVar22 + 0xdb) = bVar26 | 1;
|
|
}
|
|
param_3 = (undefined *)((iVar16 - iVar11) + iVar20);
|
|
param_4 = (iVar23 - iVar18) + iVar24;
|
|
|
|
// previous skidmark index
|
|
iVar22 = param_2 + (uVar13 - 1 & 7) * 0x40;
|
|
|
|
*(short *)(iVar22 + 0xd4) = (short)param_3 + sVar5;
|
|
puVar12 = param_3 + -iVar9;
|
|
*(undefined2 *)(iVar22 + 0xd6) = uVar15;
|
|
*(short *)(iVar22 + 0xd8) = (short)param_4 + sVar4;
|
|
*(short *)(iVar22 + 0xdc) = (short)puVar12;
|
|
*(undefined2 *)(iVar22 + 0xde) = uVar15;
|
|
*(short *)(iVar22 + 0xe0) = (short)param_4 - sVar4;
|
|
*(char *)(iVar22 + 0xda) = cVar25;
|
|
if ((*(uint *)(puVar21 + 0x38) & 8) == 0) {
|
|
*(byte *)(iVar22 + 0xdb) = bVar26;
|
|
}
|
|
else {
|
|
*(byte *)(iVar22 + 0xdb) = bVar26 | 1;
|
|
}
|
|
}
|
|
|
|
// front wheel skids
|
|
if ((*(uint *)(param_2 + 0x2c8) & 0x1000) != 0)
|
|
{
|
|
// enable skidmarks for third tire
|
|
*(uint *)(param_2 + 0x2c4) = *(uint *)(param_2 + 0x2c4) | 4;
|
|
|
|
gte_ldVXY0(0xffe2);
|
|
gte_ldVZ0(0x28);
|
|
gte_rt();
|
|
read_mt(param_3,in_t1,param_4);
|
|
bVar1 = *(byte *)(param_2 + 0xc3);
|
|
iVar22 = param_2 + (uint)bVar1 * 0x40;
|
|
sVar6 = (short)((int)param_3 - iVar11);
|
|
*(short *)(iVar22 + 0xe4) = sVar6 + sVar7;
|
|
sVar2 = (short)(param_4 - iVar18);
|
|
*(short *)(iVar22 + 0xe8) = sVar2 + sVar3;
|
|
*(short *)(iVar22 + 0xec) = sVar6 - sVar7;
|
|
*(undefined2 *)(iVar22 + 0xe6) = uVar15;
|
|
*(undefined2 *)(iVar22 + 0xee) = uVar15;
|
|
*(short *)(iVar22 + 0xf0) = sVar2 - sVar3;
|
|
*(char *)(iVar22 + 0xea) = cVar25;
|
|
if ((*(uint *)(puVar21 + 0x38) & 8) == 0) {
|
|
*(byte *)(iVar22 + 0xeb) = bVar26;
|
|
}
|
|
else {
|
|
*(byte *)(iVar22 + 0xeb) = bVar26 | 1;
|
|
}
|
|
iVar23 = ((int)param_3 - iVar11) + iVar20;
|
|
iVar16 = (param_4 - iVar18) + iVar24;
|
|
|
|
// next skidmark buffer
|
|
uVar13 = bVar1 - 1 & 7;
|
|
iVar22 = param_2 + uVar13 * 0x40;
|
|
|
|
*(short *)(iVar22 + 0xe4) = (short)iVar23 + sVar5;
|
|
sVar6 = (short)iVar16;
|
|
*(undefined2 *)(iVar22 + 0xe6) = uVar15;
|
|
*(short *)(iVar22 + 0xe8) = sVar6 + sVar4;
|
|
*(short *)(iVar22 + 0xec) = (short)iVar23 - sVar5;
|
|
*(undefined2 *)(iVar22 + 0xee) = uVar15;
|
|
*(short *)(iVar22 + 0xf0) = sVar6 - sVar4;
|
|
*(char *)(iVar22 + 0xea) = cVar25;
|
|
if ((*(uint *)(puVar21 + 0x38) & 8) == 0) {
|
|
*(byte *)(iVar22 + 0xeb) = bVar26;
|
|
}
|
|
else {
|
|
*(byte *)(iVar22 + 0xeb) = bVar26 | 1;
|
|
}
|
|
|
|
// enable skidmarks for fourth tire
|
|
*(uint *)(param_2 + 0x2c4) = *(uint *)(param_2 + 0x2c4) | 8;
|
|
|
|
gte_ldVXY0(0x1e);
|
|
gte_ldVZ0(0x28);
|
|
gte_rt();
|
|
read_mt(iVar23,in_t1,iVar16);
|
|
|
|
// next skidmark buffer
|
|
uVar13 = uVar13 + 1 & 7;
|
|
|
|
sVar6 = sVar6 - (short)iVar18;
|
|
iVar22 = param_2 + uVar13 * 0x40;
|
|
sVar2 = (short)(iVar23 - iVar11);
|
|
*(short *)(iVar22 + 0xf4) = sVar2 + sVar7;
|
|
*(short *)(iVar22 + 0xf8) = sVar6 + sVar3;
|
|
*(short *)(iVar22 + 0xfc) = sVar2 - sVar7;
|
|
*(undefined2 *)(iVar22 + 0xf6) = uVar15;
|
|
*(undefined2 *)(iVar22 + 0xfe) = uVar15;
|
|
*(short *)(iVar22 + 0x100) = sVar6 - sVar3;
|
|
*(char *)(iVar22 + 0xfa) = cVar25;
|
|
if ((*(uint *)(puVar21 + 0x38) & 8) == 0) {
|
|
*(byte *)(iVar22 + 0xfb) = bVar26;
|
|
}
|
|
else {
|
|
*(byte *)(iVar22 + 0xfb) = bVar26 | 1;
|
|
}
|
|
iVar20 = (iVar23 - iVar11) + iVar20;
|
|
sVar6 = sVar6 + (short)iVar24;
|
|
iVar22 = param_2 + (uVar13 - 1 & 7) * 0x40;
|
|
*(short *)(iVar22 + 0xf4) = (short)iVar20 + sVar5;
|
|
puVar12 = (undefined *)(iVar20 - iVar9);
|
|
*(undefined2 *)(iVar22 + 0xf6) = uVar15;
|
|
*(short *)(iVar22 + 0xf8) = sVar6 + sVar4;
|
|
*(short *)(iVar22 + 0xfc) = (short)puVar12;
|
|
*(undefined2 *)(iVar22 + 0xfe) = uVar15;
|
|
*(short *)(iVar22 + 0x100) = sVar6 - sVar4;
|
|
*(char *)(iVar22 + 0xfa) = cVar25;
|
|
if ((*(uint *)(puVar21 + 0x38) & 8) == 0) {
|
|
*(byte *)(iVar22 + 0xfb) = bVar26;
|
|
}
|
|
else {
|
|
*(byte *)(iVar22 + 0xfb) = bVar26 | 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// thread -> modelIndex == "robotcar" of any kind
|
|
if (*(short *)(*(int *)(puVar21 + 0x68) + 0x44) == 0x3f)
|
|
{
|
|
// put each driver on alternates frames of 4 (0,1,2,3)
|
|
uVar13 = *(uint *)(PTR_DAT_8008d2ac + 0x1cec) & 3;
|
|
if (uVar13 != (*(byte *)(param_2 + 0x4a) & 3)) goto LAB_8005a9d8;
|
|
|
|
LAB_8005a858:
|
|
if (*(char *)(param_2 + 0x381) != '\0') goto LAB_8005a868;
|
|
}
|
|
|
|
// else if "player"???
|
|
else
|
|
{
|
|
if (
|
|
// revEngineState
|
|
(*(char *)(param_2 + 0x4fe) == '\x02') ||
|
|
|
|
(
|
|
(
|
|
// do not use GOTO in 1P mode
|
|
uVar13 = (uint)(byte)PTR_DAT_8008d2ac[0x1ca8], 1 < uVar13 &&
|
|
|
|
(
|
|
(
|
|
(
|
|
// in 2P, alternate on every 2 frames
|
|
uVar13 != 2 ||
|
|
(
|
|
uVar13 = (uint)*(byte *)(param_2 + 0x4a),
|
|
|
|
(*(uint *)(PTR_DAT_8008d2ac + 0x1cec) & 1) != uVar13
|
|
)
|
|
) &&
|
|
|
|
// in 4P, alternate on every 4 frames
|
|
(
|
|
uVar13 = (uint)*(byte *)(param_2 + 0x4a),
|
|
(*(uint *)(PTR_DAT_8008d2ac + 0x1cec) & 3) != uVar13
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
) goto LAB_8005a9d8;
|
|
|
|
puVar12 = PTR_DAT_8008d2ac;
|
|
if (*(char *)(param_2 + 0x381) == '\0')
|
|
{
|
|
uVar13 = (uint)*(short *)(param_2 + 0x3dc);
|
|
|
|
if (((int)uVar13 < 0x81) || ((int)((*(byte *)(param_2 + 0x477) + 2) * 0x20) < (int)uVar13))
|
|
{
|
|
puVar12 = *(undefined **)(*(int *)(puVar21 + 0x68) + 0x14);
|
|
|
|
// PROC_SearchForModel (turbo)
|
|
uVar29 = FUN_80042394(puVar12,0x2c);
|
|
uVar13 = (uint)((ulonglong)uVar29 >> 0x20);
|
|
if ((int)uVar29 != 0) goto LAB_8005a9d8;
|
|
}
|
|
|
|
goto LAB_8005a858;
|
|
}
|
|
LAB_8005a868:
|
|
*(char *)(param_2 + 0x381) = *(char *)(param_2 + 0x381) + -1;
|
|
}
|
|
|
|
// instance->matrix
|
|
pMVar10 = (MATRIX *)(iVar27 + 0x30);
|
|
gte_SetRotMatrix(pMVar10);
|
|
gte_ldVXY0(0x4000000);
|
|
gte_ldVZ0(0xfffffc00);
|
|
gte_rtv0();
|
|
read_mt(pMVar10,uVar13,puVar12);
|
|
|
|
*(MATRIX **)(puVar21 + 0x28) = pMVar10;
|
|
*(uint *)(puVar21 + 0x2c) = uVar13;
|
|
*(undefined **)(puVar21 + 0x30) = puVar12;
|
|
|
|
// instance scale (x,y,z)
|
|
gte_ldVXY0(*(short *)(iVar27 + 0x1c) * 9 >> 3 & 0xffffU |
|
|
(*(short *)(iVar27 + 0x1e) * 7 >> 1) << 0x10);
|
|
|
|
gte_ldVZ0(*(short *)(iVar27 + 0x20) * -0x38 >> 4);
|
|
gte_rtv0();
|
|
|
|
r0 = (VECTOR *)(puVar21 + 0x18);
|
|
gte_stlvnl(r0);
|
|
|
|
puVar21 = puVar21 + 0x28;
|
|
|
|
// VehEmitter_Exhaust
|
|
FUN_80059100(param_2,r0,puVar21);
|
|
|
|
// instance scale (x,y,z)
|
|
gte_ldVXY0(*(short *)(iVar27 + 0x1c) * -0x12 >> 4 & 0xffffU |
|
|
(*(short *)(iVar27 + 0x1e) * 7 >> 1) << 0x10);
|
|
gte_ldVZ0(*(short *)(iVar27 + 0x20) * -0x38 >> 4);
|
|
gte_rtv0();
|
|
|
|
gte_stlvnl(r0);
|
|
|
|
// VehEmitter_Exhaust
|
|
FUN_80059100(param_2,r0,puVar21);
|
|
|
|
LAB_8005a9d8:
|
|
|
|
// if driver is burnt
|
|
if (*(short *)(param_2 + 0x402) != 0)
|
|
{
|
|
*(undefined2 *)(param_2 + 0x508) = 0x1000;
|
|
|
|
// set alpha to max (draws black)
|
|
*(undefined2 *)(*(int *)(param_2 + 0x1c) + 0x22) = 0x1000;
|
|
}
|
|
|
|
// if driver is invisible
|
|
if (*(int *)(param_2 + 0x28) != 0)
|
|
{
|
|
// set transparency to max
|
|
*(undefined2 *)(iVar27 + 0x22) = 0x1000;
|
|
}
|
|
|
|
//if racer is not driving normally and not drifting
|
|
if ((*(char *)(param_2 + 0x376) != '\0') && (*(char *)(param_2 + 0x376) != '\x02'))
|
|
{
|
|
//turn off 20th bit of Actions Flag set (means racer is not in the air)
|
|
*(uint *)(param_2 + 0x2c8) = *(uint *)(param_2 + 0x2c8) & 0xfff7ffff;
|
|
}
|
|
|
|
//if racer is being mask grabbed or repositioned, or is on the ground
|
|
if ((*(byte *)(param_2 + 0x376) - 4 < 2) || ((*(uint *)(param_2 + 0x2c8) & 1) != 0))
|
|
{
|
|
// GAMEPAD_JogCon2
|
|
FUN_800263fc(param_2,0x27,0);
|
|
|
|
if (*(short *)(param_2 + 0x3d4) == 0) {
|
|
return;
|
|
}
|
|
if ((*(uint *)(PTR_DAT_8008d2ac + 0x1cec) & 3) == 0) {
|
|
uVar19 = 0x27;
|
|
}
|
|
else {
|
|
uVar19 = 0xf0;
|
|
}
|
|
uVar14 = 0x100;
|
|
}
|
|
else
|
|
{
|
|
// low jump landing boost
|
|
if (*(short *)(param_2 + 0x3fc) < 0x80)
|
|
{
|
|
uVar19 = 0x12;
|
|
if (
|
|
// steer left
|
|
(*(char *)(param_2 + 0x4b) < '\0') ||
|
|
|
|
(
|
|
// steer right
|
|
uVar19 = 0x22,
|
|
'\0' < *(char *)(param_2 + 0x4b)
|
|
)
|
|
)
|
|
{
|
|
// GAMEPAD_JogCon1
|
|
FUN_800263a0(param_2,uVar19,0x20);
|
|
}
|
|
}
|
|
uVar19 = 0;
|
|
uVar14 = uVar19;
|
|
}
|
|
|
|
// GAMEPAD_JogCon2
|
|
FUN_800263fc(param_2,uVar19,uVar14);
|
|
return;
|
|
}
|
|
|
|
// VehFire_Audio
|
|
// param1 - driver
|
|
// param2 - speed cap
|
|
void FUN_8005ab24(int param_1,int param_2)
|
|
|
|
{
|
|
uint uVar1;
|
|
uint uVar2;
|
|
int iVar3;
|
|
int iVar4;
|
|
|
|
// if turbo audio cooldown is not done
|
|
if (*(short *)(param_1 + 0x3e0) != 0) {
|
|
return;
|
|
}
|
|
|
|
// half volume
|
|
iVar4 = 0x80;
|
|
|
|
if (param_2 < 0x40)
|
|
{
|
|
// distort
|
|
iVar3 = 0x94;
|
|
}
|
|
|
|
else
|
|
{
|
|
// 3/4 volume
|
|
iVar4 = 0xc0;
|
|
|
|
if (0x7f < param_2)
|
|
{
|
|
// distort
|
|
iVar3 = 0x6c;
|
|
|
|
// Make driver talk
|
|
FUN_8002cbe8(0x10,(int)(short)(&DAT_80086e84)[*(byte *)(param_1 + 0x4a)],0x10);
|
|
|
|
// max volume
|
|
uVar2 = 0xff0000;
|
|
|
|
goto LAB_8005aba4;
|
|
}
|
|
|
|
// no distort
|
|
iVar3 = 0x80;
|
|
}
|
|
|
|
// volume
|
|
uVar2 = iVar4 << 0x10;
|
|
|
|
LAB_8005aba4:
|
|
|
|
// distortion
|
|
uVar1 = iVar3 << 8;
|
|
|
|
// if echo is requierd
|
|
if ((*(uint *)(param_1 + 0x2c8) & 0x10000) != 0)
|
|
{
|
|
// add echo
|
|
uVar1 = uVar1 | 0x1000000;
|
|
}
|
|
|
|
// OtherFX_Play_LowLevel
|
|
// 0xD = Turbo Boost Sound
|
|
// 0x80 = balance L/R
|
|
FUN_800284d0(0xd,1,uVar2 | uVar1 | 0x80);
|
|
|
|
// turbo audio cooldown 0.24s
|
|
*(undefined2 *)(param_1 + 0x3e0) = 0xf0;
|
|
|
|
return;
|
|
}
|
|
|
|
// VehFire_Increment
|
|
// param1 - driver
|
|
// param2 - reserves to add
|
|
// param3 - add type
|
|
// param4 - fire level
|
|
void FUN_8005abfc(int param_1,int param_2,uint param_3,int param_4)
|
|
|
|
{
|
|
char cVar1;
|
|
short sVar2;
|
|
undefined *puVar3;
|
|
undefined uVar4;
|
|
int iVar5;
|
|
uint uVar6;
|
|
int *piVar7;
|
|
int iVar8;
|
|
short sVar9;
|
|
|
|
if (
|
|
//if pointer is not null and
|
|
((param_3 & 4) != 0) &&
|
|
|
|
//racer is in accel prevention
|
|
((*(uint *)(param_1 + 0x2c8) & 8) != 0)
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (
|
|
// Player / AI structure + 0x4a shows driver index (0-7)
|
|
|
|
// If this is the first driver (P1) and
|
|
(*(char *)(param_1 + 0x4a) == '\0') &&
|
|
|
|
// driver -> instance -> thread -> modelIndex == "player" of any kind
|
|
(*(short *)(*(int *)(*(int *)(param_1 + 0x1c) + 0x6c) + 0x44) == 0x18)
|
|
)
|
|
{
|
|
// Add Reserves to ghost buffer
|
|
FUN_8002838c(param_2,param_3,param_4);
|
|
}
|
|
|
|
//puVar3 = 0x96B20
|
|
puVar3 = PTR_DAT_8008d2ac;
|
|
//cVar1 = Kart state
|
|
cVar1 = *(char *)(param_1 + 0x376);
|
|
|
|
//if player is spinning, blasted, or mask grabbed, quit the function
|
|
if (cVar1 == '\x03') {
|
|
return;
|
|
}
|
|
if (cVar1 == '\x06') {
|
|
return;
|
|
}
|
|
if (cVar1 == '\x05') {
|
|
return;
|
|
}
|
|
|
|
//turn off 8th flag, turn on 22nd flag of actions flag set
|
|
//means ? (!(8)) and racer just got an outside turbo (22)
|
|
*(uint *)(param_1 + 0x2c8) = *(uint *)(param_1 + 0x2c8) & 0xffffff7f | 0x200000;
|
|
|
|
// turbo thread bucket
|
|
iVar5 = *(int *)(puVar3 + 0x1be0);
|
|
|
|
// turbo thread bucket exists
|
|
if (iVar5 != 0)
|
|
{
|
|
// check all turbo threads
|
|
do
|
|
{
|
|
// if this turbo thread is owned by this driver
|
|
// turboThread->object->offset0x4 == driver
|
|
if (*(int *)(*(int *)(iVar5 + 0x30) + 4) == param_1)
|
|
{
|
|
// quit, iVar5 is now this driver's turbo thread
|
|
break;
|
|
}
|
|
|
|
// next turbo thread in bucket
|
|
iVar5 = *(int *)(iVar5 + 0x10);
|
|
|
|
} while (iVar5 != 0);
|
|
|
|
// if this driver's turbo thread was found
|
|
if (iVar5 != 0)
|
|
{
|
|
// get the turbo's object
|
|
piVar7 = *(int **)(iVar5 + 0x30);
|
|
|
|
// get the turbo's instance
|
|
iVar8 = *(int *)(iVar5 + 0x34);
|
|
|
|
// thread flags
|
|
*(uint *)(iVar5 + 0x1c) = *(uint *)(iVar5 + 0x1c) & 0xfffff7ff;
|
|
|
|
// manipulate how turbo draws, depending on Add Type flag
|
|
if ((param_3 & 4) == 0)
|
|
{
|
|
|
|
// turbo instance (1/2) attached to thread, edit instance draw flags
|
|
*(uint *)(iVar8 + 0x28) = *(uint *)(iVar8 + 0x28) | 0x1000080;
|
|
|
|
// turbo instance (2/2) in thread's object, edit instance draw flags
|
|
*(uint *)(*piVar7 + 0x28) = *(uint *)(*piVar7 + 0x28) | 0x1000080;
|
|
|
|
*(undefined2 *)((int)piVar7 + 0xe) = 0x60;
|
|
|
|
LAB_8005ad6c:
|
|
|
|
//increase Turbo counter by 1
|
|
*(short *)(param_1 + 0x4e) = *(short *)(param_1 + 0x4e) + 1;
|
|
}
|
|
|
|
// if AddType is different
|
|
else
|
|
{
|
|
//if racer got an Outside turbo, add it to the Turbo counter
|
|
if ((*(uint *)(param_1 + 0x2cc) & 0x200000) == 0) goto LAB_8005ad6c;
|
|
}
|
|
|
|
*(undefined *)(piVar7 + 3) = 0xff;
|
|
*(undefined2 *)(iVar8 + 0x22) = 0;
|
|
*(undefined2 *)(*piVar7 + 0x22) = 0;
|
|
|
|
if (
|
|
// driver -> instance -> thread -> modelIndex == "player" of any kind
|
|
(*(short *)(*(int *)(*(int *)(param_1 + 0x1c) + 0x6c) + 0x44) == 0x18) &&
|
|
(
|
|
(
|
|
//if racer is not getting a new boost this frame
|
|
(*(uint *)(param_1 + 0x2c8) & 0x200000) == 0 ||
|
|
|
|
//racer was not getting a new boost previous frame
|
|
((*(uint *)(param_1 + 0x2cc) & 0x200000) == 0)
|
|
)
|
|
)
|
|
)
|
|
{
|
|
*(undefined *)((int)piVar7 + 0xd) = 0;
|
|
|
|
// VehFire_Audio
|
|
FUN_8005ab24(param_1,param_4);
|
|
}
|
|
|
|
// skip code, do not re-initialize turbo thread,
|
|
// because it already exists
|
|
goto LAB_8005af38;
|
|
}
|
|
}
|
|
|
|
// If the program reaches this point,
|
|
// it means a boost was added to the driver,
|
|
// and a thread does not already exist, so
|
|
// a turbo thread is created
|
|
|
|
//Turbo counter = 1
|
|
*(undefined2 *)(param_1 + 0x4e) = 1;
|
|
|
|
// definitely related to turbo display counter,
|
|
// because it is in the HUD thread bucket...
|
|
|
|
// s_turbo1_8008d61c
|
|
// "turbo1"
|
|
// 0x300 flag = SmallStackPool
|
|
// 0x10 = HUD thread bucket
|
|
iVar5 = FUN_800309a4(0x2c,s_turbo1_8008d61c,0x300,9,FUN_800693c8,0x10,0);
|
|
|
|
// piVar7 = nullptr
|
|
piVar7 = (int *)0x0;
|
|
|
|
//if iVar5 != nullptr
|
|
if (iVar5 != 0)
|
|
{
|
|
// turboInstance->thread->object
|
|
piVar7 = *(int **)(*(int *)(iVar5 + 0x6c) + 0x30);
|
|
|
|
// store Driver pointer inside Turbo object
|
|
piVar7[1] = param_1;
|
|
|
|
*(undefined2 *)((int)piVar7 + 0xe) = 0;
|
|
|
|
// allow this thread to ignore all collisions
|
|
*(uint *)(*(int *)(iVar5 + 0x6c) + 0x1c) = *(uint *)(*(int *)(iVar5 + 0x6c) + 0x1c) | 0x1000;
|
|
|
|
if (
|
|
|
|
// driver -> instance -> thread -> modelIndex == "player" of any kind
|
|
(*(short *)(*(int *)(*(int *)(param_1 + 0x1c) + 0x6c) + 0x44) == 0x18) &&
|
|
(
|
|
*(undefined *)((int)piVar7 + 0xd) = 0,
|
|
|
|
//racer is not crashing
|
|
*(char *)(param_1 + 0x376) != '\x01'
|
|
)
|
|
)
|
|
{
|
|
// VehFire_Audio
|
|
FUN_8005ab24(param_1,param_4);
|
|
}
|
|
|
|
//puVar3 = 0x96B20
|
|
puVar3 = PTR_DAT_8008d2ac;
|
|
|
|
// turbo thread OnDestroy
|
|
*(undefined4 *)(*(int *)(iVar5 + 0x6c) + 0x24) = 0x80069370;
|
|
|
|
// s_turbo2_8008d624
|
|
// "turbo2"
|
|
|
|
// INSTANCE_Birth3D -- ptrModel, name, thread,
|
|
// model 0x2c, first turbo_effect
|
|
iVar8 = FUN_8003086c(*(undefined4 *)(puVar3 + 0x2210),
|
|
s_turbo2_8008d624,
|
|
|
|
// turbo thread
|
|
*(undefined4 *)(iVar5 + 0x6c));
|
|
|
|
//puVar3 = 0x96B20 (again)
|
|
puVar3 = PTR_DAT_8008d2ac;
|
|
|
|
// store pointer to 2nd turbo
|
|
// inside Turbo object
|
|
*piVar7 = iVar8;
|
|
|
|
// if numPlyrCurrGame is not 1
|
|
uVar6 = 0x1040000;
|
|
|
|
// if numPlyrCurrGame is 1
|
|
if (puVar3[0x1ca8] == '\x01')
|
|
{
|
|
uVar6 = 0x3040000;
|
|
}
|
|
|
|
// turbo (1/2) instance flag (attached to thread)
|
|
*(uint *)(iVar5 + 0x28) =
|
|
*(uint *)(iVar5 + 0x28) | uVar6 | 0x80;
|
|
|
|
// turbo (2/2) instance flag (attached to object)
|
|
*(uint *)(*piVar7 + 0x28) =
|
|
*(uint *)(*piVar7 + 0x28) | uVar6 | 0x80;
|
|
|
|
*(undefined2 *)(piVar7 + 2) = 0;
|
|
if ((param_3 & 2) == 0) {
|
|
uVar4 = 0xff;
|
|
}
|
|
else {
|
|
uVar4 = 2;
|
|
}
|
|
*(undefined *)(piVar7 + 3) = uVar4;
|
|
}
|
|
|
|
// This code only seem to run when you either are on a turbo pad/super turbo pad or you get any sort of boost
|
|
LAB_8005af38:
|
|
|
|
// param_4 = multiplier that represents the level of fire of your boost
|
|
// Constant values:
|
|
// sacred fire speed cap = 0x1000
|
|
// single turbo speed cap = 0x800
|
|
|
|
// iVar5 = (param_4 * sacred fire speed cap) - (single turbo speed cap >> 8) + (single turbo speed cap)
|
|
// iVar5 = ground speed cap represented by your multiplier
|
|
|
|
iVar5 = (param_4 * ((int)*(short *)(param_1 + 0x432) - (int)*(short *)(param_1 + 0x430)) >> 8) +
|
|
(int)*(short *)(param_1 + 0x430);
|
|
|
|
if (
|
|
(
|
|
(
|
|
// Reserves are equal to zero
|
|
(*(short *)(param_1 + 0x3e2) == 0) ||
|
|
|
|
// OR
|
|
|
|
// Current ground speed cap is less than iVar5
|
|
((int)*(short *)(param_1 + 0x3e4) < iVar5)
|
|
) ||
|
|
|
|
// OR
|
|
|
|
(
|
|
(
|
|
// Current speed cap is greater than 0x1000
|
|
(int)*(short *)(param_1 + 0x432) < (int)*(short *)(param_1 + 0x3e4) &&
|
|
|
|
// AND
|
|
|
|
// You are not on a super turbo pad
|
|
((*(uint *)(param_1 + 0xbc) & 2) == 0)
|
|
)
|
|
)
|
|
) &&
|
|
|
|
// AND
|
|
|
|
(
|
|
(
|
|
// Current speed cap = iVar5
|
|
*(undefined2 *)(param_1 + 0x3e4) = (short)iVar5,
|
|
|
|
// Compare !=
|
|
piVar7 != (int *)0x0 &&
|
|
|
|
// AND
|
|
|
|
(
|
|
// Assignment
|
|
iVar5 = (param_4 >> 6) + 5,
|
|
|
|
// Assignment
|
|
*(undefined2 *)((int)piVar7 + 10) = (short)iVar5,
|
|
|
|
// Compoare <
|
|
8 < iVar5 * 0x10000 >> 0x10
|
|
)
|
|
)
|
|
)
|
|
)
|
|
{
|
|
*(undefined2 *)((int)piVar7 + 10) = 8;
|
|
}
|
|
|
|
if ((param_3 & 8) != 0)
|
|
{
|
|
// driver is using turbo weapon
|
|
*(uint *)(param_1 + 0x2c8) = *(uint *)(param_1 + 0x2c8) | 0x200;
|
|
}
|
|
|
|
sVar9 = (short)param_2;
|
|
if ((param_3 & 1) == 0)
|
|
{
|
|
if ((param_3 & 0x10) == 0)
|
|
{
|
|
// increase reserves BY param2
|
|
*(short *)(param_1 + 0x3e2) = *(short *)(param_1 + 0x3e2) + sVar9;
|
|
}
|
|
else
|
|
{
|
|
// increase reserves TO param2
|
|
if (*(short *)(param_1 + 0x3e2) < param_2)
|
|
{
|
|
*(short *)(param_1 + 0x3e2) = sVar9;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
sVar2 = *(short *)(param_1 + 0x3de);
|
|
if (*(short *)(param_1 + 0x3de) < param_2) {
|
|
*(short *)(param_1 + 0x3de) = sVar9;
|
|
*(short *)(param_1 + 0x3e2) = *(short *)(param_1 + 0x3e2) + (sVar9 - sVar2);
|
|
}
|
|
}
|
|
|
|
// driver -> instance -> thread -> modelIndex == "player" of any kind
|
|
if (*(short *)(*(int *)(*(int *)(param_1 + 0x1c) + 0x6c) + 0x44) == 0x18) {
|
|
|
|
// CameraDC flag
|
|
*(uint *)(PTR_DAT_8008d2ac + (uint)*(byte *)(param_1 + 0x4a) * 0xdc + 0x1508) =
|
|
*(uint *)(PTR_DAT_8008d2ac + (uint)*(byte *)(param_1 + 0x4a) * 0xdc + 0x1508) | 0x80;
|
|
|
|
// GAMEPAD_ShockForce1
|
|
FUN_800264c0(param_1,8,0x7f);
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// animation index, and number of frames
|
|
// 0 - midpoint (steering should start at midpoint)
|
|
// 1 - start
|
|
// 2 - start
|
|
// 3 - start
|
|
// 4 - end
|
|
|
|
// VehFrameInst_GetStartFrame
|
|
int FUN_8005b0c4(int param_1,int param_2)
|
|
{
|
|
if (param_1 == 0) {
|
|
return param_2 >> 1;
|
|
}
|
|
if (param_1 != 4) {
|
|
return 0;
|
|
}
|
|
return param_2 + -1;
|
|
}
|
|
|
|
|
|
// get number of frames in animation
|
|
// param1 - instance
|
|
// param2 - animIndex
|
|
|
|
// VehFrameInst_GetNumAnimFrames
|
|
uint FUN_8005b0f4(int param_1,int param_2)
|
|
{
|
|
int iVar1;
|
|
|
|
// instance -> model
|
|
iVar1 = *(int *)(param_1 + 0x18);
|
|
|
|
// if model is valid, and if numHeaders is more than zero
|
|
if ((((iVar1 != 0) && (0 < *(short *)(iVar1 + 0x12))) &&
|
|
|
|
// get header, check for nullptr
|
|
(iVar1 = *(int *)(iVar1 + 0x14), iVar1 != 0)) &&
|
|
|
|
// animIndex < numAnimations in model
|
|
(param_2 < *(int *)(iVar1 + 0x34)))
|
|
{
|
|
// if pointer to animation data is valid
|
|
if (*(int *)(iVar1 + 0x38) != 0)
|
|
{
|
|
// get pointer to animation, given animIndex
|
|
iVar1 = *(int *)(param_2 * 4 + *(int *)(iVar1 + 0x38));
|
|
if (iVar1 != 0)
|
|
{
|
|
// return number of animation frames
|
|
return (uint)*(ushort *)(iVar1 + 0x10) & 0x7fff;
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
// VehFrameProc_Driving
|
|
// param1 = thread, param2 = driver
|
|
void FUN_8005b178(int param_1,int param_2)
|
|
{
|
|
byte bVar1;
|
|
undefined *puVar2;
|
|
char cVar3;
|
|
undefined2 uVar4;
|
|
int iVar5;
|
|
short sVar6;
|
|
int iVar7;
|
|
undefined4 uVar8;
|
|
int iVar9;
|
|
int iVar10;
|
|
uint uVar11;
|
|
|
|
// Get instance from thread
|
|
iVar10 = *(int *)(param_1 + 0x34);
|
|
|
|
// animation is drive forwards
|
|
uVar11 = 0;
|
|
|
|
//if you don't have a TNT over you and state of kart is not in a warp pad
|
|
if ((*(int *)(param_2 + 0x18) == 0) && (*(char *)(param_2 + 0x376) != '\n'))
|
|
{
|
|
if (*(short *)(param_2 + 0x39e) < 0)
|
|
{
|
|
// check if you are driving backwards
|
|
// (0) forwards
|
|
// (1) backwards
|
|
uVar11 = (uint)(*(short *)(param_2 + 0x38e) < 1);
|
|
}
|
|
if (
|
|
((0x600 < *(short *)(param_2 + 0x390)) || (*(char *)(iVar10 + 0x52) == '\x03')) &&
|
|
|
|
// if player height is far from quadblock height
|
|
(0x8000 < *(int *)(param_2 + 0x2d8) - *(int *)(param_2 + 0x2d0))
|
|
)
|
|
{
|
|
// jumping animation
|
|
uVar11 = 3;
|
|
}
|
|
}
|
|
|
|
// get number of frames in animation
|
|
iVar5 = FUN_8005b0f4(iVar10,(uint)*(byte *)(iVar10 + 0x52));
|
|
|
|
// if animation has frames
|
|
if (0 < iVar5)
|
|
{
|
|
// get animation frame currently
|
|
bVar1 = *(byte *)(iVar10 + 0x52);
|
|
|
|
// if animation changes
|
|
if (uVar11 != (uint)bVar1)
|
|
{
|
|
// if crashing animation
|
|
if (bVar1 == 2)
|
|
{
|
|
// get number of frames in animation
|
|
iVar5 = FUN_8005b0f4(iVar10);
|
|
|
|
// start on last frame
|
|
iVar5 = iVar5 + -1;
|
|
}
|
|
|
|
else
|
|
{
|
|
// VehFrameInst_GetStartFrame
|
|
iVar5 = FUN_8005b0c4((uint)bVar1,iVar5);
|
|
}
|
|
|
|
// if animation frame has changed
|
|
if ((int)*(short *)(iVar10 + 0x54) != iVar5)
|
|
{
|
|
// if steering animation
|
|
if (*(char *)(iVar10 + 0x52) == '\0') {
|
|
uVar8 = 6;
|
|
}
|
|
|
|
else
|
|
{
|
|
// jump or reverse?
|
|
uVar8 = 2;
|
|
|
|
// crashing
|
|
if (*(char *)(iVar10 + 0x52) == '\x02')
|
|
{
|
|
uVar8 = 1;
|
|
|
|
// matrixIndex = animFrame
|
|
*(undefined *)(param_2 + 0x4d) = *(undefined *)(iVar10 + 0x54);
|
|
}
|
|
}
|
|
|
|
// Interpolate animation by speed
|
|
uVar4 = FUN_80058f54((int)*(short *)(iVar10 + 0x54),uVar8,iVar5);
|
|
*(undefined2 *)(iVar10 + 0x54) = uVar4;
|
|
|
|
if (1 < (uint)*(byte *)(iVar10 + 0x52) - 2) {
|
|
return;
|
|
}
|
|
|
|
// get animation frame from Instance
|
|
cVar3 = *(char *)(iVar10 + 0x54);
|
|
|
|
// Give it to driver
|
|
*(char *)(param_2 + 0x4d) = cVar3;
|
|
|
|
if (cVar3 != '\0') {
|
|
return;
|
|
}
|
|
//kart animation Index
|
|
*(undefined *)(param_2 + 0x4c) = 0;
|
|
|
|
//kart animation frame
|
|
*(undefined *)(param_2 + 0x4d) = 0;
|
|
return;
|
|
}
|
|
|
|
// get number of frames in animation
|
|
iVar5 = FUN_8005b0f4(iVar10,uVar11);
|
|
if (iVar5 < 1) {
|
|
return;
|
|
}
|
|
|
|
// set animation
|
|
*(undefined *)(iVar10 + 0x52) = (char)uVar11;
|
|
|
|
// VehFrameInst_GetStartFrame
|
|
uVar4 = FUN_8005b0c4(uVar11,iVar5);
|
|
|
|
// set animation frame
|
|
*(undefined2 *)(iVar10 + 0x54) = uVar4;
|
|
|
|
// animation index
|
|
*(undefined *)(param_2 + 0x4c) = 0;
|
|
|
|
// animation frame
|
|
*(undefined *)(param_2 + 0x4d) = 0;
|
|
}
|
|
//puVar2 = 0x96B20
|
|
puVar2 = PTR_DAT_8008d2ac;
|
|
|
|
// steering animation
|
|
if (uVar11 == 0)
|
|
{
|
|
iVar9 = iVar5 >> 1;
|
|
|
|
//if you don't have a TNT over you
|
|
if (*(int *)(param_2 + 0x18) == 0)
|
|
{
|
|
//sVar6 = time burnt left
|
|
sVar6 = *(short *)(param_2 + 0x402);
|
|
|
|
//if you're not burnt or your time burnt left is bigger than 0x1df
|
|
if ((sVar6 == 0) || (0x1df < sVar6))
|
|
{
|
|
//iVar9 = negative turning stat while braking
|
|
iVar9 = -0x40;
|
|
|
|
//if you're not in accel prevention
|
|
if ((*(uint *)(param_2 + 0x2c8) & 8) == 0)
|
|
{
|
|
//iVar7 = simplified turning state
|
|
iVar7 = (int)*(char *)(param_2 + 0x4b);
|
|
|
|
//uVar11 = character's turn stat
|
|
uVar11 = (uint)*(byte *)(param_2 + 0x43a);
|
|
|
|
//iVar9 = negative character's turn stat
|
|
iVar9 = -uVar11;
|
|
}
|
|
//if you're braking or being mask grabbed
|
|
else {
|
|
//uVar11 = positive turning stat while braking
|
|
uVar11 = 0x40;
|
|
|
|
//iVar7 = amplified turning state
|
|
iVar7 = (int)*(short *)(param_2 + 0xc0);
|
|
}
|
|
|
|
//seems like iVar9 gets set to 0 if you're turning, or to iVar5 - 1 if you're not
|
|
// Map value from [oldMin, oldMax] to [newMin, newMax]
|
|
// inverting newMin and newMax will give an inverse range mapping
|
|
iVar9 = FUN_80058f9c(-iVar7,iVar9,uVar11,0,iVar5 + -1);
|
|
}
|
|
|
|
//if your time burnt left is between (0x0, 0x1df)
|
|
else {
|
|
iVar9 = (((int)(sVar6 >> 5) % 5) * 0x10000 >> 0xe) + -8 + iVar9;
|
|
*(undefined2 *)(iVar10 + 0x54) = (short)iVar9;
|
|
|
|
// Create instance in particle pool
|
|
iVar5 = FUN_80040308(0,*(undefined4 *)(puVar2 + 0x2118),&DAT_80089974);
|
|
|
|
if (iVar5 != 0) {
|
|
*(undefined *)(iVar5 + 0x18) = *(undefined *)(*(int *)(param_2 + 0x1c) + 0x50);
|
|
|
|
// driver -> instSelf
|
|
*(undefined4 *)(iVar5 + 0x20) = *(undefined4 *)(param_2 + 0x1c);
|
|
|
|
// driverID
|
|
*(undefined *)(iVar5 + 0x19) = *(undefined *)(param_2 + 0x4a);
|
|
}
|
|
}
|
|
}
|
|
sVar6 = *(short *)(iVar10 + 0x54);
|
|
}
|
|
|
|
else
|
|
{
|
|
// jump animation
|
|
if (uVar11 == 3)
|
|
{
|
|
// Interpolate animation frame by speed
|
|
uVar4 = FUN_80058f54((int)*(short *)(iVar10 + 0x54),1,iVar5 + -1);
|
|
|
|
// set animation frame
|
|
*(undefined2 *)(iVar10 + 0x54) = uVar4;
|
|
|
|
//if you're getting mask grabbed
|
|
if (*(char *)(param_2 + 0x376) == '\x05') {
|
|
return;
|
|
}
|
|
|
|
//player / AI structure + 0x4a shows driver index (0-7)
|
|
|
|
//get character ID
|
|
sVar6 = (&DAT_80086e84)[*(byte *)(param_2 + 0x4a)];
|
|
|
|
//if this is penta
|
|
if (sVar6 == 0xd) {
|
|
sVar6 = 3;
|
|
}
|
|
|
|
//if this is fake crash
|
|
if (sVar6 == 0xe) {
|
|
sVar6 = 0;
|
|
}
|
|
|
|
cVar3 = (char)sVar6 + 7;
|
|
|
|
//if this is oxide
|
|
if (sVar6 == 0xf)
|
|
{
|
|
cVar3 = 7;
|
|
}
|
|
|
|
// set matrixArr for jump
|
|
*(char *)(param_2 + 0x4c) = cVar3;
|
|
|
|
// set matrixIndex to animation frame
|
|
*(undefined *)(param_2 + 0x4d) = *(undefined *)(iVar10 + 0x54);
|
|
return;
|
|
}
|
|
iVar9 = iVar5 + -1;
|
|
|
|
// set animation frame
|
|
sVar6 = *(short *)(iVar10 + 0x54);
|
|
}
|
|
|
|
// Interpolate rotation by speed
|
|
uVar4 = FUN_80058f54((int)sVar6,1,iVar9);
|
|
|
|
// set animation frame
|
|
*(undefined2 *)(iVar10 + 0x54) = uVar4;
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
|
|
// VehFrameProc_Spinning
|
|
// param1 = thread, param2 = driver
|
|
void FUN_8005b510(int param_1,int param_2)
|
|
|
|
{
|
|
undefined2 uVar1;
|
|
int iVar2;
|
|
int iVar3;
|
|
int iVar4;
|
|
|
|
// get instance from thread
|
|
iVar4 = *(int *)(param_1 + 0x34);
|
|
|
|
// Instance_GetNumAnimFrames(instance, animIndex)
|
|
iVar2 = FUN_8005b0f4(iVar4,(uint)*(byte *)(iVar4 + 0x52));
|
|
|
|
// if there are no frames
|
|
if (iVar2 < 1)
|
|
{
|
|
// quit
|
|
return;
|
|
}
|
|
|
|
// if animation is not zero
|
|
if (*(byte *)(iVar4 + 0x52) != 0)
|
|
{
|
|
// VehFrameInst_GetStartFrame
|
|
iVar3 = FUN_8005b0c4((uint)*(byte *)(iVar4 + 0x52),iVar2);
|
|
|
|
// If animation is negative
|
|
if ((uint)*(byte *)(iVar4 + 0x52) - 2 < 2)
|
|
{
|
|
// reset animation id and frame
|
|
*(undefined *)(param_2 + 0x4c) = 0;
|
|
*(undefined *)(param_2 + 0x4d) = 0;
|
|
}
|
|
|
|
if ((int)*(short *)(iVar4 + 0x54) == iVar3)
|
|
{
|
|
// get number of frames in animation
|
|
iVar2 = FUN_8005b0f4(iVar4,0);
|
|
if (iVar2 < 1) {
|
|
return;
|
|
}
|
|
|
|
// set animation
|
|
*(undefined *)(iVar4 + 0x52) = 0;
|
|
}
|
|
if (*(char *)(iVar4 + 0x52) != '\0') goto LAB_8005b5d0;
|
|
}
|
|
iVar3 = 0;
|
|
if (-1 < *(short *)(param_2 + 0x582)) {
|
|
iVar3 = iVar2 + -1;
|
|
}
|
|
LAB_8005b5d0:
|
|
|
|
// Interpolate animation frame by speed
|
|
uVar1 = FUN_80058f54((int)*(short *)(iVar4 + 0x54),4,iVar3);
|
|
|
|
// set animation frame
|
|
*(undefined2 *)(iVar4 + 0x54) = uVar1;
|
|
|
|
return;
|
|
}
|
|
|
|
// VehFrameProc_LastSpin
|
|
// param1 = thread, param2 = driver
|
|
void FUN_8005b5fc(int param_1,int param_2)
|
|
|
|
{
|
|
short sVar1;
|
|
undefined2 uVar2;
|
|
int iVar3;
|
|
int iVar4;
|
|
int iVar5;
|
|
|
|
// get instance from thread
|
|
iVar5 = *(int *)(param_1 + 0x34);
|
|
|
|
// if animation is zero
|
|
if (*(char *)(iVar5 + 0x52) == '\0')
|
|
{
|
|
// get number of frames in animation
|
|
iVar3 = FUN_8005b0f4(iVar5,0);
|
|
|
|
if (0 < iVar3) {
|
|
sVar1 = *(short *)(param_2 + 0x3c6);
|
|
|
|
// get animation frame
|
|
iVar4 = (int)*(short *)(iVar5 + 0x54);
|
|
|
|
if (0 < sVar1)
|
|
{
|
|
if (*(short *)(param_2 + 0x3d2) < 0) {
|
|
iVar4 = iVar3 + -1;
|
|
}
|
|
sVar1 = *(short *)(param_2 + 0x3c6);
|
|
}
|
|
|
|
if ((sVar1 < 0) && (0 < *(short *)(param_2 + 0x3d2))) {
|
|
iVar4 = 0;
|
|
}
|
|
|
|
// Interpolate animation frame by speed
|
|
uVar2 = FUN_80058f54((int)*(short *)(iVar5 + 0x54),3,iVar4);
|
|
|
|
// set animation frame
|
|
*(undefined2 *)(iVar5 + 0x54) = uVar2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// VehFrameProc_Spinning
|
|
FUN_8005b510();
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// without this, all shadows are solid rectangles
|
|
// VehGroundShadow_Subset1
|
|
undefined4 FUN_8005b6b8(undefined4 *param_1,int param_2)
|
|
|
|
{
|
|
int iVar1;
|
|
|
|
// get pointer to icon
|
|
iVar1 = *(int *)(PTR_DAT_8008d2ac + param_2 * 4 + 0x1eec);
|
|
|
|
// if icon is valid
|
|
if (iVar1 != 0) {
|
|
*param_1 = *(undefined4 *)(iVar1 + 0x14);
|
|
param_1[1] = *(uint *)(iVar1 + 0x18) & 0xff9fffff | 0x400000;
|
|
*(undefined2 *)(param_1 + 2) = *(undefined2 *)(iVar1 + 0x1c);
|
|
*(undefined2 *)((int)param_1 + 10) = *(undefined2 *)(iVar1 + 0x1e);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
// VehGroundShadow_Main
|
|
void FUN_8005b720(void)
|
|
|
|
{
|
|
undefined *puVar1;
|
|
char cVar2;
|
|
ushort uVar3;
|
|
int iVar4;
|
|
int iVar5;
|
|
uint uVar6;
|
|
uint uVar7;
|
|
short sVar8;
|
|
int iVar9;
|
|
MATRIX *pMVar10;
|
|
int iVar11;
|
|
uint *puVar12;
|
|
uint uVar13;
|
|
short sVar14;
|
|
undefined *puVar15;
|
|
uint *puVar16;
|
|
int iVar17;
|
|
short sVar18;
|
|
int iVar19;
|
|
int iVar20;
|
|
uint uVar21;
|
|
MATRIX *r0;
|
|
uint *puVar22;
|
|
uint *puVar23;
|
|
uint *puVar24;
|
|
uint *puVar25;
|
|
undefined2 *puVar26;
|
|
SVECTOR *r0_00;
|
|
undefined *puVar27;
|
|
uint *puVar28;
|
|
undefined auStack72 [32];
|
|
|
|
puVar27 = auStack72;
|
|
puVar23 = &DAT_1f800000;
|
|
|
|
// without this, all shadows are solid rectangles
|
|
iVar4 = FUN_8005b6b8(&DAT_1f800224,0);
|
|
|
|
if (
|
|
(
|
|
(iVar4 != 0) &&
|
|
(
|
|
// without this, all shadows are solid rectangles
|
|
iVar4 = FUN_8005b6b8(&DAT_1f800230,1),
|
|
iVar4 != 0
|
|
)
|
|
) &&
|
|
|
|
(
|
|
// backBuffer->primMem.curr
|
|
puVar28 = *(uint **)(*(int *)(PTR_DAT_8008d2ac + 0x10) + 0x80),
|
|
|
|
// if enough primMem remains to draw shadows
|
|
puVar28 + 0x140 < *(uint **)(*(int *)(PTR_DAT_8008d2ac + 0x10) + 0x84)
|
|
)
|
|
)
|
|
{
|
|
// set transformation vector to (0,0,0)
|
|
_DAT_1f800090 = 0;
|
|
DAT_1f800094 = 0;
|
|
DAT_1f800098 = 0;
|
|
gte_SetTransVector((VECTOR *)&DAT_1f800090);
|
|
|
|
// loop counter
|
|
iVar4 = 0;
|
|
|
|
puVar15 = (undefined *)((uint)puVar23 | 0xb6);
|
|
uVar21 = (uint)puVar23 | 0xa4;
|
|
|
|
// for iVar4 = 0; iVar4 < 8; iVar4++
|
|
do
|
|
{
|
|
uVar6 = uVar21;
|
|
puVar1 = PTR_DAT_8008d2ac;
|
|
|
|
// pointer to each player structure
|
|
iVar11 = *(int *)(PTR_DAT_8008d2ac + iVar4 * 4 + 0x24ec);
|
|
|
|
// if player pointer is invalid
|
|
if (iVar11 == 0) {
|
|
*(undefined4 *)(puVar15 + 2) = 0;
|
|
}
|
|
|
|
// if player pointer is valid
|
|
else
|
|
{
|
|
*(int *)(puVar15 + 2) = iVar11;
|
|
|
|
// get instance
|
|
iVar19 = *(int *)(iVar11 + 0x1c);
|
|
|
|
*(int *)(puVar15 + 6) = iVar19;
|
|
|
|
// instance flags
|
|
*(undefined2 *)(puVar15 + 0x14) = *(undefined2 *)(iVar19 + 0x28);
|
|
|
|
// numPlyrCurrGame - 1
|
|
iVar17 = (byte)puVar1[0x1ca8] - 1;
|
|
|
|
// numPlyrCurrGame > 0
|
|
if (-1 < iVar17)
|
|
{
|
|
// InstDrawPerPlayer = Instance -> InstDrawPerPlayer[iVar17]
|
|
iVar9 = iVar17 * 0x88 + iVar19;
|
|
|
|
// loop for all players
|
|
do
|
|
{
|
|
// flags?
|
|
puVar1 = (undefined *)(iVar9 + 0xb8);
|
|
|
|
// next InstDrawPerPlayer
|
|
iVar9 = iVar9 + -0x88;
|
|
|
|
iVar5 = uVar6 + iVar17;
|
|
iVar17 = iVar17 + -1;
|
|
*(undefined *)(iVar5 + 0x1c) = *puVar1;
|
|
} while (-1 < iVar17);
|
|
}
|
|
|
|
// PlayerX, quadblockHeight+3, PlayerZ
|
|
*(short *)(puVar15 + 0xe) = (short)((uint)*(undefined4 *)(iVar11 + 0x2d4) >> 8);
|
|
*(short *)(puVar15 + 0x10) = (short)((uint)*(undefined4 *)(iVar11 + 0x2d0) >> 8) + 3;
|
|
*(short *)(puVar15 + 0x12) = (short)((uint)*(undefined4 *)(iVar11 + 0x2dc) >> 8);
|
|
|
|
if ((*(ushort *)(puVar15 + 0x14) & 0x2000) == 0) {
|
|
cVar2 = *(char *)(iVar19 + 0x50);
|
|
}
|
|
else {
|
|
cVar2 = *(char *)(iVar19 + 0x51);
|
|
}
|
|
puVar15[1] = cVar2 + '\x01';
|
|
}
|
|
*puVar15 = 0;
|
|
puVar1 = PTR_DAT_8008d2ac;
|
|
|
|
// increment loop iteration counter
|
|
iVar4 = iVar4 + 1;
|
|
|
|
puVar15 = puVar15 + 0x28;
|
|
uVar21 = uVar6 + 0x28;
|
|
} while (iVar4 < 8);
|
|
|
|
*(undefined4 *)(uVar6 + 0x3c) = 0;
|
|
|
|
// numPlyrCurrGame - 1
|
|
iVar4 = (byte)puVar1[0x1ca8] - 1;
|
|
|
|
// loop through all player screens
|
|
if (-1 < iVar4)
|
|
{
|
|
iVar11 = -1;
|
|
r0_00 = (SVECTOR *)(puVar23 + 0x12);
|
|
uVar21 = 1;
|
|
|
|
// pushBuffer offset 0x38
|
|
puVar26 = (undefined2 *)(puVar1 + iVar4 * 0x110 + 0x1a0);
|
|
|
|
do {
|
|
puVar23[0x90] = *(uint *)(puVar26 + -0x10);
|
|
puVar23[0x8f] = *(uint *)(puVar26 + 0x5e);
|
|
|
|
// screen dimensions
|
|
gte_SetGeomOffset((int)((uint)(ushort)puVar26[-0xc] << 0x10) >> 0x11,
|
|
(int)((uint)(ushort)puVar26[-0xb] << 0x10) >> 0x11);
|
|
|
|
// distToScreen
|
|
gte_ldH(puVar23[0x90]);
|
|
|
|
puVar23[0x24] = *(uint *)(puVar26 + 0x22);
|
|
puVar23[0x25] = *(uint *)(puVar26 + 0x24);
|
|
puVar23[0x26] = *(uint *)(puVar26 + 0x26);
|
|
puVar23[0x14] = *(uint *)(puVar26 + -8);
|
|
puVar23[0x15] = *(uint *)(puVar26 + -6);
|
|
puVar23[0x16] = *(uint *)(puVar26 + -4);
|
|
uVar6 = *(uint *)(puVar26 + -2);
|
|
*(undefined2 *)(puVar23 + 0x18) = *puVar26;
|
|
puVar23[0x17] = uVar6;
|
|
|
|
gte_SetRotMatrix((MATRIX *)(puVar23 + 0x14));
|
|
|
|
puVar12 = puVar23 + 0x29;
|
|
uVar6 = puVar23[0x2e];
|
|
if (uVar6 != 0) {
|
|
puVar22 = puVar23 + 0x2e;
|
|
do {
|
|
if (*(char *)((int)puVar22 + -2) != iVar11) {
|
|
if ((*(ushort *)((int)puVar22 + 0x12) & 0x80) == 0) {
|
|
if ((*(byte *)((int)puVar12 + iVar4 + 0x1c) & 0x40) != 0) {
|
|
uVar3 = *(ushort *)(puVar22 + 3);
|
|
*(short *)(puVar23 + 0x27) =
|
|
(short)((uint)uVar3 - (uint)*(ushort *)(puVar23 + 0x24)) * 4;
|
|
iVar9 = (int)(((uint)uVar3 - (uint)*(ushort *)(puVar23 + 0x24)) * 0x40000) >> 0x10
|
|
;
|
|
iVar17 = (uint)*(ushort *)((int)puVar22 + 0xe) - (uint)*(ushort *)(puVar23 + 0x25)
|
|
;
|
|
*(short *)((int)puVar23 + 0x9e) = (short)iVar17 * 4;
|
|
iVar19 = iVar17 * 0x40000 >> 0x10;
|
|
iVar17 = (int)(((uint)*(ushort *)(puVar22 + 4) - (uint)*(ushort *)(puVar23 + 0x26)
|
|
) * 0x40000) >> 0x10;
|
|
*(short *)(puVar23 + 0x28) =
|
|
(short)((uint)*(ushort *)(puVar22 + 4) - (uint)*(ushort *)(puVar23 + 0x26)) *
|
|
4;
|
|
uVar7 = (uint)((int)puVar23[0x90] < 0x101);
|
|
if ((uVar7 == 0) ||
|
|
((((iVar9 < 0x1771 && (iVar19 < 0x1771)) &&
|
|
((iVar17 < 0x1771 && ((-0x1771 < iVar9 && (-0x1771 < iVar19)))))) &&
|
|
(-0x1771 < iVar17)))) {
|
|
gte_ldv0((SVECTOR *)(puVar23 + 0x27));
|
|
gte_rtv0();
|
|
iVar5 = gte_stMAC3();
|
|
iVar5 = iVar5 >> 2;
|
|
if (-0x35 < iVar5) {
|
|
if (uVar7 == 0) {
|
|
uVar7 = 0x2e1f1f1f;
|
|
}
|
|
else {
|
|
if (iVar5 < 0x180) {
|
|
uVar7 = 0x1f;
|
|
}
|
|
else
|
|
{
|
|
// asm address 8005bb04,
|
|
// changing 0x200 to 0x800, increases
|
|
// the render distance of shadows
|
|
iVar5 = (0x200 - iVar5) * 0x1f;
|
|
|
|
if (iVar5 < 0) {
|
|
iVar5 = iVar5 + 0x7f;
|
|
}
|
|
|
|
uVar7 = iVar5 >> 7;
|
|
|
|
// skip shadow draw
|
|
if ((int)uVar7 < 1) goto LAB_8005c0b8;
|
|
}
|
|
uVar7 = uVar7 | uVar7 << 8 | 0x2e000000 | uVar7 << 0x10;
|
|
}
|
|
puVar25 = puVar12;
|
|
if (*(char *)((int)puVar22 + -2) == '\0')
|
|
{
|
|
// player height, minus quadblock height
|
|
iVar17 = 0x100 - (*(int *)(uVar6 + 0x2d8) - *(int *)(uVar6 + 0x2d0) >> 8);
|
|
|
|
// if driver is too far from ground, skip shadow draw
|
|
if ((iVar17 < 1) || (0x109 < iVar17)) goto LAB_8005bb94;
|
|
|
|
r0 = (MATRIX *)(puVar23 + 0x1c);
|
|
if (0x100 < iVar17) {
|
|
iVar17 = 0x100;
|
|
}
|
|
iVar19 = (int)*(short *)(uVar6 + 0x2ee);
|
|
*(int *)(puVar27 + 0x10) = iVar11;
|
|
*(uint *)(puVar27 + 0x14) = uVar21;
|
|
*(SVECTOR **)(puVar27 + 0x18) = r0_00;
|
|
pMVar10 = r0;
|
|
|
|
// VehPhysForce_RotAxisAngle
|
|
FUN_8005f89c(r0,uVar6 + 0x370);
|
|
|
|
gte_SetLightMatrix(r0);
|
|
|
|
// loop counter
|
|
uVar6 = 0;
|
|
|
|
iVar20 = iVar17 * 0x29 >> 6;
|
|
iVar5 = iVar17 * 0x34 >> 6;
|
|
*(short *)(puVar23 + 0x12) = (short)(iVar17 * 0x28 >> 6);
|
|
*(undefined2 *)((int)puVar23 + 0x4a) = 0;
|
|
*(undefined2 *)(puVar23 + 0x13) = 0;
|
|
r0_00 = *(SVECTOR **)(puVar27 + 0x18);
|
|
uVar21 = *(uint *)(puVar27 + 0x14);
|
|
iVar11 = *(int *)(puVar27 + 0x10);
|
|
puVar25 = puVar12;
|
|
|
|
// for uVar6 = 0; uVar6 < 3; uVar6++
|
|
do
|
|
{
|
|
gte_ldv0(r0_00);
|
|
gte_llv0();
|
|
if (uVar6 == 0) {
|
|
*(undefined2 *)(puVar23 + 0x12) = 0;
|
|
*(short *)(puVar23 + 0x13) = (short)iVar20;
|
|
}
|
|
else if (uVar6 == uVar21) {
|
|
*(short *)(puVar23 + 0x13) = (short)iVar5;
|
|
}
|
|
read_mt(iVar9,iVar19,pMVar10);
|
|
*(short *)puVar12 = (short)iVar9;
|
|
*(short *)((int)puVar12 + 2) = (short)iVar19;
|
|
*(short *)(puVar12 + 1) = (short)pMVar10;
|
|
|
|
// increment loop counter
|
|
uVar6 = uVar6 + 1;
|
|
|
|
puVar12 = (uint *)((int)puVar12 + 6);
|
|
|
|
} while ((int)uVar6 < 3);
|
|
|
|
gte_SetRotMatrix((MATRIX *)(puVar23 + 0x14));
|
|
|
|
sVar8 = *(short *)(puVar23 + 0x27);
|
|
sVar14 = *(short *)((int)puVar23 + 0x9e);
|
|
sVar18 = *(short *)(puVar23 + 0x28);
|
|
*(char *)((int)puVar22 + -2) = (char)uVar21;
|
|
iVar9 = (int)sVar8;
|
|
iVar19 = (int)sVar14;
|
|
iVar17 = (int)sVar18;
|
|
}
|
|
sVar18 = (short)iVar9;
|
|
*(short *)(puVar23 + 0x83) = sVar18;
|
|
sVar14 = (short)iVar19;
|
|
*(short *)((int)puVar23 + 0x20e) = sVar14;
|
|
sVar8 = (short)iVar17;
|
|
*(short *)(puVar23 + 0x84) = sVar8;
|
|
*(short *)(puVar23 + 0x85) =
|
|
(sVar18 - *(short *)puVar25) - *(short *)((int)puVar22 + -0xe);
|
|
*(short *)((int)puVar23 + 0x216) =
|
|
(sVar14 - *(short *)((int)puVar22 + -0x12)) - *(short *)(puVar22 + -3);
|
|
*(short *)(puVar23 + 0x86) =
|
|
(sVar8 - *(short *)(puVar22 + -4)) - *(short *)((int)puVar22 + -10);
|
|
iVar5 = 0;
|
|
*(short *)(puVar23 + 0x87) = sVar18 - *(short *)((int)puVar22 + -0xe);
|
|
iVar20 = 0x24;
|
|
*(short *)((int)puVar23 + 0x21e) = sVar14 - *(short *)(puVar22 + -3);
|
|
*(short *)(puVar23 + 0x88) = sVar8 - *(short *)((int)puVar22 + -10);
|
|
puVar24 = puVar23;
|
|
do {
|
|
gte_ldv3c((SVECTOR *)(puVar24 + 0x83));
|
|
gte_rtpt();
|
|
sVar8 = (short)iVar9;
|
|
sVar14 = (short)iVar19;
|
|
sVar18 = (short)iVar17;
|
|
if (iVar5 == 0) {
|
|
*(short *)(puVar24 + 0x83) =
|
|
(*(short *)puVar25 + sVar8) - *(short *)((int)puVar22 + -0xe);
|
|
*(short *)((int)puVar24 + 0x20e) =
|
|
(*(short *)((int)puVar22 + -0x12) + sVar14) -
|
|
*(short *)(puVar22 + -3);
|
|
*(short *)(puVar24 + 0x84) =
|
|
(*(short *)(puVar22 + -4) + sVar18) - *(short *)((int)puVar22 + -10);
|
|
*(short *)(puVar24 + 0x85) = *(short *)puVar25 + sVar8;
|
|
*(short *)((int)puVar24 + 0x216) =
|
|
*(short *)((int)puVar22 + -0x12) + sVar14;
|
|
*(short *)(puVar24 + 0x86) = *(short *)(puVar22 + -4) + sVar18;
|
|
*(short *)(puVar24 + 0x87) =
|
|
*(short *)(puVar22 + -2) + *(short *)puVar25 + sVar8;
|
|
*(short *)((int)puVar24 + 0x21e) =
|
|
*(short *)((int)puVar22 + -6) +
|
|
*(short *)((int)puVar22 + -0x12) + sVar14;
|
|
*(short *)(puVar24 + 0x88) =
|
|
*(short *)(puVar22 + -1) + *(short *)(puVar22 + -4) + sVar18;
|
|
}
|
|
else if (iVar5 == 3) {
|
|
*(short *)(puVar24 + 0x83) = *(short *)(puVar22 + -2) + sVar8;
|
|
*(short *)((int)puVar24 + 0x20e) = *(short *)((int)puVar22 + -6) + sVar14;
|
|
*(short *)(puVar24 + 0x84) = *(short *)(puVar22 + -1) + sVar18;
|
|
*(short *)(puVar24 + 0x85) =
|
|
*(short *)(puVar22 + -2) + (sVar8 - *(short *)puVar25);
|
|
*(short *)((int)puVar24 + 0x216) =
|
|
*(short *)((int)puVar22 + -6) +
|
|
(sVar14 - *(short *)((int)puVar22 + -0x12));
|
|
*(short *)(puVar24 + 0x86) =
|
|
*(short *)(puVar22 + -1) + (sVar18 - *(short *)(puVar22 + -4));
|
|
*(short *)(puVar24 + 0x87) = sVar8 - *(short *)puVar25;
|
|
*(short *)((int)puVar24 + 0x21e) =
|
|
sVar14 - *(short *)((int)puVar22 + -0x12);
|
|
*(short *)(puVar24 + 0x88) = sVar18 - *(short *)(puVar22 + -4);
|
|
}
|
|
gte_stsxy3c((long *)puVar23);
|
|
gte_stsz3c((long *)((int)puVar24 + iVar20));
|
|
iVar20 = iVar20 + 0xc;
|
|
iVar5 = iVar5 + 3;
|
|
puVar23 = puVar23 + 3;
|
|
} while (iVar5 < 9);
|
|
uVar6 = 0;
|
|
puVar16 = puVar28 + 8;
|
|
do {
|
|
puVar23 = puVar24 + 0x89;
|
|
if ((uVar6 & 1) != 0) {
|
|
puVar23 = puVar24 + 0x8c;
|
|
}
|
|
puVar16[-7] = uVar7;
|
|
puVar16[-5] = *puVar23;
|
|
puVar16[-3] = puVar23[1];
|
|
*(undefined2 *)(puVar16 + -1) = *(undefined2 *)(puVar23 + 2);
|
|
*(undefined2 *)(puVar16 + 1) = *(undefined2 *)((int)puVar23 + 10);
|
|
if (uVar6 == uVar21) {
|
|
puVar16[-6] = puVar24[8];
|
|
puVar16[-4] = *puVar24;
|
|
puVar16[-2] = puVar24[7];
|
|
LAB_8005c044:
|
|
*puVar16 = puVar24[6];
|
|
}
|
|
else if ((int)uVar6 < 2) {
|
|
if (uVar6 == 0) {
|
|
puVar16[-6] = puVar24[8];
|
|
puVar16[-4] = *puVar24;
|
|
puVar16[-2] = puVar24[1];
|
|
*puVar16 = puVar24[2];
|
|
}
|
|
}
|
|
else if (uVar6 == 2) {
|
|
puVar16[-6] = puVar24[4];
|
|
puVar16[-4] = *puVar24;
|
|
puVar16[-2] = puVar24[3];
|
|
*puVar16 = puVar24[2];
|
|
}
|
|
else if (uVar6 == 3) {
|
|
puVar16[-6] = puVar24[4];
|
|
puVar16[-4] = *puVar24;
|
|
puVar16[-2] = puVar24[5];
|
|
goto LAB_8005c044;
|
|
}
|
|
iVar19 = ((int)puVar24[9] >> 8) + (int)*(char *)((int)puVar22 + -1);
|
|
iVar17 = iVar19;
|
|
if (iVar19 < 0) {
|
|
iVar17 = 0;
|
|
}
|
|
if (0x3ff < iVar19) {
|
|
iVar17 = 0x3ff;
|
|
}
|
|
puVar16 = puVar16 + 10;
|
|
uVar6 = uVar6 + 1;
|
|
uVar13 = (uint)puVar28 & 0xffffff;
|
|
puVar23 = (uint *)(puVar24[0x8f] + iVar17 * 4);
|
|
*puVar28 = *puVar23 | 0x9000000;
|
|
puVar28 = puVar28 + 10;
|
|
*puVar23 = uVar13;
|
|
puVar23 = puVar24;
|
|
puVar12 = puVar25;
|
|
} while ((int)uVar6 < 4);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
LAB_8005bb94:
|
|
*(char *)((int)puVar22 + -2) = (char)iVar11;
|
|
}
|
|
}
|
|
LAB_8005c0b8:
|
|
puVar22 = puVar22 + 10;
|
|
uVar6 = *puVar22;
|
|
puVar12 = puVar12 + 10;
|
|
} while (uVar6 != 0);
|
|
}
|
|
iVar4 = iVar4 + -1;
|
|
puVar26 = puVar26 + -0x88;
|
|
} while (-1 < iVar4);
|
|
}
|
|
|
|
// backBuffer->primMem.curr
|
|
*(uint **)(*(int *)(PTR_DAT_8008d2ac + 0x10) + 0x80) = puVar28;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// VehGroundSkids_Subset1
|
|
void FUN_8005c120(uint *param_1,uint *param_2,int param_3,int param_4)
|
|
|
|
{
|
|
undefined *puVar1;
|
|
uint uVar2;
|
|
int iVar3;
|
|
uint uVar4;
|
|
uint *puVar5;
|
|
uint *puVar6;
|
|
|
|
puVar1 = PTR_DAT_8008d2ac;
|
|
|
|
// gGT->backDB
|
|
iVar3 = *(int *)(PTR_DAT_8008d2ac + 0x10);
|
|
|
|
// primMem.curr
|
|
puVar6 = *(uint **)(iVar3 + 0x80);
|
|
|
|
// if there is room to draw
|
|
if (puVar6 + 0xd <= *(uint **)(iVar3 + 0x84))
|
|
{
|
|
|
|
// primMem.curr += 0x34
|
|
*(uint **)(iVar3 + 0x80) = puVar6 + 0xd;
|
|
|
|
puVar6[1] = *(uint *)(param_4 + 0x1c);
|
|
puVar6[4] = *(uint *)(param_4 + 0x1c);
|
|
puVar6[7] = *(uint *)(param_4 + 0x20);
|
|
puVar6[10] = *(uint *)(param_4 + 0x20);
|
|
puVar6[2] = *param_1;
|
|
puVar6[5] = param_1[1];
|
|
puVar6[8] = *param_2;
|
|
puVar6[0xb] = param_2[1];
|
|
|
|
// gGT->0x1fa8 = gGT->0x1eec[0x2f*4] = skidmark
|
|
|
|
puVar6[3] = *(uint *)(*(int *)(puVar1 + 0x1fa8) + 0x14);
|
|
if ((*(uint *)(param_4 + 0x24) & 1) == 0) {
|
|
uVar2 = *(uint *)(*(int *)(puVar1 + 0x1fa8) + 0x18);
|
|
uVar4 = 0x400000;
|
|
}
|
|
else {
|
|
uVar2 = *(uint *)(*(int *)(puVar1 + 0x1fa8) + 0x18);
|
|
uVar4 = 0x600000;
|
|
}
|
|
puVar6[6] = uVar2 & 0xff9fffff | uVar4;
|
|
puVar1 = PTR_DAT_8008d2ac;
|
|
*(undefined2 *)(puVar6 + 9) = *(undefined2 *)(*(int *)(PTR_DAT_8008d2ac + 0x1fa8) + 0x1c);
|
|
*(undefined2 *)(puVar6 + 0xc) = *(undefined2 *)(*(int *)(puVar1 + 0x1fa8) + 0x1e);
|
|
puVar5 = (uint *)(*(int *)(*(int *)(param_4 + 0x18) + 0xf4) + (param_3 >> 6) * 4);
|
|
*puVar6 = *puVar5 | 0xc000000;
|
|
*puVar5 = (uint)puVar6 & 0xffffff;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// VehGroundSkids_Subset2
|
|
void FUN_8005c278(short *param_1,short *param_2,short *param_3,short *param_4)
|
|
|
|
{
|
|
*param_1 = (*param_2 - param_1[0x5c]) * 4;
|
|
param_1[1] = (param_2[1] - param_1[0x5e]) * 4;
|
|
param_1[2] = (param_2[2] - param_1[0x60]) * 4;
|
|
param_1[4] = (*param_3 - param_1[0x5c]) * 4;
|
|
param_1[5] = (param_3[1] - param_1[0x5e]) * 4;
|
|
param_1[6] = (param_3[2] - param_1[0x60]) * 4;
|
|
param_1[8] = (*param_4 - param_1[0x5c]) * 4;
|
|
param_1[9] = (param_4[1] - param_1[0x5e]) * 4;
|
|
param_1[10] = (param_4[2] - param_1[0x60]) * 4;
|
|
return;
|
|
}
|
|
|
|
|
|
// VehGroundSkids_Main
|
|
// param_1 - thread pointer (player or robot)
|
|
// param_2 - pushBuffer pointer
|
|
void FUN_8005c354(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
uint uVar1;
|
|
int iVar2;
|
|
int iVar3;
|
|
int iVar4;
|
|
int iVar5;
|
|
SVECTOR *pSVar6;
|
|
SVECTOR *pSVar7;
|
|
SVECTOR *r0;
|
|
SVECTOR *pSVar8;
|
|
SVECTOR *r0_00;
|
|
uint uVar9;
|
|
SVECTOR *pSVar10;
|
|
undefined *puVar11;
|
|
uint uVar12;
|
|
undefined auStack64 [24];
|
|
|
|
puVar11 = auStack64;
|
|
|
|
// window dimensions
|
|
gte_SetGeomOffset((int)((uint)*(ushort *)(param_2 + 0x20) << 0x10) >> 0x11,
|
|
(int)((uint)*(ushort *)(param_2 + 0x22) << 0x10) >> 0x11);
|
|
|
|
// distance to screen
|
|
gte_ldH(*(undefined4 *)(param_2 + 0x18));
|
|
|
|
r0 = (SVECTOR *)&DAT_1f800000;
|
|
DAT_1f8000b8 = 0;
|
|
DAT_1f8000bc = 0;
|
|
DAT_1f8000c0 = 0;
|
|
DAT_1f800018 = param_2;
|
|
|
|
// pushBuffer offset 0x28, ViewProj
|
|
gte_SetRotMatrix((MATRIX *)(param_2 + 0x28));
|
|
gte_SetTransVector((VECTOR *)&DAT_1f8000b8);
|
|
|
|
*(undefined4 *)(r0 + 0x17) = *(undefined4 *)(param_2 + 0x7c);
|
|
*(undefined4 *)&r0[0x17].vz = *(undefined4 *)(param_2 + 0x80);
|
|
*(undefined4 *)(r0 + 0x18) = *(undefined4 *)(param_2 + 0x84);
|
|
|
|
// this is "somehow" param_1 (thread)
|
|
iVar5 = *(int *)(puVar11 + 0x40);
|
|
|
|
do {
|
|
if (iVar5 == 0) {
|
|
return;
|
|
}
|
|
|
|
// thread -> object
|
|
iVar5 = *(int *)(*(int *)(puVar11 + 0x40) + 0x30);
|
|
|
|
*(int *)(puVar11 + 0x10) = iVar5;
|
|
|
|
// if skidmarks are enabled...
|
|
// will be enabled for 7 frames after drift stops,
|
|
// because of how the bit shifting works
|
|
uVar9 = *(uint *)(iVar5 + 0x2c4);
|
|
|
|
// if skidmarks are enabled
|
|
if (0xf < uVar9) {
|
|
uVar12 = 0;
|
|
pSVar7 = r0 + 5;
|
|
pSVar6 = r0 + 0xe;
|
|
pSVar10 = (SVECTOR *)&r0[9].vz;
|
|
uVar1 = *(byte *)(iVar5 + 0xc3) - 1 & 7;
|
|
*(uint *)(puVar11 + 0x14) = uVar1;
|
|
iVar5 = iVar5 + uVar1 * 0x40;
|
|
iVar2 = (int)*(short *)(iVar5 + 0xc4) - *(int *)(r0 + 0x17);
|
|
iVar4 = iVar2 * 4;
|
|
iVar3 = iVar4;
|
|
if (iVar4 < 0) {
|
|
iVar3 = iVar2 * -4;
|
|
}
|
|
pSVar8 = (SVECTOR *)&r0[0x12].vz;
|
|
if (iVar3 < 0x1771) {
|
|
r0->vx = (short)iVar4;
|
|
iVar2 = (int)*(short *)(iVar5 + 0xc6) - *(int *)&r0[0x17].vz;
|
|
iVar4 = iVar2 * 4;
|
|
iVar3 = iVar4;
|
|
if (iVar4 < 0) {
|
|
iVar3 = iVar2 * -4;
|
|
}
|
|
if (iVar3 < 0x1771) {
|
|
r0->vy = (short)iVar4;
|
|
iVar3 = (int)*(short *)(iVar5 + 200) - *(int *)(r0 + 0x18);
|
|
iVar2 = iVar3 * 4;
|
|
iVar5 = iVar2;
|
|
if (iVar2 < 0) {
|
|
iVar5 = iVar3 * -4;
|
|
}
|
|
if (iVar5 < 0x1771) {
|
|
r0->vz = (short)iVar2;
|
|
gte_ldv0(r0);
|
|
gte_rtv0();
|
|
iVar5 = gte_stMAC3();
|
|
if (iVar5 >> 2 < 0x180) {
|
|
uVar1 = 0x7f;
|
|
}
|
|
else {
|
|
gte_ldLZCS((iVar5 >> 2) + -0x180);
|
|
iVar5 = gte_stLZCR();
|
|
uVar1 = 0x1a - iVar5;
|
|
if ((int)uVar1 < 0) {
|
|
uVar1 = 0;
|
|
}
|
|
uVar1 = 0x7f >> (uVar1 & 0x1f);
|
|
if ((int)uVar1 < 0x10) goto LAB_8005c9dc;
|
|
}
|
|
*(uint *)&r0[3].vz = uVar1 | uVar1 << 8 | 0x3e000000 | uVar1 << 0x10;
|
|
*(undefined4 *)(r0 + 4) = 0xffffffff;
|
|
do {
|
|
uVar1 = uVar9;
|
|
r0_00 = pSVar7;
|
|
pSVar7 = pSVar6;
|
|
if (uVar1 == 0) break;
|
|
if ((uVar1 & 0xf) != 0)
|
|
{
|
|
iVar3 = *(int *)(puVar11 + 0x14) * 0x40;
|
|
iVar5 = *(int *)(puVar11 + 0x10) + iVar3 + 0xc4;
|
|
|
|
FUN_8005c278(r0,iVar5,iVar5 + 8,iVar5 + 0x10);
|
|
gte_ldv3c(r0);
|
|
gte_rtpt();
|
|
|
|
FUN_8005c278(r0,iVar5 + 0x18,iVar5 + 0x20,iVar5 + 0x28);
|
|
gte_stsxy3c((long *)r0_00);
|
|
gte_stsz3c((long *)pSVar7);
|
|
gte_ldv3c(r0);
|
|
gte_rtpt();
|
|
|
|
FUN_8005c278(r0,iVar5 + 0x30,iVar5 + 0x38,iVar5);
|
|
gte_stsxy3c((long *)&r0_00[1].vz);
|
|
gte_stsz3c((long *)&pSVar7[1].vz);
|
|
gte_ldv3c(r0);
|
|
gte_rtpt();
|
|
|
|
gte_stsxy3c((long *)(r0_00 + 3));
|
|
gte_stsz3c((long *)(pSVar7 + 3));
|
|
|
|
// skidmark primitive 1/4
|
|
if (((((uVar1 & uVar12 & 1) != 0) && (0x20 < *(int *)pSVar7)) &&
|
|
(0x20 < *(int *)&pSVar7->vz)) &&
|
|
((0x20 < *(int *)pSVar8 && (0x20 < *(int *)&pSVar8->vz))))
|
|
{
|
|
iVar5 = *(int *)(puVar11 + 0x10);
|
|
*(uint *)&r0[4].vz = (uint)*(byte *)(iVar5 + iVar3 + 0xcb);
|
|
|
|
// draw prim
|
|
FUN_8005c120(r0_00,pSVar10,
|
|
(*(int *)pSVar7 >> 2) + (uint)*(byte *)(iVar5 + iVar3 + 0xca) * 0x40,
|
|
r0);
|
|
}
|
|
|
|
// skidmark primitive 2/4
|
|
if ((((uVar1 & uVar12 & 2) != 0) && (0x20 < *(int *)(pSVar7 + 1))) &&
|
|
((0x20 < *(int *)&pSVar7[1].vz &&
|
|
((0x20 < *(int *)(pSVar8 + 1) && (0x20 < *(int *)&pSVar8[1].vz))))))
|
|
{
|
|
iVar5 = *(int *)(puVar11 + 0x14);
|
|
iVar3 = *(int *)(puVar11 + 0x10);
|
|
*(uint *)&r0[4].vz = (uint)*(byte *)(iVar3 + iVar5 * 0x40 + 0xdb);
|
|
|
|
// draw prim
|
|
FUN_8005c120(r0_00 + 1,pSVar10 + 1,
|
|
(*(int *)(pSVar7 + 1) >> 2) +
|
|
(uint)*(byte *)(iVar3 + iVar5 * 0x40 + 0xda) * 0x40,r0);
|
|
}
|
|
|
|
// skidmark primitive 3/4
|
|
if (((((uVar1 & uVar12 & 4) != 0) && (0x20 < *(int *)(pSVar7 + 2))) &&
|
|
(0x20 < *(int *)&pSVar7[2].vz)) &&
|
|
((0x20 < *(int *)(pSVar8 + 2) && (0x20 < *(int *)&pSVar8[2].vz))))
|
|
{
|
|
iVar5 = *(int *)(puVar11 + 0x14);
|
|
iVar3 = *(int *)(puVar11 + 0x10);
|
|
*(uint *)&r0[4].vz = (uint)*(byte *)(iVar3 + iVar5 * 0x40 + 0xeb);
|
|
|
|
// draw prim
|
|
FUN_8005c120(r0_00 + 2,pSVar10 + 2,
|
|
(*(int *)(pSVar7 + 2) >> 2) +
|
|
(uint)*(byte *)(iVar3 + iVar5 * 0x40 + 0xea) * 0x40,r0);
|
|
}
|
|
|
|
// skidmark primitive 4/4
|
|
if ((((uVar1 & uVar12 & 8) != 0) && (0x20 < *(int *)(pSVar7 + 3))) &&
|
|
((0x20 < *(int *)&pSVar7[3].vz &&
|
|
((0x20 < *(int *)(pSVar8 + 3) && (0x20 < *(int *)&pSVar8[3].vz))))))
|
|
{
|
|
iVar5 = *(int *)(puVar11 + 0x14);
|
|
iVar3 = *(int *)(puVar11 + 0x10);
|
|
*(uint *)&r0[4].vz = (uint)*(byte *)(iVar3 + iVar5 * 0x40 + 0xfb);
|
|
|
|
// draw prim
|
|
FUN_8005c120(r0_00 + 3,pSVar10 + 3,
|
|
(*(int *)(pSVar7 + 3) >> 2) +
|
|
(uint)*(byte *)(iVar3 + iVar5 * 0x40 + 0xfa) * 0x40,r0);
|
|
}
|
|
}
|
|
*(uint *)(puVar11 + 0x14) = *(int *)(puVar11 + 0x14) + 1U & 7;
|
|
if (*(int *)(r0 + 4) == -1) {
|
|
*(undefined4 *)(r0 + 4) = *(undefined4 *)&r0[3].vz;
|
|
uVar9 = uVar1;
|
|
uVar1 = 0xf;
|
|
}
|
|
else {
|
|
uVar9 = uVar1 >> 4;
|
|
uVar12 = (int)(*(uint *)&r0[3].vz & 0xff) >> 1;
|
|
*(undefined4 *)(r0 + 4) = *(undefined4 *)&r0[3].vz;
|
|
*(uint *)&r0[3].vz = uVar12 | uVar12 << 8 | 0x3e000000 | uVar12 << 0x10;
|
|
}
|
|
pSVar6 = pSVar8;
|
|
pSVar8 = pSVar7;
|
|
pSVar7 = pSVar10;
|
|
pSVar10 = r0_00;
|
|
uVar12 = uVar1;
|
|
} while (*(int *)(r0 + 4) != 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
LAB_8005c9dc:
|
|
|
|
// thread = thread -> next
|
|
iVar5 = *(int *)(*(int *)(puVar11 + 0x40) + 0x10);
|
|
*(int *)(puVar11 + 0x40) = iVar5;
|
|
|
|
} while( true );
|
|
}
|
|
|
|
|
|
// VehLap_UpdateProgress (param1=driver)
|
|
void FUN_8005ca24(int param_1)
|
|
|
|
{
|
|
ushort uVar1;
|
|
undefined *puVar2;
|
|
undefined4 in_zero;
|
|
undefined4 in_at;
|
|
undefined4 uVar3;
|
|
undefined4 uVar4;
|
|
uint uVar5;
|
|
int iVar6;
|
|
int iVar7;
|
|
short *psVar8;
|
|
int iVar9;
|
|
short *psVar10;
|
|
ushort uVar11;
|
|
int iVar12;
|
|
undefined4 local_30;
|
|
undefined4 local_20;
|
|
uint local_1c;
|
|
|
|
// if player structure is not nullptr
|
|
if (param_1 != 0)
|
|
{
|
|
uVar11 = 0xffff;
|
|
|
|
// If this is human and not an AI
|
|
if ((*(uint *)(param_1 + 0x2c8) & 0x100000) == 0)
|
|
{
|
|
// quadblock (last valid)
|
|
iVar7 = *(int *)(param_1 + 0x354);
|
|
|
|
if (
|
|
// if quadblock exists
|
|
(iVar7 != 0) &&
|
|
|
|
// quadBlock -> checkpointIndex is valid
|
|
(*(char *)(iVar7 + 0x3e) != -1)
|
|
)
|
|
{
|
|
// quadblock -> checkpointIndex
|
|
uVar11 = (ushort)*(byte *)(iVar7 + 0x3e);
|
|
}
|
|
}
|
|
|
|
// If this is an AI
|
|
else
|
|
{
|
|
// duplicate of quadblock checkpointIndex (AI-exclusive)
|
|
uVar11 = (ushort)*(byte *)(param_1 + 0x60a);
|
|
}
|
|
|
|
// if level has respawn points
|
|
if ((*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0x148) - 1U < 0xff) &&
|
|
|
|
// checkpointIndex is valid
|
|
(-1 < (int)(short)uVar11))
|
|
{
|
|
// array of respawn points
|
|
iVar7 = *(int *)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0x14c);
|
|
|
|
// byte offset of respawn point from last-valid quadblock
|
|
iVar12 = iVar7 + (int)(short)uVar11 * 0xc;
|
|
|
|
// pointer to desired respawn point
|
|
psVar10 = (short *)(iVar7 + (uint)*(byte *)(iVar12 + 8) * 0xc);
|
|
|
|
// Player X, Y, and Z
|
|
uVar3 = *(undefined4 *)(param_1 + 0x2d4);
|
|
uVar4 = *(undefined4 *)(param_1 + 0x2d8);
|
|
uVar5 = *(uint *)(param_1 + 0x2dc);
|
|
|
|
psVar8 = (short *)(iVar7 + (uint)*(byte *)(psVar10 + 4) * 0xc);
|
|
local_20 = CONCAT22(psVar10[1] - psVar8[1],*psVar10 - *psVar8);
|
|
local_1c = local_1c & 0xffff0000 | (uint)(ushort)(psVar10[2] - psVar8[2]);
|
|
|
|
// MATH_VectorNormalize
|
|
FUN_8003d378(&local_20);
|
|
|
|
local_30 = CONCAT22((short)((uint)uVar4 >> 8) - psVar10[1],
|
|
(short)((uint)uVar3 >> 8) - *psVar10);
|
|
gte_ldR11R12(local_30);
|
|
gte_ldR13R21((uint)(ushort)((short)((uint)uVar5 >> 8) - psVar10[2]) |
|
|
((int)((uint)*(ushort *)(param_1 + 0x314) << 0x10) >> 0x15) << 0x10);
|
|
gte_ldR22R23((int)((uint)*(ushort *)(param_1 + 0x31a) << 0x10) >> 0x15 & 0xffffU |
|
|
((int)((uint)*(ushort *)(param_1 + 800) << 0x10) >> 0x15) << 0x10);
|
|
gte_ldv0(&local_20);
|
|
gte_mvmva(0,0,0,3,0);
|
|
|
|
iVar7 = gte_stMAC1();
|
|
iVar9 = gte_stMAC2();
|
|
iVar6 = (uint)(ushort)psVar10[3] * 8 + (iVar7 >> 0xc);
|
|
|
|
// set new progress
|
|
*(int *)(param_1 + 0x488) = iVar6;
|
|
|
|
puVar2 = PTR_DAT_8008d2ac;
|
|
uVar1 = *(ushort *)(*(int *)(*(int *)(puVar2 + 0x160) + 0x14c) + 6);
|
|
iVar7 = (uint)uVar1 << 3;
|
|
if (uVar1 == 0) {
|
|
trap(0x1c00);
|
|
}
|
|
if ((iVar7 == -1) && (iVar6 == -0x80000000)) {
|
|
trap(0x1800);
|
|
}
|
|
|
|
// set new progress
|
|
*(int *)(param_1 + 0x488) = iVar6 % iVar7;
|
|
|
|
if (iVar9 < 0x5a801) {
|
|
//uVar5 = Actions Flag set with 9th bit off
|
|
uVar5 = *(uint *)(param_1 + 0x2c8) & 0xfffffeff;
|
|
}
|
|
else {
|
|
//uVar5 = Actions Flag set with 9th bit on
|
|
uVar5 = *(uint *)(param_1 + 0x2c8) | 0x100;
|
|
}
|
|
|
|
//manage 9th bit of Actions Flag set
|
|
*(uint *)(param_1 + 0x2c8) = uVar5;
|
|
|
|
//if 28th bit of Actions Flag set is on (means ?) and
|
|
if (((*(uint *)(param_1 + 0x2c8) & 0x8000000) != 0) &&
|
|
((uint)*(byte *)(param_1 + 0x495) != (int)(short)uVar11))
|
|
{
|
|
// save respawn index
|
|
*(undefined *)(param_1 + 0x494) = (char)uVar11;
|
|
|
|
//turn off 28th bit of Actions Flag set (means ?)
|
|
*(uint *)(param_1 + 0x2c8) = *(uint *)(param_1 + 0x2c8) & 0xf7ffffff;
|
|
}
|
|
if (*(char *)(iVar12 + 9) != -1) {
|
|
//turn on 28th bit of Actions Flag set (means ?)
|
|
*(uint *)(param_1 + 0x2c8) = *(uint *)(param_1 + 0x2c8) | 0x8000000;
|
|
}
|
|
|
|
// checkpointIndex
|
|
*(undefined *)(param_1 + 0x495) = (char)uVar11;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
// VehPhysCrash_ConvertVecToSpeed
|
|
// param_1: &driver
|
|
// param_2: velocityXYZs
|
|
void FUN_8005cd1c(int param_1,int *param_2)
|
|
|
|
{
|
|
undefined2 extraout_var;
|
|
short extraout_var_00;
|
|
short extraout_var_01;
|
|
long x;
|
|
int iVar1;
|
|
int iVar2;
|
|
int iVar3;
|
|
int iVar4;
|
|
|
|
// 2D movement
|
|
// x = sqrt(x2+z2 << 0x10)
|
|
x = FUN_80059070(*param_2 * *param_2 + param_2[2] * param_2[2], 0x10);
|
|
|
|
// 3D movement
|
|
// sqrt(x2+y2+z2 << 0x10)
|
|
FUN_80059070(*param_2 * *param_2 + param_2[1] * param_2[1] + param_2[2] * param_2[2],0x10);
|
|
|
|
// Ghidra missed this!
|
|
// extraout_var = FUN_80059070(*param_2 * *param_2 + param_2[1] * param_2[1] + param_2[2] * param_2[2],0x10);
|
|
// extraout_var = extraout_var << 0x8;
|
|
|
|
// 3D speed
|
|
*(undefined2 *)(param_1 + 0x38c) = extraout_var;
|
|
|
|
// X speed
|
|
x = ratan2(param_2[1] << 8,x);
|
|
*(undefined2 *)(param_1 + 0x394) = (short)x;
|
|
|
|
// Z speed
|
|
x = ratan2(*param_2,param_2[2]);
|
|
*(undefined2 *)(param_1 + 0x396) = (short)x;
|
|
|
|
iVar4 = *param_2 * (int)*(short *)(param_1 + 0x312) +
|
|
param_2[1] * (int)*(short *)(param_1 + 0x318) +
|
|
param_2[2] * (int)*(short *)(param_1 + 0x31e) >> 0xc;
|
|
|
|
iVar1 = (int)*(short *)(param_1 + 0x312) * iVar4 >> 0xc;
|
|
iVar2 = (int)*(short *)(param_1 + 0x318) * iVar4 >> 0xc;
|
|
iVar3 = (int)*(short *)(param_1 + 0x31e) * iVar4 >> 0xc;
|
|
|
|
// sqrt(x2+y2+z2 << 0x10)
|
|
FUN_80059070(iVar1 * iVar1 + iVar2 * iVar2 + iVar3 * iVar3,0x10);
|
|
|
|
// Ghidra missed this!
|
|
// extraout_var_00 = FUN_80059070(iVar1 * iVar1 + iVar2 * iVar2 + iVar3 * iVar3,0x10);
|
|
// extraout_var_00 = extraout_var_00 << 0x8;
|
|
|
|
*(short *)(param_1 + 0x390) = extraout_var_00;
|
|
if (iVar4 < 0) {
|
|
*(short *)(param_1 + 0x390) = -extraout_var_00;
|
|
}
|
|
iVar1 = *param_2 - iVar1;
|
|
iVar2 = param_2[1] - iVar2;
|
|
iVar3 = param_2[2] - iVar3;
|
|
|
|
// sqrt(x2+y2+z2 << 0x10)
|
|
FUN_80059070(iVar1 * iVar1 + iVar2 * iVar2 + iVar3 * iVar3,0x10);
|
|
|
|
// Ghidra missed this!
|
|
// extraout_var_01 = FUN_80059070(iVar1 * iVar1 + iVar2 * iVar2 + iVar3 * iVar3,0x10);
|
|
// extraout_var_01 = extraout_var_01 << 0x8;
|
|
|
|
*(short *)(param_1 + 0x38e) = extraout_var_01;
|
|
if (
|
|
iVar1 * *(short *)(param_1 + 0x314) +
|
|
iVar2 * *(short *)(param_1 + 0x31a) +
|
|
iVar3 * *(short *)(param_1 + 0x320)
|
|
< 0
|
|
) {
|
|
*(short *)(param_1 + 0x38e) = -extraout_var_01;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// VehPhysCrash_BounceSelf
|
|
undefined4 FUN_8005cf64(short *param_1,int *param_2,int *param_3,int param_4)
|
|
|
|
{
|
|
short sVar1;
|
|
short sVar2;
|
|
int iVar3;
|
|
int iVar4;
|
|
int iVar5;
|
|
int iVar6;
|
|
int iVar7;
|
|
int iVar8;
|
|
|
|
iVar5 = param_2[1];
|
|
iVar6 = param_2[2];
|
|
iVar8 = (*param_3 - *param_2) * (int)*param_1 + (param_3[1] - iVar5) * (int)param_1[1] +
|
|
(param_3[2] - iVar6) * (int)param_1[2] >> 0xc;
|
|
if (param_4 == 0) {
|
|
if (iVar8 < 0) goto LAB_8005cfdc;
|
|
}
|
|
else {
|
|
if (0 < iVar8) {
|
|
LAB_8005cfdc:
|
|
iVar7 = iVar8;
|
|
if (iVar8 < 0) {
|
|
iVar7 = -iVar8;
|
|
}
|
|
if (DAT_8008d9f4 < iVar7) {
|
|
DAT_8008d9f4 = iVar7;
|
|
}
|
|
iVar7 = iVar8 * *param_1 >> 0x1f;
|
|
sVar1 = param_1[1];
|
|
sVar2 = param_1[2];
|
|
iVar3 = iVar8 * sVar1 >> 0x1f;
|
|
iVar4 = iVar8 * sVar2 >> 0x1f;
|
|
*param_3 = ((*param_3 - *param_2) - (((iVar8 * *param_1) / 6 + iVar7 >> 9) - iVar7)) +
|
|
*param_2;
|
|
iVar5 = ((param_3[1] - iVar5) - (((iVar8 * sVar1) / 6 + iVar3 >> 9) - iVar3)) + param_2[1];
|
|
if ((param_3[1] < iVar5) && (0x3200 < iVar5)) {
|
|
iVar5 = 0x3200;
|
|
}
|
|
param_3[1] = iVar5;
|
|
param_3[2] = ((param_3[2] - iVar6) - (((iVar8 * sVar2) / 6 + iVar4 >> 9) - iVar4)) +
|
|
param_2[2];
|
|
return 0;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
// VehPhysCrash_AI
|
|
void FUN_8005d0d0(int param_1,int *param_2)
|
|
|
|
{
|
|
int iVar1;
|
|
int iVar2;
|
|
|
|
DAT_8008d9ec = (ushort)*(byte *)(*(int *)(param_1 + 0x5a4) + 6) << 4;
|
|
DAT_8008d9ee = (ushort)*(byte *)(*(int *)(param_1 + 0x5a4) + 7) << 4;
|
|
DAT_8008d9f0 = (ushort)*(byte *)(*(int *)(param_1 + 0x5a4) + 8) << 4;
|
|
|
|
// convert 3 rotation shorts into rotation matrix
|
|
FUN_8006c2a4(&DAT_8009ae38,&DAT_8008d9ec);
|
|
|
|
DAT_8009ae28 = (int)((uint)DAT_8009ae3c << 0x10) >> 0x14;
|
|
DAT_8009ae2c = (int)((uint)DAT_8009ae42 << 0x10) >> 0x14;
|
|
DAT_8009ae30 = (int)((uint)DAT_8009ae48 << 0x10) >> 0x14;
|
|
iVar1 = DAT_8009ae28 * *param_2 + DAT_8009ae2c * param_2[1] + DAT_8009ae30 * param_2[2] >> 8;
|
|
*(int *)(param_1 + 0x5d4) = iVar1;
|
|
*(int *)(param_1 + 0x5d8) = *param_2 - (DAT_8009ae28 * iVar1 >> 8);
|
|
iVar1 = DAT_8009ae30 * iVar1;
|
|
iVar2 = param_2[2];
|
|
*(uint *)(param_1 + 0x5b0) = *(uint *)(param_1 + 0x5b0) | 8;
|
|
*(int *)(param_1 + 0x5e0) = iVar2 - (iVar1 >> 8);
|
|
return;
|
|
}
|
|
|
|
// VehPhysCrash_Attack
|
|
//param_1 = driver pointer
|
|
//param_2 = driver pointer
|
|
int FUN_8005d218(int param_1,int param_2,int param_3,int param_4)
|
|
{
|
|
int iVar1;
|
|
|
|
//if driver (1) is not using mask weapon
|
|
if ((*(uint *)(param_1 + 0x2c8) & 0x800000) == 0)
|
|
{
|
|
//if driver (2) is using mask weapon
|
|
if ((*(uint *)(param_2 + 0x2c8) & 0x800000) != 0)
|
|
{
|
|
// param_1 was hit with a mask weapon
|
|
*(undefined *)(param_1 + 0x4ff) = 2;
|
|
*(undefined *)(param_1 + 0x504) = 6;
|
|
*(int *)(param_1 + 0x500) = param_2;
|
|
|
|
if (((param_3 != 0) && (*(char *)(param_1 + 0x376) != '\x06')) &&
|
|
(*(int *)(param_1 + 0x24) == 0))
|
|
{
|
|
// OtherFX_DriverCrashing
|
|
FUN_8002e760(
|
|
|
|
// if driver is supposed to echo
|
|
(uint)*(ushort *)(param_1 + 0x2ca) & 1,
|
|
|
|
0xff
|
|
);
|
|
|
|
// Make driver talk
|
|
FUN_8002cbe8(1,(int)(short)(&DAT_80086e84)[*(byte *)(param_1 + 0x4a)],0x10);
|
|
}
|
|
}
|
|
|
|
// if one driver has a bubble, and the other does not
|
|
if ((*(int *)(param_2 + 0x14) != 0) && (*(int *)(param_1 + 0x14) == 0))
|
|
{
|
|
// driver -> bubbleInst -> thread -> object
|
|
iVar1 = *(int *)(*(int *)(*(int *)(param_2 + 0x14) + 0x6c) + 0x30);
|
|
|
|
*(ushort *)(iVar1 + 6) = *(ushort *)(iVar1 + 6) | 8;
|
|
|
|
// clear bubbleInst pointer
|
|
*(undefined4 *)(param_2 + 0x14) = 0;
|
|
|
|
*(undefined *)(param_1 + 0x4ff) = 2;
|
|
*(undefined *)(param_1 + 0x504) = 0;
|
|
*(int *)(param_1 + 0x500) = param_2;
|
|
|
|
if (
|
|
(param_3 != 0) &&
|
|
|
|
(
|
|
(
|
|
// if driver is not blasted
|
|
*(char *)(param_1 + 0x376) != '\x06' &&
|
|
|
|
// if driver is not invincible
|
|
(*(int *)(param_1 + 0x24) == 0)
|
|
)
|
|
)
|
|
)
|
|
{
|
|
// OtherFX_DriverCrashing
|
|
FUN_8002e760(
|
|
|
|
// if driver is supposed to echo
|
|
(uint)*(ushort *)(param_1 + 0x2ca) & 1,
|
|
|
|
0xff
|
|
);
|
|
|
|
if (param_4 != 0)
|
|
{
|
|
// OtherFX_Play
|
|
FUN_80028468(0x4f,1);
|
|
}
|
|
|
|
// Make driver talk
|
|
FUN_8002cbe8(1,(int)(short)(&DAT_80086e84)[*(byte *)(param_1 + 0x4a)],0x10);
|
|
}
|
|
}
|
|
|
|
// if one driver squished the other with turbo
|
|
if (
|
|
(
|
|
(
|
|
// force that the drivers collided is high
|
|
(0xa00 < DAT_8008d9f4) &&
|
|
|
|
// attacking driver has reserves
|
|
(*(short *)(param_2 + 0x3e2) != 0)
|
|
) &&
|
|
|
|
// attacking driver is using turbo weapon
|
|
((*(uint *)(param_2 + 0x2c8) & 0x200) != 0)
|
|
) &&
|
|
|
|
// attacked driver has no reserves
|
|
(*(short *)(param_1 + 0x3e2) == 0)
|
|
)
|
|
{
|
|
// set forcedJump_trampoline on attacking driver
|
|
*(undefined *)(param_2 + 0x366) = 2;
|
|
|
|
// attacked driver has been squished by attacking driver,
|
|
// this happens when one driver uses turbo weapon on another
|
|
*(undefined *)(param_1 + 0x4ff) = 3;
|
|
*(undefined *)(param_1 + 0x504) = 5;
|
|
*(int *)(param_1 + 0x500) = param_2;
|
|
}
|
|
}
|
|
return param_3;
|
|
}
|
|
|
|
// VehPhysCrash_AnyTwoCars
|
|
// pass the thread, collision data, and driver->88 velocityXYZ[] (x, y, z)
|
|
// calls Crash_AI and Crash_HumanToHuman
|
|
void FUN_8005d404(int param_1,int param_2,int *param_3)
|
|
|
|
{
|
|
undefined2 uVar1;
|
|
int iVar2;
|
|
int iVar3;
|
|
uint uVar4;
|
|
int iVar5;
|
|
int iVar6;
|
|
int iVar7;
|
|
int iVar8;
|
|
undefined4 uVar9;
|
|
uint uVar10;
|
|
int local_48;
|
|
int local_44;
|
|
int local_40;
|
|
int local_38;
|
|
int local_34;
|
|
int local_30;
|
|
|
|
// fast sqrt
|
|
iVar2 = FUN_8003d214(*(undefined4 *)(param_2 + 0xc),0);
|
|
|
|
uVar1 = 0x1000;
|
|
if (iVar2 == 0) {
|
|
*(undefined2 *)(param_2 + 0x18) = 0;
|
|
*(undefined2 *)(param_2 + 0x1a) = 0;
|
|
}
|
|
else
|
|
{
|
|
// distX
|
|
iVar8 = (int)*(short *)(param_2 + 0x10) << 0xc;
|
|
|
|
// safety check
|
|
if (iVar2 == 0) { trap(0x1c00); }
|
|
if ((iVar2 == -1) && (iVar8 == -0x80000000)) { trap(0x1800); }
|
|
|
|
// distY
|
|
iVar5 = (int)*(short *)(param_2 + 0x12) << 0xc;
|
|
|
|
// safety check
|
|
if (iVar2 == 0) { trap(0x1c00); }
|
|
if ((iVar2 == -1) && (iVar5 == -0x80000000)) { trap(0x1800); }
|
|
|
|
// distZ
|
|
iVar3 = (int)*(short *)(param_2 + 0x14) << 0xc;
|
|
|
|
// safety check
|
|
if (iVar2 == 0) { trap(0x1c00); }
|
|
if ((iVar2 == -1) && (iVar3 == -0x80000000)) { trap(0x1800); }
|
|
|
|
// hit direction vector,
|
|
// divide each direction by distance
|
|
uVar1 = (undefined2)(iVar3 / iVar2);
|
|
*(undefined2 *)(param_2 + 0x18) = (short)(iVar8 / iVar2);
|
|
*(undefined2 *)(param_2 + 0x1a) = (short)(iVar5 / iVar2);
|
|
}
|
|
|
|
// hit direction vector
|
|
*(undefined2 *)(param_2 + 0x1c) = uVar1;
|
|
|
|
// two driver objects
|
|
iVar8 = *(int *)(*(int *)(param_2 + 8) + 0x30);
|
|
iVar5 = *(int *)(param_1 + 0x30);
|
|
|
|
// hit strength
|
|
iVar2 =
|
|
(
|
|
// driver1 radius
|
|
(int)*(short *)(param_1 + 0x42) +
|
|
|
|
// driver2 radius
|
|
(int)*(short *)(*(int *)(*(int *)(iVar8 + 0x1c) + 0x6c) + 0x42)
|
|
)
|
|
|
|
// minus distance between them
|
|
- iVar2;
|
|
|
|
// if hitStrength < 0, drivers dont collide,
|
|
// if hitStrength == 0, drivers touch, but with no force
|
|
// if hitStrength > 0, drivers touch with force
|
|
|
|
// if drivers hit each other
|
|
if (0 < iVar2)
|
|
{
|
|
DAT_8008d9f4 = 0;
|
|
|
|
// If this is human and not AI
|
|
if ((*(uint *)(iVar5 + 0x2c8) & 0x100000) == 0) {
|
|
iVar3 = param_2 + 0x18;
|
|
|
|
// If this (other driver) is human and not AI
|
|
if ((*(uint *)(iVar8 + 0x2c8) & 0x100000) == 0) {
|
|
iVar7 = (int)*(short *)(iVar5 + 0x47c) + (int)*(short *)(iVar8 + 0x47c);
|
|
iVar6 = *param_3 * (int)*(short *)(iVar5 + 0x47c) +
|
|
*(int *)(iVar8 + 0x88) * (int)*(short *)(iVar8 + 0x47c);
|
|
local_38 = iVar6 / iVar7;
|
|
if (iVar7 == 0) {
|
|
trap(0x1c00);
|
|
}
|
|
if ((iVar7 == -1) && (iVar6 == -0x80000000)) {
|
|
trap(0x1800);
|
|
}
|
|
iVar7 = (int)*(short *)(iVar5 + 0x47c) + (int)*(short *)(iVar8 + 0x47c);
|
|
iVar6 = param_3[1] * (int)*(short *)(iVar5 + 0x47c) +
|
|
*(int *)(iVar8 + 0x8c) * (int)*(short *)(iVar8 + 0x47c);
|
|
local_34 = iVar6 / iVar7;
|
|
if (iVar7 == 0) {
|
|
trap(0x1c00);
|
|
}
|
|
if ((iVar7 == -1) && (iVar6 == -0x80000000)) {
|
|
trap(0x1800);
|
|
}
|
|
iVar7 = (int)*(short *)(iVar5 + 0x47c) + (int)*(short *)(iVar8 + 0x47c);
|
|
iVar6 = param_3[2] * (int)*(short *)(iVar5 + 0x47c) +
|
|
*(int *)(iVar8 + 0x90) * (int)*(short *)(iVar8 + 0x47c);
|
|
local_30 = iVar6 / iVar7;
|
|
if (iVar7 == 0) {
|
|
trap(0x1c00);
|
|
}
|
|
if ((iVar7 == -1) && (iVar6 == -0x80000000)) {
|
|
trap(0x1800);
|
|
}
|
|
|
|
// VehPhysCrash_BounceSelf
|
|
iVar6 = FUN_8005cf64(iVar3,&local_38,iVar8 + 0x88,1);
|
|
|
|
if (iVar6 < 0) {
|
|
DAT_8008d9f4 = 0;
|
|
}
|
|
|
|
// VehPhysCrash_BounceSelf
|
|
iVar3 = FUN_8005cf64(iVar3,&local_38,param_3,0);
|
|
|
|
if (0 < iVar3) {
|
|
DAT_8008d9f4 = 0;
|
|
}
|
|
*param_3 = *param_3 + (*(short *)(param_2 + 0x18) * iVar2 >> 8);
|
|
param_3[1] = param_3[1] + (*(short *)(param_2 + 0x1a) * iVar2 >> 8);
|
|
param_3[2] = param_3[2] + (*(short *)(param_2 + 0x1c) * iVar2 >> 8);
|
|
|
|
// deduct speed by (dirVec * hitStrength)
|
|
*(int *)(iVar8 + 0x88) = *(int *)(iVar8 + 0x88) - (*(short *)(param_2 + 0x18) * iVar2 >> 8);
|
|
*(int *)(iVar8 + 0x8c) = *(int *)(iVar8 + 0x8c) - (*(short *)(param_2 + 0x1a) * iVar2 >> 8);
|
|
*(int *)(iVar8 + 0x90) = *(int *)(iVar8 + 0x90) - (*(short *)(param_2 + 0x1c) * iVar2 >> 8);
|
|
}
|
|
|
|
// If this (other driver) is an AI
|
|
else {
|
|
local_48 = *(int *)(iVar8 + 0x3a0) + *(int *)(iVar8 + 0x5d8);
|
|
local_44 = *(int *)(iVar8 + 0x3a4) + *(int *)(iVar8 + 0x5dc);
|
|
local_40 = *(int *)(iVar8 + 0x3a8) + *(int *)(iVar8 + 0x5e0);
|
|
iVar7 = (int)*(short *)(iVar5 + 0x47c) + (int)*(short *)(iVar8 + 0x47c);
|
|
iVar6 = *param_3 * (int)*(short *)(iVar5 + 0x47c) +
|
|
local_48 * (int)*(short *)(iVar8 + 0x47c);
|
|
local_38 = iVar6 / iVar7;
|
|
if (iVar7 == 0) {
|
|
trap(0x1c00);
|
|
}
|
|
if ((iVar7 == -1) && (iVar6 == -0x80000000)) {
|
|
trap(0x1800);
|
|
}
|
|
iVar7 = (int)*(short *)(iVar5 + 0x47c) + (int)*(short *)(iVar8 + 0x47c);
|
|
iVar6 = param_3[1] * (int)*(short *)(iVar5 + 0x47c) +
|
|
local_44 * (int)*(short *)(iVar8 + 0x47c);
|
|
local_34 = iVar6 / iVar7;
|
|
if (iVar7 == 0) {
|
|
trap(0x1c00);
|
|
}
|
|
if ((iVar7 == -1) && (iVar6 == -0x80000000)) {
|
|
trap(0x1800);
|
|
}
|
|
iVar7 = (int)*(short *)(iVar5 + 0x47c) + (int)*(short *)(iVar8 + 0x47c);
|
|
iVar6 = param_3[2] * (int)*(short *)(iVar5 + 0x47c) +
|
|
local_40 * (int)*(short *)(iVar8 + 0x47c);
|
|
local_30 = iVar6 / iVar7;
|
|
if (iVar7 == 0) {
|
|
trap(0x1c00);
|
|
}
|
|
if ((iVar7 == -1) && (iVar6 == -0x80000000)) {
|
|
trap(0x1800);
|
|
}
|
|
|
|
// VehPhysCrash_BounceSelf
|
|
iVar6 = FUN_8005cf64(iVar3,&local_38,&local_48,1);
|
|
|
|
if (iVar6 < 0) {
|
|
DAT_8008d9f4 = 0;
|
|
}
|
|
|
|
// VehPhysCrash_BounceSelf
|
|
iVar3 = FUN_8005cf64(iVar3,&local_38,param_3,0);
|
|
|
|
if (0 < iVar3) {
|
|
DAT_8008d9f4 = 0;
|
|
}
|
|
|
|
*param_3 = *param_3 + (*(short *)(param_2 + 0x18) * iVar2 >> 8);
|
|
param_3[1] = param_3[1] + (*(short *)(param_2 + 0x1a) * iVar2 >> 8);
|
|
param_3[2] = param_3[2] + (*(short *)(param_2 + 0x1c) * iVar2 >> 8);
|
|
|
|
local_48 = local_48 - (*(short *)(param_2 + 0x18) * iVar2 >> 8);
|
|
local_44 = local_44 - (*(short *)(param_2 + 0x1a) * iVar2 >> 8);
|
|
local_40 = local_40 - (*(short *)(param_2 + 0x1c) * iVar2 >> 8);
|
|
|
|
// VehPhysCrash_AI
|
|
FUN_8005d0d0(iVar8,&local_48);
|
|
}
|
|
uVar10 = (uint)((uint)(*(int *)(PTR_DAT_8008d2ac + 0x1cf8) - DAT_8008d838) < 3) ^ 1;
|
|
if (0x200 < DAT_8008d9f4)
|
|
{
|
|
// thread -> modelIndex == "player" of any kind
|
|
if ((((*(short *)(param_1 + 0x44) == 0x18) ||
|
|
|
|
// modelIndex == "player" of any kind
|
|
(*(short *)(*(int *)(param_2 + 8) + 0x44) == 0x18)) &&
|
|
|
|
// Map value from [oldMin, oldMax] to [newMin, newMax]
|
|
// inverting newMin and newMax will give an inverse range mapping
|
|
(uVar4 = FUN_80058f9c(DAT_8008d9f4,0,0x1900,0x3f,0xff), uVar10 != 0)) &&
|
|
(
|
|
// if both drivers are not blasted and not invincible
|
|
((*(char *)(iVar5 + 0x376) != '\x06' && (*(int *)(iVar5 + 0x24) == 0)) &&
|
|
((*(char *)(iVar8 + 0x376) != '\x06' && (*(int *)(iVar8 + 0x24) == 0))))
|
|
)
|
|
)
|
|
{
|
|
// OtherFX_DriverCrashing
|
|
FUN_8002e760(
|
|
|
|
// if driver is supposed to echo
|
|
(uint)*(ushort *)(iVar5 + 0x2ca) & 1,
|
|
|
|
uVar4
|
|
);
|
|
|
|
DAT_8008d838 = *(int *)(PTR_DAT_8008d2ac + 0x1cf8);
|
|
if (0xdc < uVar4)
|
|
{
|
|
// Make driver talk
|
|
FUN_8002cbe8(5,(int)(short)(&DAT_80086e84)[*(byte *)(iVar5 + 0x4a)],0x10);
|
|
}
|
|
}
|
|
|
|
// GAMEPAD_ShockFreq and GAMEPAD_ShockForce1
|
|
FUN_80026440(iVar8,8,0);
|
|
FUN_800264c0(iVar8,8,0x7f);
|
|
|
|
if (*(char *)(iVar8 + 0x4b) < '\x01') {
|
|
uVar9 = 0x19;
|
|
}
|
|
else {
|
|
uVar9 = 0x29;
|
|
}
|
|
|
|
// GAMEPAD_JogCon1
|
|
FUN_800263a0(iVar8,uVar9,0x60);
|
|
|
|
// GAMEPAD_ShockFreq and GAMEPAD_ShockForce1
|
|
FUN_80026440(iVar5,8,0);
|
|
FUN_800264c0(iVar5,8,0x7f);
|
|
|
|
if (*(char *)(iVar5 + 0x4b) < '\x01') {
|
|
uVar9 = 0x19;
|
|
}
|
|
else {
|
|
uVar9 = 0x29;
|
|
}
|
|
|
|
// GAMEPAD_JogCon1
|
|
FUN_800263a0(iVar5,uVar9,0x60);
|
|
|
|
// flag used in 80062e04
|
|
// Let both human drivers know, they are in a human-human collision
|
|
*(uint *)(iVar5 + 0x2c8) = *(uint *)(iVar5 + 0x2c8) | 0x10000000;
|
|
*(uint *)(iVar8 + 0x2c8) = *(uint *)(iVar8 + 0x2c8) | 0x10000000;
|
|
}
|
|
|
|
// VehPhysCrash_Attack
|
|
uVar9 = FUN_8005d218(iVar5,iVar8,uVar10,0);
|
|
FUN_8005d218(iVar8,iVar5,uVar9,1);
|
|
}
|
|
|
|
// If this is an AI
|
|
else
|
|
{
|
|
// If this (other driver) is human and not AI
|
|
if ((*(uint *)(iVar8 + 0x2c8) & 0x100000) == 0)
|
|
{
|
|
// VehPhysForce_ConvertSpeedToVec
|
|
FUN_8005e104(iVar8,&local_48);
|
|
|
|
iVar6 = (int)*(short *)(iVar5 + 0x47c) + (int)*(short *)(iVar8 + 0x47c);
|
|
iVar3 = *param_3 * (int)*(short *)(iVar5 + 0x47c) +
|
|
local_48 * (int)*(short *)(iVar8 + 0x47c);
|
|
local_38 = iVar3 / iVar6;
|
|
if (iVar6 == 0) {
|
|
trap(0x1c00);
|
|
}
|
|
if ((iVar6 == -1) && (iVar3 == -0x80000000)) {
|
|
trap(0x1800);
|
|
}
|
|
iVar6 = (int)*(short *)(iVar5 + 0x47c) + (int)*(short *)(iVar8 + 0x47c);
|
|
iVar3 = param_3[1] * (int)*(short *)(iVar5 + 0x47c) +
|
|
local_44 * (int)*(short *)(iVar8 + 0x47c);
|
|
local_34 = iVar3 / iVar6;
|
|
if (iVar6 == 0) {
|
|
trap(0x1c00);
|
|
}
|
|
if ((iVar6 == -1) && (iVar3 == -0x80000000)) {
|
|
trap(0x1800);
|
|
}
|
|
iVar6 = (int)*(short *)(iVar5 + 0x47c) + (int)*(short *)(iVar8 + 0x47c);
|
|
iVar3 = param_3[2] * (int)*(short *)(iVar5 + 0x47c) +
|
|
local_40 * (int)*(short *)(iVar8 + 0x47c);
|
|
local_30 = iVar3 / iVar6;
|
|
if (iVar6 == 0) {
|
|
trap(0x1c00);
|
|
}
|
|
if ((iVar6 == -1) && (iVar3 == -0x80000000)) {
|
|
trap(0x1800);
|
|
}
|
|
|
|
// VehPhysCrash_BounceSelf
|
|
iVar3 = FUN_8005cf64(param_2 + 0x18,&local_38,&local_48,1);
|
|
|
|
if (iVar3 < 0) {
|
|
DAT_8008d9f4 = 0;
|
|
}
|
|
|
|
// VehPhysCrash_BounceSelf
|
|
iVar3 = FUN_8005cf64(param_2 + 0x18,&local_38,param_3,0);
|
|
|
|
if (0 < iVar3) {
|
|
DAT_8008d9f4 = 0;
|
|
}
|
|
|
|
*param_3 = *param_3 + (*(short *)(param_2 + 0x18) * iVar2 >> 8);
|
|
param_3[1] = param_3[1] + (*(short *)(param_2 + 0x1a) * iVar2 >> 8);
|
|
param_3[2] = param_3[2] + (*(short *)(param_2 + 0x1c) * iVar2 >> 8);
|
|
|
|
local_48 = local_48 - (*(short *)(param_2 + 0x18) * iVar2 >> 8);
|
|
local_44 = local_44 - (*(short *)(param_2 + 0x1a) * iVar2 >> 8);
|
|
local_40 = local_40 - (*(short *)(param_2 + 0x1c) * iVar2 >> 8);
|
|
|
|
// VehPhysCrash_AI
|
|
FUN_8005d0d0(iVar5,param_3);
|
|
|
|
// VehPhysCrash_ConvertVecToSpeed
|
|
FUN_8005cd1c(iVar8,&local_48,0);
|
|
}
|
|
|
|
// If this (other driver) is an AI
|
|
else {
|
|
local_48 = *(int *)(iVar8 + 0x3a0) + *(int *)(iVar8 + 0x5d8);
|
|
local_44 = *(int *)(iVar8 + 0x3a4) + *(int *)(iVar8 + 0x5dc);
|
|
local_40 = *(int *)(iVar8 + 0x3a8) + *(int *)(iVar8 + 0x5e0);
|
|
iVar6 = (int)*(short *)(iVar5 + 0x47c) + (int)*(short *)(iVar8 + 0x47c);
|
|
iVar3 = *param_3 * (int)*(short *)(iVar5 + 0x47c) +
|
|
local_48 * (int)*(short *)(iVar8 + 0x47c);
|
|
local_38 = iVar3 / iVar6;
|
|
if (iVar6 == 0) {
|
|
trap(0x1c00);
|
|
}
|
|
if ((iVar6 == -1) && (iVar3 == -0x80000000)) {
|
|
trap(0x1800);
|
|
}
|
|
iVar6 = (int)*(short *)(iVar5 + 0x47c) + (int)*(short *)(iVar8 + 0x47c);
|
|
iVar3 = param_3[1] * (int)*(short *)(iVar5 + 0x47c) +
|
|
local_44 * (int)*(short *)(iVar8 + 0x47c);
|
|
local_34 = iVar3 / iVar6;
|
|
if (iVar6 == 0) {
|
|
trap(0x1c00);
|
|
}
|
|
if ((iVar6 == -1) && (iVar3 == -0x80000000)) {
|
|
trap(0x1800);
|
|
}
|
|
iVar6 = (int)*(short *)(iVar5 + 0x47c) + (int)*(short *)(iVar8 + 0x47c);
|
|
iVar3 = param_3[2] * (int)*(short *)(iVar5 + 0x47c) +
|
|
local_40 * (int)*(short *)(iVar8 + 0x47c);
|
|
local_30 = iVar3 / iVar6;
|
|
if (iVar6 == 0) {
|
|
trap(0x1c00);
|
|
}
|
|
if ((iVar6 == -1) && (iVar3 == -0x80000000)) {
|
|
trap(0x1800);
|
|
}
|
|
|
|
// VehPhysCrash_BounceSelf
|
|
iVar3 = FUN_8005cf64(param_2 + 0x18,&local_38,&local_48,1);
|
|
|
|
if (iVar3 < 0) {
|
|
DAT_8008d9f4 = 0;
|
|
}
|
|
|
|
// VehPhysCrash_BounceSelf
|
|
iVar3 = FUN_8005cf64(param_2 + 0x18,&local_38,param_3,0);
|
|
|
|
if (0 < iVar3) {
|
|
DAT_8008d9f4 = 0;
|
|
}
|
|
|
|
*param_3 = *param_3 + (*(short *)(param_2 + 0x18) * iVar2 >> 8);
|
|
param_3[1] = param_3[1] + (*(short *)(param_2 + 0x1a) * iVar2 >> 8);
|
|
param_3[2] = param_3[2] + (*(short *)(param_2 + 0x1c) * iVar2 >> 8);
|
|
|
|
local_48 = local_48 - (*(short *)(param_2 + 0x18) * iVar2 >> 8);
|
|
local_44 = local_44 - (*(short *)(param_2 + 0x1a) * iVar2 >> 8);
|
|
local_40 = local_40 - (*(short *)(param_2 + 0x1c) * iVar2 >> 8);
|
|
|
|
// VehPhysCrash_AI (twice)
|
|
FUN_8005d0d0(iVar8,&local_48);
|
|
FUN_8005d0d0(iVar5,param_3);
|
|
|
|
// pass pointer to two drivers,
|
|
// this is AI-on-AI collision
|
|
FUN_80016ec8(iVar5,iVar8);
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
// VehPhysForce_ConvertSpeedToVec
|
|
// param_1 = &driver
|
|
// param_2 = &driver.velocityXYZ
|
|
void FUN_8005e104(int param_1,int *param_2)
|
|
|
|
{
|
|
short sVar1;
|
|
int iVar2;
|
|
int iVar3;
|
|
int iVar4;
|
|
int iVar5;
|
|
uint uVar6;
|
|
|
|
// angle = axisRotationY
|
|
uVar6 = SEXT24(*(short *)(param_1 + 0x394));
|
|
|
|
// approximate trigonometry
|
|
// sVar1 = sin(angle)
|
|
sVar1 = (short)*(int *)(&DAT_800845a0 + (uVar6 & 0x3ff) * 4);
|
|
// iVar5 = cos(angle)
|
|
iVar5 = *(int *)(&DAT_800845a0 + (uVar6 & 0x3ff) * 4) >> 0x10;
|
|
|
|
if ((uVar6 & 0x400) == 0) {
|
|
iVar2 = (int)sVar1;
|
|
if ((uVar6 & 0x800) != 0) {
|
|
iVar3 = -iVar5;
|
|
goto LAB_8005e15c;
|
|
}
|
|
}
|
|
else {
|
|
iVar3 = (int)sVar1;
|
|
iVar2 = iVar5;
|
|
if ((uVar6 & 0x800) == 0) {
|
|
iVar5 = -iVar3;
|
|
}
|
|
else {
|
|
LAB_8005e15c:
|
|
iVar2 = -iVar2;
|
|
iVar5 = iVar3;
|
|
}
|
|
}
|
|
|
|
// velocityXYZ[y] = (driver.speed * ???) >> 0xC
|
|
param_2[1] = *(short *)(param_1 + 0x38c) * iVar2 >> 0xc;
|
|
|
|
// angle = axisRotationX
|
|
uVar6 = SEXT24(*(short *)(param_1 + 0x396));
|
|
iVar2 = *(short *)(param_1 + 0x38c) * iVar5 >> 0xc;
|
|
|
|
// approximate trigonometry
|
|
iVar5 = *(int *)(&DAT_800845a0 + (uVar6 & 0x3ff) * 4) >> 0x10;
|
|
sVar1 = (short)*(int *)(&DAT_800845a0 + (uVar6 & 0x3ff) * 4);
|
|
|
|
if ((uVar6 & 0x400) == 0) {
|
|
iVar3 = (int)sVar1;
|
|
if ((uVar6 & 0x800) == 0) goto LAB_8005e1e8;
|
|
iVar4 = -iVar5;
|
|
}
|
|
else {
|
|
iVar4 = (int)sVar1;
|
|
iVar3 = iVar5;
|
|
if ((uVar6 & 0x800) == 0) {
|
|
iVar5 = -iVar4;
|
|
goto LAB_8005e1e8;
|
|
}
|
|
}
|
|
iVar3 = -iVar3;
|
|
iVar5 = iVar4;
|
|
|
|
LAB_8005e1e8:
|
|
|
|
// velocityXYZ[x] and velocityXYZ[z]
|
|
*param_2 = iVar2 * iVar3 >> 0xc;
|
|
param_2[2] = iVar2 * iVar5 >> 0xc;
|
|
return;
|
|
}
|
|
|
|
|
|
// VehPhysForce_OnGravity (for humans only)
|
|
// param1 - driver, param2 - velocityXYZ
|
|
void FUN_8005e214(int param_1,VECTOR *param_2)
|
|
|
|
{
|
|
char cVar1;
|
|
undefined2 uVar2;
|
|
int iVar3;
|
|
uint uVar4;
|
|
int iVar5;
|
|
int iVar6;
|
|
uint uVar7;
|
|
uint uVar8;
|
|
uint uVar9;
|
|
uint uVar10;
|
|
uint uVar11;
|
|
uint uVar12;
|
|
int iVar13;
|
|
uint unaff_s3;
|
|
uint unaff_s5;
|
|
undefined *puVar14;
|
|
int unaff_s8;
|
|
int iVar15;
|
|
int iVar16;
|
|
undefined auStack72 [16];
|
|
|
|
puVar14 = auStack72;
|
|
|
|
// driver -> 0x310 matrix
|
|
uVar8 = *(uint *)(param_1 + 0x310);
|
|
uVar7 = *(uint *)(param_1 + 0x314);
|
|
uVar10 = *(uint *)(param_1 + 0x318);
|
|
uVar9 = *(uint *)(param_1 + 0x31c);
|
|
|
|
// load matrix into GTE
|
|
gte_ldR11R12(uVar8);
|
|
gte_ldR13R21(uVar7);
|
|
gte_ldR22R23(uVar10);
|
|
gte_ldR31R32(uVar9);
|
|
gte_ldR33((int)*(short *)(param_1 + 800)); // 0x320
|
|
|
|
// transpose matrix
|
|
gte_ldL11L12(uVar8 & 0xffff | uVar7 & 0xffff0000);
|
|
uVar8 = uVar8 & 0xffff0000;
|
|
gte_ldL13L21(uVar9 & 0xffff | uVar8);
|
|
gte_ldL22L23(uVar10 & 0xffff | uVar9 & 0xffff0000);
|
|
uVar7 = uVar7 & 0xffff | uVar10 & 0xffff0000;
|
|
gte_ldL31L32(uVar7);
|
|
gte_ldL33((int)*(short *)(param_1 + 800)); // 0x320
|
|
|
|
// load vector from param_2
|
|
gte_ldVXY0((uint)*(ushort *)¶m_2->vx | param_2->vy << 0x10);
|
|
gte_ldVZ0(param_2->vz);
|
|
gte_llv0();
|
|
|
|
// these registers hold movement vector,
|
|
// but why does that need driver matrix?
|
|
read_mt(unaff_s5,unaff_s8,unaff_s3);
|
|
|
|
// driver gravity constant
|
|
iVar3 = -(int)*(short *)(param_1 + 0x416);
|
|
|
|
// elapsed milliseconds per frame, ~32
|
|
iVar5 = *(int *)(PTR_DAT_8008d2ac + 0x1d04);
|
|
iVar6 = iVar5;
|
|
|
|
// If the driver's under-quadblock has moon gravity
|
|
if ((*(ushort *)(*(int *)(param_1 + 0x350) + 0x12) & 2) != 0)
|
|
{
|
|
// 41% gravity (41 / 100)
|
|
iVar6 = *(short *)(param_1 + 0x416) * -0x29;
|
|
iVar3 = iVar6 >> 0x1f;
|
|
iVar6 = iVar6 / 100 + iVar3;
|
|
iVar3 = iVar6 - iVar3;
|
|
}
|
|
|
|
// vector = {0, gravity*elapsedMS, 0}
|
|
// matrix = driver orientation (driver->0x310)
|
|
gte_ldVXY0((iVar3 * iVar5 >> 5) << 0x10);
|
|
gte_ldVZ0(0);
|
|
gte_llv0();
|
|
|
|
// gravity is a vector, not straight down,
|
|
// this causes road grip, and halfpipe physics
|
|
read_mt(uVar7,uVar8,iVar6);
|
|
|
|
if (((iVar6 < 0) && (0 < *(short *)(param_1 + 0x3b2))) ||
|
|
((0 < iVar6 && (*(short *)(param_1 + 0x3b2) < 0)))) {
|
|
iVar6 = 0;
|
|
}
|
|
|
|
// driver flags
|
|
uVar10 = *(uint *)(param_1 + 0x2c8);
|
|
|
|
iVar3 = (int)*(short *)(param_1 + 0x38e); // speed approximate magnitude
|
|
uVar9 = (uint)*(short *)(param_1 + 0x39c); // baseSpeed
|
|
|
|
if ((((uVar10 & 8) != 0) || ((0 < (int)uVar9 && (iVar3 < 0)))) ||
|
|
(((int)uVar9 < 0 && (0 < iVar3)))) {
|
|
uVar7 = 0;
|
|
iVar6 = 0;
|
|
}
|
|
|
|
// movementY + gravityY
|
|
iVar15 = unaff_s8 + uVar8;
|
|
|
|
uVar11 = (int)*(short *)(param_1 + 0x39e) + (int)*(short *)(param_1 + 0x47e);
|
|
uVar8 = unaff_s3 + iVar6;
|
|
if (((int)uVar11 < (int)(unaff_s3 + iVar6)) && (uVar8 = unaff_s3, (int)unaff_s3 < (int)uVar11)) {
|
|
uVar8 = uVar11;
|
|
}
|
|
uVar11 = (int)*(short *)(param_1 + 0x39e) - ((int)*(short *)(param_1 + 0x47e) >> 1);
|
|
if (((int)uVar8 < (int)uVar11) && (uVar8 = unaff_s3, (int)uVar11 < (int)unaff_s3)) {
|
|
uVar8 = uVar11;
|
|
}
|
|
|
|
uVar12 = (uint)*(short *)(param_1 + 0x480);
|
|
|
|
// terrainMeta1
|
|
uVar4 = *(uint *)(*(int *)(param_1 + 0x358) + 4);
|
|
|
|
uVar11 = unaff_s5 + uVar7;
|
|
if (((int)(unaff_s5 + uVar7) <= (int)uVar12) ||
|
|
(uVar11 = uVar12, uVar7 = unaff_s5, (int)unaff_s5 < (int)uVar12)) {
|
|
uVar7 = uVar11;
|
|
}
|
|
uVar12 = -uVar12;
|
|
if (((int)uVar7 < (int)uVar12) && (uVar7 = unaff_s5, (int)uVar12 < (int)unaff_s5)) {
|
|
uVar7 = uVar12;
|
|
}
|
|
|
|
// const_TerminalVelocity
|
|
iVar6 = (int)*(short *)(param_1 + 0x442);
|
|
|
|
if (
|
|
(
|
|
// if falling
|
|
(iVar15 < 0) &&
|
|
|
|
// terrain = zero-gravity
|
|
// in oxide station
|
|
((uVar4 & 0x80) != 0)
|
|
|
|
) &&
|
|
|
|
(
|
|
// terminalVelocity
|
|
iVar6 = 0x100,
|
|
|
|
// if movementY is less
|
|
unaff_s8 < -0x100)
|
|
)
|
|
{
|
|
// dont let movementY go
|
|
// below terminalVelocity
|
|
unaff_s8 = -0x100;
|
|
}
|
|
|
|
if (
|
|
// if totalY is less than terminalVelocity
|
|
(iVar15 <= iVar6) ||
|
|
|
|
(
|
|
// copy of terminalVelocity
|
|
iVar15 = iVar6,
|
|
|
|
// movementY
|
|
iVar16 = unaff_s8,
|
|
|
|
// movementY is less than terminalVelocity
|
|
unaff_s8 < iVar6
|
|
)
|
|
)
|
|
{
|
|
// movementY = terminalVelocity
|
|
iVar16 = iVar15;
|
|
}
|
|
|
|
// negate terminal velocity and check again,
|
|
// just in case gravity is upside down (scrapped feature)?
|
|
// that or just make sure you dont go upward too fast
|
|
iVar6 = -iVar6;
|
|
if ((iVar16 < iVar6) && (iVar16 = unaff_s8, iVar6 < unaff_s8))
|
|
{
|
|
// movementY = max upward terminalVelocity
|
|
iVar16 = iVar6;
|
|
}
|
|
|
|
// kart state
|
|
cVar1 = *(char *)(param_1 + 0x376);
|
|
|
|
// if mask grab
|
|
if (cVar1 == '\x05') {
|
|
uVar7 = 0;
|
|
uVar8 = 0;
|
|
}
|
|
|
|
// if not mask grab
|
|
else if (
|
|
(
|
|
((*(uint *)(param_1 + 0x2cc) & 1) != 0) ||
|
|
|
|
// blasted
|
|
(cVar1 == '\x06')
|
|
) ||
|
|
(
|
|
(
|
|
*(short *)(param_1 + 0x3c4) < *(short *)(param_1 + 0x38e) &&
|
|
|
|
// terrainMeta2
|
|
(*(int *)(*(int *)(param_1 + 0x35c) + 8) < 0x100)
|
|
)
|
|
)
|
|
)
|
|
{
|
|
// 2c8 & 8
|
|
// not in accel-prevention,
|
|
// not holding square, etc...
|
|
if ((uVar10 & 8) == 0)
|
|
{
|
|
// current baseSpeed is zero,
|
|
// which includes kart rolling on hill
|
|
// without gas pedal or reserves
|
|
if (uVar9 == 0)
|
|
{
|
|
// const_NoPedalFriction_Perpendicular
|
|
iVar15 = (int)*(short *)(param_1 + 0x41e);
|
|
|
|
// const_NoPedalFriction_Forward
|
|
iVar6 = (int)*(short *)(param_1 + 0x420);
|
|
|
|
// driverRankItemValue
|
|
if (*(short *)(param_1 + 0x50a) == 5)
|
|
{
|
|
// const_BrakeFriction
|
|
iVar15 = (int)*(short *)(param_1 + 0x422) << 4;
|
|
iVar6 = iVar15;
|
|
}
|
|
}
|
|
|
|
// baseSpeed > 0,
|
|
// driving in some way
|
|
else {
|
|
iVar6 = iVar3;
|
|
if (iVar3 < 0) {
|
|
iVar6 = -iVar3;
|
|
}
|
|
if (
|
|
(iVar6 < 0x301) ||
|
|
(
|
|
(
|
|
((int)uVar9 < 1 || (-1 < iVar3)) &&
|
|
((-1 < (int)uVar9 || (iVar3 < 1)))
|
|
)
|
|
)
|
|
)
|
|
{
|
|
// kartState drifting
|
|
if (cVar1 == '\x02')
|
|
{
|
|
// const_DriftCurve
|
|
iVar15 = (int)*(short *)(param_1 + 0x424);
|
|
|
|
// const_DriftFriction
|
|
iVar6 = (int)*(short *)(param_1 + 0x426);
|
|
}
|
|
|
|
// driving straight
|
|
else {
|
|
if (iVar3 < 0) {
|
|
iVar3 = -iVar3;
|
|
}
|
|
|
|
// const_PedalFriction_Perpendicular
|
|
iVar15 = (int)*(short *)(param_1 + 0x41a);
|
|
|
|
// const_PedalFriction_Forward
|
|
iVar6 = (int)*(short *)(param_1 + 0x41c);
|
|
|
|
if (0x300 < iVar3) {
|
|
uVar11 = uVar9;
|
|
if ((int)uVar9 < 0) {
|
|
uVar11 = -uVar9;
|
|
}
|
|
if (iVar3 < (int)uVar11 >> 1) {
|
|
uVar10 = uVar10 | 0x800;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (iVar3 < 0) {
|
|
iVar3 = -iVar3;
|
|
}
|
|
|
|
// const_PedalFriction_Perpendicular
|
|
iVar15 = (int)*(short *)(param_1 + 0x41a);
|
|
|
|
// const_BrakeFriction
|
|
iVar6 = (int)*(short *)(param_1 + 0x422);
|
|
|
|
if (0x300 < iVar3) {
|
|
uVar10 = uVar10 | 0x800;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// if in accel-prevention
|
|
else {
|
|
if (iVar3 < 0) {
|
|
iVar3 = -iVar3;
|
|
}
|
|
if (0x300 < iVar3) {
|
|
uVar10 = uVar10 | 0x800;
|
|
}
|
|
|
|
// const_BrakeFriction
|
|
iVar3 = (uint)*(ushort *)(param_1 + 0x422) << 0x10;
|
|
|
|
iVar15 = iVar3 >> 0x10;
|
|
|
|
// driverRankItemValue
|
|
if (*(short *)(param_1 + 0x50a) == 5) {
|
|
iVar15 = iVar15 << 4;
|
|
iVar6 = iVar15;
|
|
}
|
|
|
|
// blasted kartState
|
|
else if (cVar1 == '\x06') {
|
|
iVar15 = iVar15 * 3 >> 2;
|
|
iVar6 = iVar15;
|
|
}
|
|
|
|
else {
|
|
iVar6 = iVar15;
|
|
|
|
// If you're spinning: if you hit a glass
|
|
// or spun out from drifting
|
|
if (cVar1 == '\x03') {
|
|
iVar15 = iVar3 >> 0x11;
|
|
iVar6 = iVar15;
|
|
}
|
|
}
|
|
}
|
|
|
|
// terrainMeta1
|
|
iVar13 = *(int *)(*(int *)(param_1 + 0x358) + 0x20);
|
|
|
|
iVar3 = iVar15 * iVar5 >> 5;
|
|
iVar6 = iVar6 * iVar5 >> 5;
|
|
if (iVar13 != 0x100) {
|
|
iVar3 = iVar13 * iVar3 >> 8;
|
|
iVar6 = iVar13 * iVar6 >> 8;
|
|
}
|
|
|
|
iVar15 = (int)*(short *)(param_1 + 0x414);
|
|
|
|
if (iVar15 < 0) {
|
|
uVar11 = uVar7;
|
|
if (iVar15 == -0x140) {
|
|
if ((int)uVar7 < 0) {
|
|
uVar11 = -uVar7;
|
|
}
|
|
iVar3 = (int)uVar11 >> 1;
|
|
}
|
|
else {
|
|
iVar3 = iVar3 + (iVar3 * *(short *)(param_1 + 0x444) >> 8);
|
|
if (iVar3 < 0) {
|
|
iVar3 = 0;
|
|
}
|
|
if ((int)uVar7 < 0) {
|
|
uVar11 = -uVar7;
|
|
}
|
|
}
|
|
if (0 < (int)uVar11) {
|
|
uVar10 = uVar10 | 0x1800;
|
|
|
|
// GAMEPAD_ShockFreq and GAMEPAD_ShockForce1
|
|
FUN_800264c0(param_1,4,0x7f);
|
|
FUN_80026440(param_1,4,0);
|
|
}
|
|
iVar15 = iVar15 + iVar5;
|
|
if (0 < iVar15) {
|
|
iVar15 = 0;
|
|
}
|
|
*(short *)(param_1 + 0x414) = (short)iVar15;
|
|
}
|
|
else if (0 < iVar15) {
|
|
iVar15 = iVar15 - iVar5;
|
|
if (iVar15 < 0) {
|
|
iVar15 = 0;
|
|
}
|
|
iVar3 = iVar3 + (iVar3 * *(short *)(param_1 + 0x444) >> 8);
|
|
*(short *)(param_1 + 0x414) = (short)iVar15;
|
|
if (iVar3 < 0) {
|
|
iVar3 = 0;
|
|
}
|
|
}
|
|
if (((uVar10 & 0x800000) == 0) && (iVar5 = (int)uVar7 >> 3, (uVar4 & 0x80) != 0)) {
|
|
if (iVar5 < 0) {
|
|
iVar5 = -iVar5;
|
|
}
|
|
if (iVar3 < iVar5) {
|
|
iVar3 = iVar5;
|
|
}
|
|
if (((uVar8 == 0) || (uVar9 == 0)) || (-1 < (int)(uVar8 ^ uVar9))) {
|
|
if ((((int)uVar9 <= (int)uVar8) || (0 < (int)uVar8)) &&
|
|
(((int)uVar8 <= (int)uVar9 || ((int)uVar8 < 0)))) goto LAB_8005e8d8;
|
|
iVar5 = uVar8 - uVar9;
|
|
if (iVar5 < 0) {
|
|
iVar5 = -iVar5;
|
|
}
|
|
iVar5 = iVar5 >> 1;
|
|
}
|
|
else {
|
|
iVar5 = (int)uVar8 >> 1;
|
|
if (iVar5 < 0) {
|
|
iVar5 = -iVar5;
|
|
}
|
|
}
|
|
if (iVar6 < iVar5) {
|
|
iVar6 = iVar5;
|
|
}
|
|
}
|
|
LAB_8005e8d8:
|
|
if (((uVar4 & 0x100) == 0) || (iVar5 = iVar3 * 3 >> 2, iVar3 = iVar6, iVar5 < iVar6)) {
|
|
iVar5 = iVar3;
|
|
}
|
|
|
|
// Interpolate rotation by speed
|
|
uVar7 = FUN_80058f54(uVar7,iVar5,0);
|
|
uVar8 = FUN_80058f54(uVar8,iVar6,0);
|
|
}
|
|
|
|
// load new movement vector
|
|
gte_ldVXY0(uVar7 & 0xffff | iVar16 << 0x10);
|
|
gte_ldVZ0(uVar8);
|
|
gte_rtv0();
|
|
|
|
// save new movement vector
|
|
gte_stlvnl(param_2);
|
|
|
|
// set flag
|
|
*(uint *)(param_1 + 0x2c8) = uVar10;
|
|
|
|
// if driver is not in air
|
|
if ((uVar10 & 0x80000) == 0)
|
|
{
|
|
if (
|
|
// firstFrameSinceRevEngine
|
|
(*(char *)(param_1 + 0x449) != '\0') &&
|
|
|
|
(uVar8 != 0)
|
|
)
|
|
{
|
|
// move forward
|
|
uVar2 = 1;
|
|
|
|
// move backward
|
|
if ((int)uVar8 < 0) {
|
|
uVar2 = 0xffff;
|
|
}
|
|
|
|
// forwardDir (0x3e8)
|
|
*(undefined2 *)(param_1 + 1000) = uVar2;
|
|
|
|
// firstFrameSinceRevEngine
|
|
*(undefined *)(param_1 + 0x449) = 0;
|
|
|
|
goto LAB_8005e9d8;
|
|
}
|
|
|
|
if (*(int *)(puVar14 + 0x10) < 0)
|
|
{
|
|
|
|
LAB_8005e9cc:
|
|
|
|
// moving forward
|
|
if (-1 < (int)uVar8)
|
|
{
|
|
// forwardDir (0x3e8)
|
|
*(undefined2 *)(param_1 + 1000) = 1;
|
|
}
|
|
goto LAB_8005e9d8;
|
|
}
|
|
|
|
// moving backward
|
|
if ((int)uVar8 < 0)
|
|
{
|
|
// forwardDir (0x3e8)
|
|
*(undefined2 *)(param_1 + 1000) = 0xffff;
|
|
}
|
|
|
|
if (*(int *)(puVar14 + 0x10) < 1) goto LAB_8005e9cc;
|
|
|
|
LAB_8005e9e8:
|
|
|
|
// moving backward
|
|
if ((int)uVar8 < 0) goto LAB_8005ea08;
|
|
|
|
if (0 < *(int *)(puVar14 + 0x10)) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
// if driver is in air
|
|
else {
|
|
LAB_8005e9d8:
|
|
if (-1 < *(int *)(puVar14 + 0x10)) goto LAB_8005e9e8;
|
|
}
|
|
if ((int)uVar8 < 1) {
|
|
return;
|
|
}
|
|
|
|
// start Rollback
|
|
LAB_8005ea08:
|
|
|
|
|
|
// if rollback is starting, but in the last 0.64s
|
|
// the driver started rollback already, then rolled
|
|
// forward, and is now rolling back AGAIN, count
|
|
// V_Shift, inside two quadblocks in the shape of a V
|
|
if (*(short *)(param_1 + 0x408) != 0)
|
|
{
|
|
// increment number of V_Shifts
|
|
*(short *)(param_1 + 0x40a) = *(short *)(param_1 + 0x40a) + 1;
|
|
}
|
|
|
|
// reset timer, rolling backward
|
|
*(undefined2 *)(param_1 + 0x408) = 0x280;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
// VehPhysForce_OnApplyForces
|
|
void FUN_8005ea60(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
undefined4 uVar1;
|
|
int iVar2;
|
|
|
|
// if speed is more than top speed
|
|
if (0x6400 < *(short *)(param_2 + 0x38c))
|
|
{
|
|
// set top speed
|
|
*(undefined2 *)(param_2 + 0x38c) = 0x6400;
|
|
}
|
|
|
|
// vec3_originToCenter
|
|
// origin of driver model is center-bottom of kart,
|
|
// 0x19 is the half-radius of the model,
|
|
// calculate normalVec with magnitude 0x19 of driver,
|
|
// then we can find the "true center" of the model
|
|
gte_SetColorMatrix((MATRIX *)(param_2 + 0x330));
|
|
gte_ldVXY0(0x190000);
|
|
gte_ldVZ0(0);
|
|
gte_lcv0();
|
|
gte_stlvnl0((long *)(param_2 + 0x94));
|
|
gte_stlvnl1((long *)(param_2 + 0x98));
|
|
gte_stlvnl2((long *)(param_2 + 0x9c));
|
|
|
|
// VehPhysForce_ConvertSpeedToVec
|
|
FUN_8005e104(param_2,param_2 + 0x88,0);
|
|
|
|
if (
|
|
(
|
|
// if under-quadblock exists
|
|
(*(int *)(param_2 + 0x350) != 0) &&
|
|
|
|
// if quadblock terrain is mud
|
|
(*(char *)(*(int *)(param_2 + 0x350) + 0x38) == '\x0e')
|
|
)
|
|
)
|
|
{
|
|
// if you have not sinked to the mud's bottom (-0x1000)
|
|
if(-0x1000 < *(int *)(param_2 + 0x2d8))
|
|
{
|
|
// sink slower as you approach the mud's bottom
|
|
iVar2 = -0x1000 - *(int *)(param_2 + 0x2d8)
|
|
|
|
// set driver velY
|
|
if(*(int *)(param_2 + 0x8c) < iVar2)
|
|
{
|
|
*(int *)(param_2 + 0x8c) = iVar2;
|
|
}
|
|
}
|
|
}
|
|
|
|
// VehPhysForce_OnGravity
|
|
FUN_8005e214(param_2,param_2 + 0x88);
|
|
|
|
// normalVec = {0, 0x1000, ...}
|
|
*(undefined4 *)(param_2 + 0xa4) = 0x10000000;
|
|
|
|
// normalVec = {0, 0x1000, ...}
|
|
*(undefined4 *)(param_2 + 0x360) = 0x10000000;
|
|
|
|
// driver is not touching quadblock
|
|
*(undefined4 *)(param_2 + 0xa0) = 0;
|
|
|
|
// normalVec = {... ..., 0}
|
|
*(undefined2 *)(param_2 + 0xa8) = 0;
|
|
|
|
// normalVec = {... ..., 0}
|
|
*(undefined2 *)(param_2 + 0x364) = 0;
|
|
|
|
*(undefined2 *)(param_2 + 0xaa) = 0;
|
|
|
|
// increase velocity by acceleration
|
|
*(int *)(param_2 + 0x88) = *(int *)(param_2 + 0x88) + (int)*(short *)(param_2 + 0x3cc);
|
|
*(int *)(param_2 + 0x90) = *(int *)(param_2 + 0x90) + (int)*(short *)(param_2 + 0x3d0);
|
|
*(int *)(param_2 + 0x8c) = *(int *)(param_2 + 0x8c) + (int)*(short *)(param_2 + 0x3ce);
|
|
|
|
return;
|
|
}
|
|
|
|
// VehPhysForce_CollideDrivers
|
|
// handle collision with turbo pads and robotcars
|
|
void FUN_8005ebac(int param_1,int param_2)
|
|
|
|
{
|
|
int iVar1;
|
|
undefined4 uVar2;
|
|
int iVar3;
|
|
undefined4 uVar4;
|
|
uint uVar5;
|
|
undefined2 local_40;
|
|
undefined2 local_3e;
|
|
undefined2 local_3c;
|
|
int local_38;
|
|
int local_34;
|
|
|
|
// decrease velocity by acceleration
|
|
*(int *)(param_2 + 0x8c) = *(int *)(param_2 + 0x8c) - (int)*(short *)(param_2 + 0x3ce);
|
|
*(int *)(param_2 + 0x88) = *(int *)(param_2 + 0x88) - (int)*(short *)(param_2 + 0x3cc);
|
|
uVar5 = *(uint *)(param_2 + 0xbc);
|
|
*(int *)(param_2 + 0x90) = *(int *)(param_2 + 0x90) - (int)*(short *)(param_2 + 0x3d0);
|
|
|
|
if ((uVar5 & 0x4000) != 0) {
|
|
*(ushort *)(param_2 + 0xaa) = *(ushort *)(param_2 + 0xaa) | 1;
|
|
}
|
|
|
|
// If this is not a super turbo pad
|
|
if ((uVar5 & 2) == 0) {
|
|
|
|
// If this is not an ordinary turbo pad
|
|
if ((uVar5 & 1) == 0) goto LAB_8005ec70;
|
|
|
|
// add one second reserves
|
|
uVar2 = 0x3c0;
|
|
|
|
// If Super Turbo Pads is enabled
|
|
if ((*(uint *)(PTR_DAT_8008d2ac + 8) & 0x100000) != 0)
|
|
{
|
|
// Skip a few lines
|
|
goto LAB_8005ec50;
|
|
}
|
|
|
|
// set speed of turbo to normal speed
|
|
uVar4 = 0x100;
|
|
}
|
|
|
|
// If this is a super turbo pad (only on some tracks)
|
|
else {
|
|
LAB_8005ec50:
|
|
|
|
// add 0.12s reserves
|
|
uVar2 = 0x78;
|
|
|
|
// Set speed of turbo to big speed
|
|
uVar4 = 0x800;
|
|
}
|
|
|
|
// VehFire_Increment
|
|
// add reserves and speed of turbo pad
|
|
FUN_8005abfc(param_2,uVar2,5,uVar4);
|
|
|
|
LAB_8005ec70:
|
|
if ((uVar5 & 0x8000) == 0)
|
|
{
|
|
// thread -> instance -> flags
|
|
// instance is not in water or mud
|
|
*(uint *)(*(int *)(param_1 + 0x34) + 0x28) =
|
|
*(uint *)(*(int *)(param_1 + 0x34) + 0x28) & 0xffffdfff;
|
|
}
|
|
|
|
// if instance is in water or mud
|
|
else
|
|
{
|
|
// thread -> instance
|
|
iVar1 = *(int *)(param_1 + 0x34);
|
|
|
|
// set vertical split height
|
|
// (Y=0 for all water and mud)
|
|
*(undefined2 *)(iVar1 + 0x56) = 0;
|
|
|
|
// instance -> flags
|
|
// split the instance
|
|
*(uint *)(iVar1 + 0x28) = *(uint *)(iVar1 + 0x28) | 0x2000;
|
|
}
|
|
|
|
// if collision is not disabled for this thread
|
|
if ((*(uint *)(param_1 + 0x1c) & 0x1000) == 0)
|
|
{
|
|
// 40, 3e, 3c, 38, 34, allocated in that order
|
|
|
|
// position X and Y
|
|
local_40 = (undefined2)((uint)*(undefined4 *)(param_2 + 0x2d4) >> 8);
|
|
local_3e = (undefined2)((uint)*(undefined4 *)(param_2 + 0x2d8) >> 8);
|
|
|
|
// distance between two objects
|
|
local_34 = 0x7fffffff;
|
|
|
|
// thread you collide with
|
|
local_38 = 0;
|
|
|
|
// position Z
|
|
local_3c = (undefined2)((uint)*(undefined4 *)(param_2 + 0x2dc) >> 8);
|
|
|
|
// check for collision with all sibling threads
|
|
// PROC_CollidePointWithBucket
|
|
FUN_80042348(*(undefined4 *)(param_1 + 0x10),&local_40);
|
|
|
|
// pointer to first robotcar thread
|
|
// PROC_CollidePointWithBucket
|
|
FUN_80042348(*(undefined4 *)(PTR_DAT_8008d2ac + 0x1b40),&local_40);
|
|
|
|
if (
|
|
// if there was a collision
|
|
(local_38 != 0) &&
|
|
(
|
|
// thread offset 0x42?
|
|
iVar1 = (int)*(short *)(param_1 + 0x42) + (int)*(short *)(local_38 + 0x42),
|
|
|
|
local_34 < iVar1 * iVar1
|
|
)
|
|
)
|
|
{
|
|
// pass the thread, collision data, and driver->88 is velocity?
|
|
FUN_8005d404(param_1,&local_40,param_2 + 0x88);
|
|
}
|
|
}
|
|
if ((*(ushort *)(param_2 + 0xaa) & 2) != 0)
|
|
{
|
|
// driverPos - spsHitPos
|
|
iVar3 = (*(int *)(param_2 + 0x2d4) >> 8) - (int)*(short *)(param_2 + 0xac);
|
|
iVar1 = (*(int *)(param_2 + 0x2dc) >> 8) - (int)*(short *)(param_2 + 0xb0);
|
|
|
|
if (
|
|
// spsNormVec
|
|
*(short *)(param_2 + 0xb4) * iVar3 +
|
|
*(short *)(param_2 + 0xb6) * (((*(int *)(param_2 + 0x2d0) >> 8) - (int)*(short *)(param_2 + 0xae)) + 4) +
|
|
*(short *)(param_2 + 0xb8) * iVar1 < 0)
|
|
{
|
|
// calculate speed vector
|
|
*(int *)(param_2 + 0x88) = *(int *)(param_2 + 0x88) + iVar3 * 0x40;
|
|
*(int *)(param_2 + 0x8c) = *(int *)(param_2 + 0x8c) + ((*(int *)(param_2 + 0x2d8) >> 8) - (int)*(short *)(param_2 + 0xae)) * 0x40;
|
|
*(int *)(param_2 + 0x90) = *(int *)(param_2 + 0x90) + iVar1 * 0x40;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
// VehPhysForce_TranslateMatrix -- move position to instance matrix
|
|
// param1 = thread, param2 = driver
|
|
void FUN_8005ee34(int param_1,int param_2)
|
|
|
|
{
|
|
bool bVar1;
|
|
undefined *puVar2;
|
|
byte bVar3;
|
|
undefined2 uVar4;
|
|
short sVar5;
|
|
int iVar6;
|
|
undefined4 uVar7;
|
|
int iVar8;
|
|
int iVar9;
|
|
MATRIX *pMVar10;
|
|
int iVar11;
|
|
int *piVar12;
|
|
uint uVar13;
|
|
MATRIX *r0;
|
|
int iVar14;
|
|
undefined uVar15;
|
|
|
|
// get instance from thread
|
|
iVar14 = *(int *)(param_1 + 0x34);
|
|
|
|
// If you are not in a warp pad
|
|
if (*(char *)(param_2 + 0x376) != '\n')
|
|
{
|
|
// if you're being mask grabbed and you're not on the ground
|
|
if ((*(char *)(param_2 + 0x376) == '\x05') && ((*(uint *)(param_2 + 0x2c8) & 1) == 0))
|
|
{
|
|
// set Y scale
|
|
*(short *)(iVar14 + 0x1e) = *(short *)(param_2 + 0x40c) + 0xccc;
|
|
|
|
iVar6 = *(short *)(param_2 + 0x40c) * 0x28;
|
|
if (iVar6 < 0) {
|
|
iVar6 = iVar6 + 0xff;
|
|
}
|
|
|
|
// X and Z
|
|
iVar6 = 0xccc - (iVar6 >> 8);
|
|
if (iVar6 < 0x400) {
|
|
iVar6 = 0x400;
|
|
}
|
|
|
|
// Set X and Z scale
|
|
*(short *)(iVar14 + 0x1c) = (short)iVar6;
|
|
*(short *)(iVar14 + 0x20) = (short)iVar6;
|
|
}
|
|
|
|
// on ground, or mid-air without a mask-grab
|
|
else
|
|
{
|
|
sVar5 = *(short *)(param_2 + 0x390);
|
|
iVar8 = (int)sVar5;
|
|
iVar6 = -800;
|
|
|
|
// if player did not start jumping this frame
|
|
if ((*(uint *)(param_2 + 0x2c8) & 0x400) == 0)
|
|
{
|
|
iVar11 = (int)*(short *)(param_2 + 0x410) -
|
|
(*(short *)(param_2 + 0x410) * 9 + iVar8 * 7 >> 4);
|
|
iVar6 = iVar11 * 4;
|
|
iVar9 = iVar6;
|
|
if (iVar6 < 0) {
|
|
iVar9 = iVar11 * -4;
|
|
}
|
|
if (iVar9 < 0x960) {
|
|
iVar6 = 0;
|
|
}
|
|
|
|
// if racer did not just touch ground this frame or last
|
|
if (((*(uint *)(param_2 + 0x2c8) | *(uint *)(param_2 + 0x2cc)) & 2) == 0) {
|
|
bVar1 = iVar6 < 0x321;
|
|
if (iVar6 < -800) {
|
|
iVar6 = -800;
|
|
goto LAB_8005ef64;
|
|
}
|
|
}
|
|
|
|
// if racer just touched ground this frame or last
|
|
else {
|
|
bVar1 = iVar6 < 0x321;
|
|
if (iVar6 < -0x640) {
|
|
iVar6 = -0x640;
|
|
LAB_8005ef64:
|
|
bVar1 = iVar6 < 0x321;
|
|
}
|
|
}
|
|
if (!bVar1) {
|
|
iVar6 = 800;
|
|
}
|
|
}
|
|
|
|
//if Hazard Timer > 0 and Hazard Timer & 80 = 0 and (?)
|
|
if (((0 < *(short *)(param_2 + 0xe)) && ((*(ushort *)(param_2 + 0xe) & 0x80) == 0)) &&
|
|
(-800 < iVar6)) {
|
|
iVar6 = -800;
|
|
}
|
|
|
|
// if racer is not on the ground
|
|
if (((*(uint *)(param_2 + 0x2c8) & 1) == 0) && (iVar8 < 0))
|
|
{
|
|
// Map value from [oldMin, oldMax] to [newMin, newMax]
|
|
// inverting newMin and newMax will give an inverse range mapping
|
|
iVar9 = FUN_80058f9c(-iVar8,0,0xa00,0x280);
|
|
|
|
if (iVar6 < iVar9) {
|
|
iVar6 = iVar9;
|
|
}
|
|
*(short *)(param_2 + 0x410) = sVar5;
|
|
}
|
|
|
|
if (
|
|
// driver->instTntRecv
|
|
(*(int *)(param_2 + 0x18) != 0) &&
|
|
|
|
// driver->instTntRecv->scale[1] < 2500
|
|
(
|
|
iVar9 = (int)*(short *)(*(int *)(param_2 + 0x18) + 0x1e),
|
|
iVar9 < 2500
|
|
)
|
|
)
|
|
{
|
|
iVar6 = iVar6 + (iVar9 + -0x800) * 2;
|
|
}
|
|
|
|
iVar11 = (int)*(short *)(param_2 + 0x40c);
|
|
iVar9 = iVar6;
|
|
if (iVar6 < 0) {
|
|
iVar9 = -iVar6;
|
|
}
|
|
if (iVar11 < 0) {
|
|
iVar11 = -iVar11;
|
|
}
|
|
if (iVar11 < iVar9) {
|
|
*(short *)(param_2 + 0x40c) = (short)iVar6;
|
|
}
|
|
|
|
// Interpolate rotation by speed
|
|
uVar4 = FUN_80058f54((int)*(short *)(param_2 + 0x40c),300,0);
|
|
*(undefined2 *)(param_2 + 0x40c) = uVar4;
|
|
|
|
*(short *)(param_2 + 0x410) = (short)(*(short *)(param_2 + 0x410) * 9 + iVar8 * 7 >> 4);
|
|
|
|
if (*(short *)(param_2 + 0x404) == 0)
|
|
{
|
|
if (*(short *)(iVar14 + 0x1e) == 0)
|
|
{
|
|
// driver -> instance -> thread -> modelIndex == "player" of any kind
|
|
if (*(short *)(*(int *)(*(int *)(param_2 + 0x1c) + 0x6c) + 0x44) == 0x18)
|
|
{
|
|
// OtherFX_Play_Echo
|
|
// 0x5b?
|
|
FUN_80028494(0x5b,1,*(ushort *)(param_2 + 0x2ca) & 1);
|
|
}
|
|
|
|
*(short *)(iVar14 + 0x1e) = *(short *)(param_2 + 0x40c) + 0xccc;
|
|
|
|
// matrixArr for blasted
|
|
*(undefined *)(param_2 + 0x4c) = 5;
|
|
*(undefined *)(param_2 + 0x4d) = 0;
|
|
}
|
|
|
|
else
|
|
{
|
|
// Interpolate scale by speed
|
|
uVar4 = FUN_80058f54((int)*(short *)(iVar14 + 0x1e),0xa0,
|
|
*(short *)(param_2 + 0x40c) + 0xccc);
|
|
*(undefined2 *)(iVar14 + 0x1e) = uVar4;
|
|
}
|
|
}
|
|
else {
|
|
*(undefined2 *)(iVar14 + 0x1e) = 0;
|
|
}
|
|
iVar6 = *(short *)(param_2 + 0x40c) * 0xa0;
|
|
if (iVar6 < 0) {
|
|
iVar6 = iVar6 + 0xff;
|
|
}
|
|
|
|
// Interpolate scale by speed
|
|
uVar4 = FUN_80058f54((int)*(short *)(iVar14 + 0x1c),0xa0,0xccc - (iVar6 >> 8));
|
|
*(undefined2 *)(iVar14 + 0x1c) = uVar4;
|
|
iVar6 = *(short *)(param_2 + 0x40c) * 0xa0;
|
|
if (iVar6 < 0) {
|
|
iVar6 = iVar6 + 0xff;
|
|
}
|
|
|
|
// Interpolate rotation by speed
|
|
uVar4 = FUN_80058f54((int)*(short *)(iVar14 + 0x20),0xa0,0xccc - (iVar6 >> 8));
|
|
*(undefined2 *)(iVar14 + 0x20) = uVar4;
|
|
}
|
|
}
|
|
|
|
// VehPhysForce_RotAxisAngle (matrixFacingDir)
|
|
FUN_8005f89c(param_2 + 0x330,param_2 + 0x368,(int)*(short *)(param_2 + 0x2ee));
|
|
|
|
if (
|
|
(
|
|
(*(short *)(param_2 + 0x3e2) == 0) ||
|
|
(*(short *)(param_2 + 0x39e) < *(short *)(param_2 + 0x42c))
|
|
) ||
|
|
|
|
((*(uint *)(param_2 + 0x2c8) & 0x80) != 0)
|
|
)
|
|
{
|
|
// matrixArr
|
|
bVar3 = *(byte *)(param_2 + 0x4c);
|
|
if (bVar3 != 0) {
|
|
if (bVar3 == 2)
|
|
{
|
|
// matrixArr
|
|
*(undefined *)(param_2 + 0x4c) = 3;
|
|
LAB_8005f398:
|
|
*(undefined *)(param_2 + 0x4d) = 0;
|
|
}
|
|
else if (bVar3 < 3) {
|
|
if (bVar3 == 1) {
|
|
iVar6 = DAT_80087f00 + -1;
|
|
if (iVar6 == 0) {
|
|
trap(0x1c00);
|
|
}
|
|
if ((iVar6 == -1) && (*(byte *)(param_2 + 0x4d) == 0x800000)) {
|
|
trap(0x1800);
|
|
}
|
|
iVar8 = 0x100 - (int)((uint)*(byte *)(param_2 + 0x4d) << 8) / iVar6;
|
|
iVar6 = iVar8;
|
|
if (iVar8 < 0) {
|
|
iVar6 = 0;
|
|
}
|
|
if (0x100 < iVar8) {
|
|
iVar6 = 0x100;
|
|
}
|
|
uVar15 = (undefined)((uint)(iVar6 * (DAT_80087f10 + -1)) >> 8);
|
|
|
|
// matrixArr
|
|
*(undefined *)(param_2 + 0x4c) = 3;
|
|
|
|
goto LAB_8005f354;
|
|
}
|
|
}
|
|
else if ((bVar3 == 3) &&
|
|
(bVar3 = *(char *)(param_2 + 0x4d) + 1, *(byte *)(param_2 + 0x4d) = bVar3,
|
|
DAT_80087f10 <= (int)(uint)bVar3)) {
|
|
*(undefined *)(param_2 + 0x4c) = 0;
|
|
goto LAB_8005f398;
|
|
}
|
|
}
|
|
LAB_8005f39c:
|
|
bVar3 = *(byte *)(param_2 + 0x4c);
|
|
}
|
|
else {
|
|
bVar3 = *(byte *)(param_2 + 0x4c);
|
|
if (bVar3 == 1) {
|
|
bVar3 = *(char *)(param_2 + 0x4d) + 1;
|
|
*(byte *)(param_2 + 0x4d) = bVar3;
|
|
if (DAT_80087f00 <= (int)(uint)bVar3)
|
|
{
|
|
// matrixArr
|
|
*(undefined *)(param_2 + 0x4c) = 2;
|
|
goto LAB_8005f398;
|
|
}
|
|
goto LAB_8005f39c;
|
|
}
|
|
if (1 < bVar3) {
|
|
if ((bVar3 != 2) && (bVar3 == 3)) {
|
|
iVar6 = DAT_80087f10 + -1;
|
|
if (iVar6 == 0) {
|
|
trap(0x1c00);
|
|
}
|
|
if ((iVar6 == -1) && (*(byte *)(param_2 + 0x4d) == 0x800000)) {
|
|
trap(0x1800);
|
|
}
|
|
iVar8 = 0x100 - (int)((uint)*(byte *)(param_2 + 0x4d) << 8) / iVar6;
|
|
iVar6 = iVar8;
|
|
if (iVar8 < 0) {
|
|
iVar6 = 0;
|
|
}
|
|
if (0x100 < iVar8) {
|
|
iVar6 = 0x100;
|
|
}
|
|
uVar15 = (undefined)((uint)(iVar6 * (DAT_80087f00 + -1)) >> 8);
|
|
|
|
// matrixArr
|
|
*(undefined *)(param_2 + 0x4c) = 1;
|
|
LAB_8005f354:
|
|
*(undefined *)(param_2 + 0x4d) = uVar15;
|
|
}
|
|
goto LAB_8005f39c;
|
|
}
|
|
if (bVar3 == 0)
|
|
{
|
|
// matrixArr
|
|
*(undefined *)(param_2 + 0x4c) = 1;
|
|
goto LAB_8005f398;
|
|
}
|
|
}
|
|
if ((bVar3 == 5) &&
|
|
(bVar3 = *(char *)(param_2 + 0x4d) + 1, *(byte *)(param_2 + 0x4d) = bVar3,
|
|
DAT_80087f20 <= (int)(uint)bVar3)) {
|
|
*(undefined *)(param_2 + 0x4c) = 0;
|
|
*(undefined *)(param_2 + 0x4d) = 0;
|
|
}
|
|
|
|
// animation index
|
|
if (*(byte *)(param_2 + 0x4c) == 0)
|
|
{
|
|
// copy matrix from driver to instance?
|
|
*(undefined4 *)(iVar14 + 0x30) = *(undefined4 *)(param_2 + 0x330);
|
|
*(undefined4 *)(iVar14 + 0x34) = *(undefined4 *)(param_2 + 0x334);
|
|
*(undefined4 *)(iVar14 + 0x38) = *(undefined4 *)(param_2 + 0x338);
|
|
*(undefined4 *)(iVar14 + 0x3c) = *(undefined4 *)(param_2 + 0x33c);
|
|
*(undefined2 *)(iVar14 + 0x40) = *(undefined2 *)(param_2 + 0x340);
|
|
|
|
// position (xyz)
|
|
*(int *)(iVar14 + 0x44) = *(int *)(param_2 + 0x2d4) >> 8;
|
|
*(int *)(iVar14 + 0x48) = (*(int *)(param_2 + 0x2d8) >> 8) + (*(char *)(param_2 + 0x377) * 3 >> 3);
|
|
iVar6 = *(int *)(param_2 + 0x2dc);
|
|
}
|
|
|
|
// different animation index
|
|
else
|
|
{
|
|
// driver -> 0x330 matrix
|
|
r0 = (MATRIX *)(param_2 + 0x330);
|
|
|
|
// 0x4C - which matrix array
|
|
// 0x4D - which matrix index
|
|
piVar12 = (int *)((&DAT_80087ef4)[(uint)*(byte *)(param_2 + 0x4c) * 2] +
|
|
(uint)*(byte *)(param_2 + 0x4d) * 0x20);
|
|
|
|
pMVar10 = r0;
|
|
|
|
// MatrixRotate(
|
|
// output = instMatrix,
|
|
// input1 = driver->matrixFacingDir
|
|
// input2 = animated matrix orientation set);
|
|
FUN_8006c3b0(iVar14 + 0x30,r0,piVar12 + 2);
|
|
|
|
// load matrix
|
|
gte_SetRotMatrix(r0);
|
|
|
|
// load vector
|
|
iVar6 = *piVar12;
|
|
gte_ldVXY0(iVar6);
|
|
gte_ldVZ0((uint)*(ushort *)(piVar12 + 1));
|
|
|
|
gte_rtv0();
|
|
|
|
// x shares register with iVar6
|
|
// y shares register with r0
|
|
// z shares register with pMVar10
|
|
read_mt(iVar6,r0,pMVar10);
|
|
|
|
// position (xyz)
|
|
*(int *)(iVar14 + 0x44) = *(int *)(param_2 + 0x2d4) + iVar6 >> 8;
|
|
*(int *)(iVar14 + 0x48) = ((int)r0->m + *(int *)(param_2 + 0x2d8) >> 8) + (*(char *)(param_2 + 0x377) * 3 >> 3);
|
|
iVar6 = (int)pMVar10->m + *(int *)(param_2 + 0x2dc);
|
|
}
|
|
|
|
// matrix -> 0x4C (posZ)
|
|
*(int *)(iVar14 + 0x4c) = iVar6 >> 8;
|
|
|
|
// if driver is squished
|
|
if (*(short *)(param_2 + 0x404) != 0)
|
|
{
|
|
// increment position by AngleAxis_NormalVec
|
|
*(int *)(iVar14 + 0x44) = *(int *)(iVar14 + 0x44) + (*(short *)(param_2 + 0x368) * 0x13 >> 0xc);
|
|
*(int *)(iVar14 + 0x48) = *(int *)(iVar14 + 0x48) + (*(short *)(param_2 + 0x36a) * 0x13 >> 0xc);
|
|
*(int *)(iVar14 + 0x4c) = *(int *)(iVar14 + 0x4c) + (*(short *)(param_2 + 0x36c) * 0x13 >> 0xc);
|
|
}
|
|
|
|
iVar6 = *(int *)(iVar14 + 0x48);
|
|
if (-1 < iVar6) {
|
|
code_r0x8005f834:
|
|
if (0 < iVar6) {
|
|
*(uint *)(iVar14 + 0x28) = *(uint *)(iVar14 + 0x28) & 0xffffdfff;
|
|
}
|
|
|
|
// wakeInst
|
|
iVar14 = *(int *)(param_2 + 0x4f8);
|
|
|
|
// if valid
|
|
if (iVar14 != 0)
|
|
{
|
|
// make invisible
|
|
*(uint *)(iVar14 + 0x28) = *(uint *)(iVar14 + 0x28) | 0x80;
|
|
|
|
// clear driver->wakeScale, and wakeInst->scale
|
|
*(undefined2 *)(param_2 + 0x4fc) = 0;
|
|
*(undefined2 *)(iVar14 + 0x1c) = 0;
|
|
*(undefined2 *)(iVar14 + 0x20) = *(undefined2 *)(param_2 + 0x4fc);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// touching wall so???? or is it water?
|
|
if ((iVar6 < -0x4f) || ((*(uint *)(iVar14 + 0x28) & 0x2000) == 0)) {
|
|
iVar6 = *(int *)(iVar14 + 0x48);
|
|
goto code_r0x8005f834;
|
|
}
|
|
iVar6 = *(int *)(param_2 + 0x4f8);
|
|
if (iVar6 == 0) {
|
|
return;
|
|
}
|
|
|
|
// make visible
|
|
*(uint *)(iVar6 + 0x28) = *(uint *)(iVar6 + 0x28) & 0xffffff7f;
|
|
|
|
// animation data
|
|
*(char *)(iVar6 + 0x50) = *(char *)(iVar14 + 0x50) + '\x01';
|
|
*(char *)(iVar6 + 0x51) = *(char *)(iVar14 + 0x51) + -1;
|
|
|
|
// instance posX, posY, posZ
|
|
uVar7 = *(undefined4 *)(iVar14 + 0x44);
|
|
*(undefined4 *)(iVar6 + 0x48) = 0;
|
|
*(undefined4 *)(iVar6 + 0x44) = uVar7;
|
|
*(undefined4 *)(iVar6 + 0x4c) = *(undefined4 *)(iVar14 + 0x4c);
|
|
|
|
// driver -> rotation
|
|
uVar13 = (uint)*(short *)(param_2 + 0x39a);
|
|
|
|
// approximate trigonometry
|
|
|
|
// Sin(angle)
|
|
sVar5 = (short)*(int *)(&DAT_800845a0 + (uVar13 & 0x3ff) * 4);
|
|
|
|
// Cos(angle)
|
|
iVar14 = *(int *)(&DAT_800845a0 + (uVar13 & 0x3ff) * 4) >> 0x10;
|
|
|
|
// if (0 < angle < 90) or (180 < angle < 270)
|
|
if ((uVar13 & 0x400) == 0) {
|
|
iVar8 = (int)sVar5;
|
|
if ((uVar13 & 0x800) == 0) goto LAB_8005f6a4;
|
|
iVar9 = -iVar14;
|
|
}
|
|
|
|
// if (90 < angle < 180) or (270 < angle < 360)
|
|
else {
|
|
iVar9 = (int)sVar5;
|
|
iVar8 = iVar14;
|
|
if ((uVar13 & 0x800) == 0) {
|
|
iVar14 = -iVar9;
|
|
goto LAB_8005f6a4;
|
|
}
|
|
}
|
|
iVar8 = -iVar8;
|
|
iVar14 = iVar9;
|
|
LAB_8005f6a4:
|
|
|
|
// instance rotation
|
|
// looks like 5 int variables, but it's really
|
|
// 9 short variables, 3x3 rotation matrix
|
|
*(int *)(iVar6 + 0x30) = iVar14;
|
|
*(int *)(iVar6 + 0x34) = iVar8;
|
|
*(undefined4 *)(iVar6 + 0x38) = 0x1000;
|
|
*(int *)(iVar6 + 0x3c) = -iVar8;
|
|
*(short *)(iVar6 + 0x40) = (short)iVar14;
|
|
|
|
puVar2 = PTR_DAT_8008d2ac;
|
|
|
|
// if wake is not visible,
|
|
// then do this for first frame of wake,
|
|
// which sets scale, and makes a splash
|
|
if (*(short *)(param_2 + 0x4fc) == 0)
|
|
{
|
|
// wake is now visible (set scale)
|
|
*(undefined2 *)(param_2 + 0x4fc) = 0x1000;
|
|
|
|
// if less than 2 screens
|
|
if ((byte)puVar2[0x1ca8] < 2)
|
|
{
|
|
// get speed
|
|
iVar14 = (int)*(short *)(param_2 + 0x38c);
|
|
|
|
// absolute value
|
|
if (iVar14 < 0) {
|
|
iVar14 = -iVar14;
|
|
}
|
|
|
|
if (
|
|
// if speed is high
|
|
(0xc00 < iVar14) &&
|
|
|
|
(
|
|
// spawn 10 particles
|
|
iVar14 = 10,
|
|
|
|
// racerY position is more than -0x200
|
|
-0x200 < *(int *)(param_2 + 0x2e4)
|
|
)
|
|
)
|
|
{
|
|
// spawn particles till counter runs out
|
|
do
|
|
{
|
|
// 0x2138 = "falling"
|
|
// like splashing in water on coco park
|
|
|
|
// Create instance in particle pool
|
|
iVar8 = FUN_80040308(0,*(undefined4 *)(PTR_DAT_8008d2ac + 0x2138),&DAT_80089a94);
|
|
|
|
// if particle was made properly
|
|
if (iVar8 != 0)
|
|
{
|
|
*(undefined *)(iVar8 + 0x18) = *(undefined *)(*(int *)(param_2 + 0x1c) + 0x50);
|
|
|
|
// driver->instSelf
|
|
*(undefined4 *)(iVar8 + 0x20) = *(undefined4 *)(param_2 + 0x1c);
|
|
|
|
// driverID
|
|
*(undefined *)(iVar8 + 0x19) = *(undefined *)(param_2 + 0x4a);
|
|
}
|
|
|
|
// reduce counter
|
|
iVar14 = iVar14 + -1;
|
|
|
|
} while (iVar14 != 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
// if numPlyrCurrGame is less than 2
|
|
else if ((byte)PTR_DAT_8008d2ac[0x1ca8] < 2)
|
|
{
|
|
// get speed
|
|
iVar14 = (int)*(short *)(param_2 + 0x38c);
|
|
|
|
// absolute value
|
|
if (iVar14 < 0) {
|
|
iVar14 = -iVar14;
|
|
}
|
|
|
|
if (
|
|
// if speed is high
|
|
(0xc00 < iVar14) &&
|
|
|
|
// spawn one particle
|
|
(
|
|
// 0x2138 = "falling"
|
|
// like splashing in water on coco park
|
|
|
|
// Create instance in particle pool
|
|
iVar14 = FUN_80040308(0,*(undefined4 *)(PTR_DAT_8008d2ac + 0x2138),&DAT_80089a94),
|
|
iVar14 != 0
|
|
)
|
|
)
|
|
{
|
|
*(undefined *)(iVar14 + 0x18) = *(undefined *)(*(int *)(param_2 + 0x1c) + 0x50);
|
|
|
|
// driver -> instSelf
|
|
*(undefined4 *)(iVar14 + 0x20) = *(undefined4 *)(param_2 + 0x1c);
|
|
|
|
// driverID
|
|
*(undefined *)(iVar14 + 0x19) = *(undefined *)(param_2 + 0x4a);
|
|
}
|
|
}
|
|
|
|
// instance -> scale (x, z)
|
|
*(undefined2 *)(iVar6 + 0x1c) = *(undefined2 *)(param_2 + 0x4fc);
|
|
*(undefined2 *)(iVar6 + 0x20) = *(undefined2 *)(param_2 + 0x4fc);
|
|
return;
|
|
}
|
|
|
|
|
|
// VehPhysForce_RotAxisAngle
|
|
// param1 - matrix
|
|
// param2 - normal axis
|
|
// param3 - angle
|
|
// equivalent to glm::AngleAxis, Unity Quaternion.AngleAxis, UE4 FVector AngleAxis
|
|
void FUN_8005f89c(undefined2 *param_1,short *param_2,uint param_3)
|
|
|
|
{
|
|
short sVar1;
|
|
int iVar2;
|
|
int iVar3;
|
|
uint uVar4;
|
|
short sVar5;
|
|
int iVar6;
|
|
int iVar7;
|
|
int iVar8;
|
|
short sVar9;
|
|
int iVar10;
|
|
int iVar11;
|
|
undefined4 uVar12;
|
|
int iVar13;
|
|
undefined4 uVar14;
|
|
undefined4 uVar15;
|
|
int iVar16;
|
|
int iVar17;
|
|
int iVar18;
|
|
|
|
// normalX
|
|
sVar1 = *param_2;
|
|
param_1[1] = sVar1;
|
|
|
|
// normalY
|
|
sVar9 = param_2[1];
|
|
iVar11 = (int)sVar1;
|
|
param_1[4] = sVar9;
|
|
|
|
// normalZ
|
|
iVar10 = (int)param_2[2];
|
|
param_1[7] = param_2[2];
|
|
|
|
// approximate trigonometry
|
|
sVar1 = (short)*(int *)(&DAT_800845a0 + (param_3 & 0x3ff) * 4);
|
|
iVar2 = *(int *)(&DAT_800845a0 + (param_3 & 0x3ff) * 4) >> 0x10;
|
|
|
|
// if (0 < angle < 90) or (180 < angle < 270)
|
|
if ((param_3 & 0x400) == 0)
|
|
{
|
|
iVar7 = (int)sVar1;
|
|
|
|
// if (0 < angle < 90)
|
|
if ((param_3 & 0x800) == 0) goto LAB_8005f934;
|
|
|
|
// if (180 < angle < 270)
|
|
// make X and Y values negative
|
|
iVar8 = -iVar2;
|
|
}
|
|
|
|
// if (90 < angle < 180) or (270 < angle < 360)
|
|
else
|
|
{
|
|
iVar8 = (int)sVar1;
|
|
iVar7 = iVar2;
|
|
|
|
// if (90 < angle < 180)
|
|
if ((param_3 & 0x800) == 0) {
|
|
iVar2 = -iVar8;
|
|
goto LAB_8005f934;
|
|
}
|
|
|
|
// if (270 < angle < 360)
|
|
// proceed without "goto"
|
|
}
|
|
|
|
iVar7 = -iVar7;
|
|
iVar2 = iVar8;
|
|
|
|
LAB_8005f934:
|
|
iVar16 = iVar11 * iVar11;
|
|
iVar17 = iVar10 * iVar10;
|
|
iVar18 = iVar11 * -iVar10;
|
|
iVar6 = iVar16 + iVar17;
|
|
iVar13 = iVar7 * sVar9 >> 0xc;
|
|
sVar1 = (short)iVar13;
|
|
iVar8 = iVar2 * sVar9 >> 0xc;
|
|
sVar9 = (short)iVar8;
|
|
|
|
gte_ldLZCS(iVar6);
|
|
iVar3 = gte_stLZCR();
|
|
|
|
if (iVar6 == 0)
|
|
{
|
|
iVar2 = iVar7 * iVar11 + iVar2 * iVar10;
|
|
|
|
// if normalY is negative
|
|
if (param_2[1] < 0)
|
|
{
|
|
// flip
|
|
sVar1 = -sVar1;
|
|
}
|
|
}
|
|
else {
|
|
uVar4 = 0x14 - iVar3;
|
|
if (0 < (int)uVar4) {
|
|
iVar16 = iVar16 >> (uVar4 & 0x1f);
|
|
iVar17 = iVar17 >> (uVar4 & 0x1f);
|
|
iVar18 = iVar18 >> (uVar4 & 0x1f);
|
|
iVar6 = iVar6 >> (uVar4 & 0x1f);
|
|
}
|
|
iVar13 = iVar7 - iVar13;
|
|
iVar8 = iVar2 - iVar8;
|
|
iVar3 = iVar13 * iVar17 + iVar8 * iVar18;
|
|
if (iVar6 == 0) {
|
|
trap(0x1c00);
|
|
}
|
|
if ((iVar6 == -1) && (iVar3 == -0x80000000)) {
|
|
trap(0x1800);
|
|
}
|
|
iVar8 = iVar13 * iVar18 + iVar8 * iVar16;
|
|
if (iVar6 == 0) {
|
|
trap(0x1c00);
|
|
}
|
|
if ((iVar6 == -1) && (iVar8 == -0x80000000)) {
|
|
trap(0x1800);
|
|
}
|
|
sVar1 = sVar1 + (short)(iVar3 / iVar6);
|
|
iVar2 = iVar7 * iVar11 + iVar2 * iVar10;
|
|
sVar9 = sVar9 + (short)(iVar8 / iVar6);
|
|
}
|
|
|
|
// write to matrix
|
|
param_1[2] = sVar1;
|
|
sVar5 = (short)(-iVar2 >> 0xc);
|
|
param_1[5] = sVar5;
|
|
param_1[8] = sVar9;
|
|
|
|
// axis to rotate on
|
|
gte_ldopv1SV(param_2);
|
|
|
|
|
|
// new GTE calls this
|
|
// gte_ldopv2SV(r0);
|
|
setCopReg(2,0x4800,(int)sVar1);
|
|
setCopReg(2,0x5000,(int)sVar5);
|
|
setCopReg(2,0x5800,(int)sVar9);
|
|
|
|
|
|
gte_op12();
|
|
read_mt(uVar12,uVar14,uVar15);
|
|
|
|
|
|
// write to matrix
|
|
*param_1 = (short)uVar12;
|
|
param_1[3] = (short)uVar14;
|
|
param_1[6] = (short)uVar15;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
// VehPhysForce_AccelTerrainSlope
|
|
// param1 - driver object
|
|
// called from:
|
|
// VehPhysGeneral_PhysAngular
|
|
// VehPhysProc_PowerSlide_PhysAngular
|
|
uint FUN_8005fb4c(int param_1)
|
|
|
|
{
|
|
int iVar1;
|
|
uint uVar2;
|
|
uint uVar3;
|
|
uint uVar4;
|
|
undefined4 uVar5;
|
|
|
|
// speed
|
|
iVar1 = (int)*(short *)(param_1 + 0x38e);
|
|
|
|
// erase accel X,Y,Z
|
|
*(undefined2 *)(param_1 + 0x3cc) = 0;
|
|
*(undefined2 *)(param_1 + 0x3ce) = 0;
|
|
*(undefined2 *)(param_1 + 0x3d0) = 0;
|
|
|
|
if (iVar1 < 0) {
|
|
iVar1 = -iVar1;
|
|
}
|
|
|
|
// low speed (useless? shoould just be '= 0;')
|
|
uVar2 = (uint)(iVar1 < 0x301);
|
|
|
|
if (
|
|
// high speed
|
|
(iVar1 >= 0x301) &&
|
|
|
|
(
|
|
// high speed
|
|
uVar2 = 1,
|
|
|
|
// if not crashing
|
|
*(char *)(param_1 + 0x376) != '\x01'
|
|
)
|
|
)
|
|
{
|
|
// check if driver is in warppad
|
|
uVar2 = *(uint *)(param_1 + 0x2c8) & 0x4000;
|
|
|
|
if (
|
|
// if driver is not being warped
|
|
(uVar2 == 0) &&
|
|
(
|
|
(
|
|
(
|
|
// if driver is on quadblock
|
|
uVar2 = *(uint *)(param_1 + 0x2c8) & 1,
|
|
|
|
*(short *)(param_1 + 0x3fe) == 0 &&
|
|
|
|
// if driver is on quadblock
|
|
(uVar2 != 0)
|
|
)
|
|
&&
|
|
(
|
|
// driver -> terrain meta -> ???
|
|
// 0x100 for everything except:
|
|
// 0x000 for "ice" and "none" (mid-air)
|
|
uVar2 = *(uint *)(*(int *)(param_1 + 0x358) + 0x10),
|
|
|
|
// not on ice, not mid-air
|
|
uVar2 != 0
|
|
)
|
|
)
|
|
)
|
|
)
|
|
{
|
|
|
|
// angleCurr - anglePrev
|
|
uVar4 = (int)*(short *)(param_1 + 0x3c6) - (int)*(short *)(param_1 + 0x3c8);
|
|
|
|
// set 0x457 to zero, to remove all camera slack,
|
|
// with no slack, steering locks camera to driver
|
|
|
|
// kart angle cap from 'straight to camera'
|
|
uVar3 = (uint)*(byte *)(param_1 + 0x457);
|
|
|
|
// clamp to min cap or max cap
|
|
if ((int)uVar3 < (int)uVar4) uVar4 = uVar3;
|
|
if ((int)uVar4 < (int)-uVar3) uVar4 = -uVar3;
|
|
|
|
// approximate trigonometry
|
|
iVar1 = *(int *)(&DAT_800845a0 + (uVar4 & 0x3ff) * 4);
|
|
|
|
if ((uVar4 & 0x400) == 0) {
|
|
iVar1 = iVar1 << 0x10;
|
|
}
|
|
iVar1 = iVar1 >> 0x10;
|
|
if ((uVar4 & 0x800) != 0) {
|
|
iVar1 = -iVar1;
|
|
}
|
|
|
|
// before this function is called, there is always
|
|
// gte_SetRotMatrix, AxisAngle, driver -> 0x310
|
|
|
|
uVar2 = ((int)(uVar2 * -8000) >> 8) * iVar1 >> 0xc & 0xffff;
|
|
gte_ldVXY0(uVar2);
|
|
gte_ldVZ0(0);
|
|
gte_rtv0();
|
|
|
|
// new acceleration vector
|
|
|
|
uVar5 = gte_stMAC1();
|
|
*(short *)(param_1 + 0x3cc) = (short)uVar5;
|
|
uVar5 = gte_stMAC2();
|
|
*(short *)(param_1 + 0x3ce) = (short)uVar5;
|
|
uVar5 = gte_stMAC3();
|
|
*(short *)(param_1 + 0x3d0) = (short)uVar5;
|
|
}
|
|
}
|
|
|
|
// does not really "return" anything, it just
|
|
// sees something in r2 and assumes. Stupid ghidra
|
|
return uVar2;
|
|
}
|
|
|
|
|
|
// VehPhysGeneral_PhysAngular
|
|
void FUN_8005fc8c(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
bool bVar1;
|
|
bool bVar2;
|
|
undefined2 uVar3;
|
|
short sVar4;
|
|
int iVar5;
|
|
int iVar6;
|
|
undefined4 uVar7;
|
|
int iVar8;
|
|
int iVar9;
|
|
uint uVar10;
|
|
int iVar11;
|
|
int iVar12;
|
|
short sVar13;
|
|
int iVar14;
|
|
int iVar15;
|
|
int iVar16;
|
|
short sVar17;
|
|
int iVar18;
|
|
int iVar19;
|
|
uint local_38;
|
|
|
|
// get camera rotation
|
|
iVar14 = (int)*(short *)(param_2 + 0x2f2);
|
|
|
|
// copy the variable
|
|
iVar5 = iVar14;
|
|
|
|
// make sure the camera is not negative; ie. get camera angle absolute
|
|
if (iVar14 < 0) {
|
|
iVar5 = -iVar14;
|
|
}
|
|
|
|
// elapsed milliseconds per frame, ~32
|
|
iVar8 = *(int *)(PTR_DAT_8008d2ac + 0x1d04);
|
|
|
|
uVar10 = iVar5 >> 3;
|
|
if (uVar10 == 0) {
|
|
uVar10 = 1;
|
|
}
|
|
// meta behaviour
|
|
if ((int)(uint)*(byte *)(param_2 + 0x46a) < (int)uVar10) {
|
|
uVar10 = (uint)*(byte *)(param_2 + 0x46a);
|
|
}
|
|
|
|
// Interpolate rotation by speed
|
|
// Rotation_Interpolation(rotPrev.w, 8, uVar10)
|
|
iVar5 = FUN_80058f54((int)*(short *)(param_2 + 0x2fa),8,uVar10);
|
|
|
|
// rotPrev.w = iVar5
|
|
*(undefined2 *)(param_2 + 0x2fa) = (short)iVar5;
|
|
|
|
// Interpolate rotation by speed
|
|
// Rotation_Interpolation( abs(camerarotation), rotPrev.w * elapsedTimeInMS >> 5, 0)
|
|
uVar3 = FUN_80058f54(iVar14,iVar5 * iVar8 >> 5,0);
|
|
|
|
local_38 = *(uint *)(param_2 + 0x2c8);
|
|
// sVar4 = numFramesSpentSteering
|
|
sVar4 = *(short *)(param_2 + 1000);
|
|
|
|
// set camera rotation (rotCurr.W)
|
|
*(undefined2 *)(param_2 + 0x2f2) = uVar3;
|
|
|
|
// speedApprox
|
|
iVar14 = (int)*(short *)(param_2 + 0x38e);
|
|
|
|
// int simpTurnState256 = simpTurnState * 0x100
|
|
iVar5 = (int)*(char *)(param_2 + 0x4b) * 0x100;
|
|
|
|
// if speedApprox is negative
|
|
if (iVar14 < 1)
|
|
{
|
|
// baseSpeed is negative
|
|
if (*(short *)(param_2 + 0x39c) < 0)
|
|
{
|
|
// forwardDir (0x3e8)
|
|
sVar4 = -1;
|
|
*(undefined2 *)(param_2 + 1000) = 0xffff; // -1
|
|
}
|
|
if (-1 < iVar14) goto LAB_8005fd74;
|
|
}
|
|
|
|
// if speedApprox is positive
|
|
else {
|
|
|
|
LAB_8005fd74:
|
|
|
|
// baseSpeed is positive
|
|
if (-1 < *(short *)(param_2 + 0x39c))
|
|
{
|
|
// forwardDir (0x3e8)
|
|
sVar4 = 1;
|
|
*(undefined2 *)(param_2 + 1000) = 1;
|
|
}
|
|
}
|
|
if (sVar4 < 0) {
|
|
// simpTurnState256 = simpTurnState * -0x100;
|
|
iVar5 = (int)*(char *)(param_2 + 0x4b) * -0x100;
|
|
// ActionsFlagSet = ActionsFlagSet ^ 0x10
|
|
local_38 = local_38 ^ 0x10;
|
|
}
|
|
if (iVar14 < 0) {
|
|
iVar14 = -iVar14;
|
|
}
|
|
if (
|
|
((local_38 & 1) != 0) &&
|
|
|
|
// if you're not on any turbo pad
|
|
((*(uint *)(param_2 + 0xbc) & 3) == 0)
|
|
)
|
|
{
|
|
|
|
// Map value from [oldMin, oldMax] to [newMin, newMax]
|
|
// inverting newMin and newMax will give an inverse range mapping
|
|
iVar5 = FUN_80058f9c(iVar14,0x10,0x300,0,iVar5);
|
|
}
|
|
|
|
//terrainMeta1
|
|
iVar12 = *(int *)(param_2 + 0x358);
|
|
|
|
// rotationSpinRate = driver.rotationSpinRate;
|
|
iVar9 = (int)*(short *)(param_2 + 0x3b4);
|
|
|
|
if (iVar5 == 0)
|
|
{
|
|
// Interpolate rotation by speed
|
|
//
|
|
sVar4 = FUN_80058f54(iVar9,((int)*(short *)(param_2 + 0x43e) +
|
|
(int)*(char *)(param_2 + 0x34) * 0x32) * *(int *)(iVar12 + 0x28) >> 8
|
|
,0);
|
|
}
|
|
else {
|
|
bVar1 = iVar5 < 0;
|
|
if (bVar1) {
|
|
iVar5 = -iVar5;
|
|
iVar9 = -iVar9;
|
|
}
|
|
sVar4 = (short)iVar9;
|
|
//if (rotationSpinRate < simpTurnState256) {
|
|
if (iVar9 < iVar5) {
|
|
//rotationSpinRate = rotationSpinRate + ((TurningInputResponseStat + TurnConst * 100) * (terrainMeta1 + 0x28) >> 8);
|
|
// 100%
|
|
iVar9 = iVar9 + (((int)*(short *)(param_2 + 0x43e) + (int)*(char *)(param_2 + 0x34) * 100) *
|
|
*(int *)(iVar12 + 0x28) >> 8);
|
|
//rotationSpinRateS16 = (short)rotationSpinRate;
|
|
sVar4 = (short)iVar9;
|
|
|
|
/*if (simpTurnState256 < rotationSpinRate) {
|
|
rotationSpinRateS16 = (short)simpTurnState256;
|
|
}*/
|
|
bVar2 = iVar5 < iVar9;
|
|
LAB_8005fee4:
|
|
if (bVar2) {
|
|
sVar4 = (short)iVar5;
|
|
}
|
|
}
|
|
else {
|
|
//if (simpTurnState256 < rotationSpinRate)
|
|
if (iVar5 < iVar9) {
|
|
//rotationSpinRate = rotationSpinRate - ((TurningInputResponseStat + TurnConst * 0x32) * (terrainMeta1 + 0x28) >> 8)
|
|
// 50%
|
|
iVar9 = iVar9 - (((int)*(short *)(param_2 + 0x43e) + (int)*(char *)(param_2 + 0x34) * 0x32)
|
|
* *(int *)(iVar12 + 0x28) >> 8);
|
|
//rotationSpinRateS16 = (short)rotationSpinRate;
|
|
sVar4 = (short)iVar9;
|
|
|
|
/*if (rotationSpinRate < simpTurnState256) {
|
|
rotationSpinRateS16 = (short)simpTurnState256;
|
|
}*/
|
|
bVar2 = iVar9 < iVar5;
|
|
goto LAB_8005fee4;
|
|
}
|
|
}
|
|
//if (isforwardDirNegative)
|
|
if (bVar1) {
|
|
//rotationSpinRateS16 = -rotationSpinRateS16
|
|
sVar4 = -sVar4;
|
|
}
|
|
}
|
|
|
|
iVar5 = (int)*(short *)(param_2 + 0x3ec);
|
|
|
|
//rotationSpinRate = rotationSpinRateS16;
|
|
iVar9 = (int)sVar4;
|
|
|
|
// driver.rotationSpinRate = rotationSpinRateS16
|
|
*(short *)(param_2 + 0x3b4) = sVar4;
|
|
|
|
if (iVar5 != 0)
|
|
{
|
|
uVar3 = (undefined2)(iVar5 - iVar8);
|
|
|
|
// map [0-0x140] to [0-???]
|
|
// deltaRotation = VehCalc_MapToRange(timeUntilDriftSpinout,0,0x140,0,previousFrameMultDrift);
|
|
iVar6 = FUN_80058f9c(iVar5,0,0x140,0,(int)*(short *)(param_2 + 0x3ea));
|
|
|
|
// rotationSpinRate = rotationSpinRate + deltaRotation;
|
|
iVar9 = iVar9 + iVar6;
|
|
|
|
// if (deltaTime < 0)
|
|
if (iVar5 - iVar8 < 0) {
|
|
uVar3 = 0;
|
|
}
|
|
|
|
*(undefined2 *)(param_2 + 0x3ec) = uVar3;
|
|
}
|
|
|
|
// character_Speed
|
|
iVar11 = (uint)*(ushort *)(param_2 + 0x42c) << 0x10;
|
|
iVar6 = iVar11 >> 0x10;
|
|
|
|
// turnResistMax = MetaPhys.turnResistMax * iVar6
|
|
iVar19 = (uint)*(byte *)(param_2 + 0x45d) * iVar6;
|
|
|
|
// turnResistMin = MetaPhys.turnResistMin * iVar6
|
|
iVar6 = (uint)*(byte *)(param_2 + 0x45c) * iVar6;
|
|
|
|
sVar4 = *(short *)(param_2 + 0x3d2);
|
|
|
|
// const_ModelRotationSpeed
|
|
iVar5 = (int)*(short *)(param_2 + 0x452);
|
|
|
|
iVar18 = iVar19 >> 8;
|
|
iVar16 = iVar6 >> 8;
|
|
|
|
// gas and break together
|
|
if ((local_38 & 0x20) != 0)
|
|
{
|
|
iVar18 = iVar19 >> 9;
|
|
|
|
if (0x300 < iVar14)
|
|
{
|
|
// driver is leaving skids
|
|
*(uint *)(param_2 + 0x2c8) = *(uint *)(param_2 + 0x2c8) | 0x800;
|
|
}
|
|
iVar16 = iVar6 >> 9;
|
|
if (*(short *)(param_2 + 0x39c) == 0) {
|
|
iVar5 = (int)*(short *)(param_2 + 0x454);
|
|
}
|
|
else
|
|
{
|
|
// speed
|
|
iVar6 = (int)*(short *)(param_2 + 0x38c);
|
|
|
|
if (iVar6 < 0) {
|
|
iVar6 = -iVar6;
|
|
}
|
|
|
|
// Map "speed" from
|
|
// - [0x300, characterSpeed]
|
|
// to
|
|
// - [const_modelRotVelMin, const_modelRotVelMax]
|
|
|
|
// Rotating the model to exaggerate the steering animation,
|
|
// only do this if driver speed is more than 0x300
|
|
iVar5 = FUN_80058f9c(iVar6,0x300,iVar11 >> 0x11,(int)*(short *)(param_2 + 0x454),iVar5);
|
|
}
|
|
}
|
|
|
|
// speed
|
|
iVar6 = (int)*(short *)(param_2 + 0x38c);
|
|
|
|
if (iVar6 < 0) {
|
|
iVar6 = -iVar6;
|
|
}
|
|
iVar19 = ((uint)*(byte *)(param_2 + 0x43a) + ((int)*(char *)(param_2 + 0x34) << 1) / 5) * 0x100;
|
|
|
|
// Map "speed" from
|
|
// - [turnResistMin*iVar6>>8(or9), turnResistMax*iVar6>>8(or9)]
|
|
// to
|
|
// - [turnResistMax*iVar6, 0]
|
|
|
|
// if iVar11 is zero, no turn-resist
|
|
// if iVar11 is 0x7FFF, high turn-resist
|
|
// this prevents you from steering sharp at low speeds
|
|
|
|
// get turn resistance, given speed, and range maps
|
|
iVar11 = FUN_80058f9c(iVar6,iVar16,iVar18,iVar19,0);
|
|
|
|
iVar6 = 0;
|
|
if (iVar16 <= iVar14) {
|
|
iVar15 = iVar9;
|
|
if (iVar9 < 0) {
|
|
iVar15 = -iVar9;
|
|
}
|
|
if (iVar11 < iVar15)
|
|
{
|
|
// fire speed
|
|
iVar6 = (int)*(short *)(param_2 + 0x39e);
|
|
if (iVar6 < 0) {
|
|
iVar6 = -iVar6;
|
|
}
|
|
|
|
// same input-range as the previous map
|
|
|
|
// Map "fire speed" from
|
|
// - [turnResistMin*iVar6>>8(or9), turnResistMax*iVar6>>8(or9)]
|
|
// to
|
|
// - [0, ???]
|
|
uVar7 = FUN_80058f9c(iVar6,iVar16,iVar18,0,iVar5);
|
|
|
|
// Map "rotation rate" from
|
|
// - [unk to unk]
|
|
// to
|
|
// - [0, mappedFireSpeed]
|
|
iVar6 = FUN_80058f9c(iVar15,iVar11,iVar19,0,uVar7);
|
|
|
|
// absolute value,
|
|
// then use this for LerpToForwards
|
|
if (iVar9 < 0) {
|
|
iVar6 = -iVar6;
|
|
}
|
|
}
|
|
}
|
|
sVar13 = *(short *)(param_2 + 0x3c6);
|
|
|
|
// VehPhysGeneral_LerpToForwards
|
|
sVar4 = FUN_80060488(param_2,(int)sVar13,(int)sVar4,iVar6);
|
|
*(short *)(param_2 + 0x3d2) = sVar4;
|
|
|
|
iVar6 = (int)sVar4;
|
|
|
|
// terrain related
|
|
if (*(int *)(iVar12 + 0x24) != 0x100) {
|
|
iVar6 = *(int *)(iVar12 + 0x24) * iVar6 >> 8;
|
|
}
|
|
|
|
iVar16 = (int)sVar13 + (iVar6 * iVar8 >> 5);
|
|
*(short *)(param_2 + 0x3c6) = (short)iVar16;
|
|
iVar11 = iVar9;
|
|
|
|
// if [???] && touching quadblock
|
|
if ((0x2ff < iVar14) && ((local_38 & 1) != 0))
|
|
{
|
|
// number of frames spent steering
|
|
sVar4 = *(short *)(param_2 + 0x3e6);
|
|
|
|
// VehCalc_SteerAccel
|
|
// all these offsets are MetaPhys, and each one is only used here
|
|
iVar18 = FUN_8005900c(
|
|
|
|
// frames spent steering
|
|
(int)sVar4,
|
|
|
|
// SteerAccel_Stage2_FirstFrame
|
|
(int)*(char *)(param_2 + 0x447),
|
|
|
|
// SteerAccel_Stage2_FrameLength
|
|
(int)*(char *)(param_2 + 0x448),
|
|
|
|
// SteerAccel_Stage4_FirstFrame
|
|
(int)*(char *)(param_2 + 0x446),
|
|
|
|
// SteerAccel_Stage1_MinSteer
|
|
(int)*(short *)(param_2 + 0x44c),
|
|
|
|
// SteerAccel_Stage1_MaxSteer
|
|
(int)*(short *)(param_2 + 0x44a)
|
|
);
|
|
|
|
if (iVar9 < 0) {
|
|
iVar11 = -iVar9;
|
|
}
|
|
|
|
// 0x44e is const val 0x80
|
|
iVar11 = *(short *)(param_2 + 0x44e) * iVar11 >> 8;
|
|
|
|
// increment frame counter
|
|
*(short *)(param_2 + 0x3e6) = sVar4 + 1;
|
|
|
|
// the higher the value of iVar18,
|
|
// the more steering is "locked up",
|
|
// try setting mov r3, xxxx at 80060170 for proof
|
|
|
|
if (iVar11 < iVar18) {
|
|
iVar18 = iVar11;
|
|
}
|
|
|
|
// steering left or right
|
|
if ((local_38 & 0x10) != 0) {
|
|
iVar18 = -iVar18;
|
|
}
|
|
|
|
// constant value zero, for all classes
|
|
iVar19 = (int)*(short *)(param_2 + 0x450);
|
|
|
|
if ((iVar9 < 1) || (iVar11 = -iVar19, iVar11 <= iVar9 + iVar18)) {
|
|
if (iVar9 < 0) {
|
|
iVar11 = iVar9 + iVar18;
|
|
if (iVar19 < iVar9 + iVar18) {
|
|
iVar11 = iVar19;
|
|
}
|
|
}
|
|
else {
|
|
iVar11 = iVar9 + iVar18;
|
|
}
|
|
}
|
|
}
|
|
iVar9 = (int)*(short *)(param_2 + 0x3d4);
|
|
sVar4 = *(short *)(param_2 + 0x3d8);
|
|
sVar13 = *(short *)(param_2 + 0x3d6);
|
|
|
|
// terrain related, and touching quadblock
|
|
if (((*(uint *)(iVar12 + 4) & 0x10) == 0) && ((local_38 & 1) != 0)) {
|
|
iVar18 = iVar16;
|
|
if (iVar16 < 0) {
|
|
iVar18 = -iVar16;
|
|
}
|
|
if (iVar5 * 3 >> 2 < iVar18) {
|
|
iVar5 = iVar6;
|
|
if (iVar6 < 0) {
|
|
iVar5 = -iVar6;
|
|
}
|
|
if (iVar5 < 3) {
|
|
iVar5 = iVar9;
|
|
if (iVar9 < 0) {
|
|
iVar5 = -iVar9;
|
|
}
|
|
if (iVar5 < 10) {
|
|
sVar4 = 8;
|
|
sVar13 = 0x14;
|
|
if (iVar16 < 0) {
|
|
sVar13 = -0x14;
|
|
}
|
|
}
|
|
}
|
|
goto LAB_80060284;
|
|
}
|
|
}
|
|
sVar4 = 0;
|
|
LAB_80060284:
|
|
iVar5 = iVar9;
|
|
if (iVar9 < 0) {
|
|
iVar5 = -iVar9;
|
|
}
|
|
if (0x32 < iVar5) {
|
|
sVar4 = 0;
|
|
}
|
|
if (sVar4 == 0) {
|
|
iVar5 = 10;
|
|
if (0 < iVar9) {
|
|
iVar5 = -10;
|
|
}
|
|
sVar13 = (short)iVar5;
|
|
if (iVar5 < 0) {
|
|
iVar5 = -iVar5;
|
|
}
|
|
|
|
// Interpolate rotation by speed
|
|
sVar17 = FUN_80058f54(iVar9,iVar5,0);
|
|
}
|
|
else {
|
|
sVar4 = sVar4 + -1;
|
|
sVar17 = *(short *)(param_2 + 0x3d4) + sVar13;
|
|
}
|
|
uVar10 = SEXT24(*(short *)(param_2 + 0x39a));
|
|
*(short *)(param_2 + 0x3d8) = sVar4;
|
|
*(short *)(param_2 + 0x3d4) = sVar17;
|
|
*(short *)(param_2 + 0x3d6) = sVar13;
|
|
|
|
// Map value from [oldMin, oldMax] to [newMin, newMax]
|
|
// inverting newMin and newMax will give an inverse range mapping
|
|
iVar5 = FUN_80058f9c(iVar14,0,0x600,iVar6,0);
|
|
iVar14 = iVar5 * iVar8 >> 5;
|
|
iVar5 = iVar14;
|
|
if (iVar14 < 0) {
|
|
iVar5 = -iVar14;
|
|
}
|
|
if (1 < iVar5) {
|
|
uVar10 = uVar10 - iVar14 & 0xfff;
|
|
}
|
|
*(undefined2 *)(param_2 + 0xc0) = (short)iVar11;
|
|
uVar10 = uVar10 + (iVar11 * iVar8 >> 0xd) & 0xfff;
|
|
sVar4 = (short)uVar10;
|
|
*(short *)(param_2 + 0x39a) = sVar4;
|
|
*(short *)(param_2 + 0x2ee) = sVar4 + (short)iVar16 + sVar17;
|
|
|
|
// if not holding break, and not mashing X
|
|
if (((local_38 & 8) == 0) && (*(short *)(param_2 + 0x3c2) < 7))
|
|
{
|
|
// terrain related
|
|
if (*(int *)(iVar12 + 0x14) != 0x100)
|
|
{
|
|
iVar11 = iVar11 * *(int *)(iVar12 + 0x14) >> 8;
|
|
}
|
|
}
|
|
|
|
// holding break, or mashing X
|
|
else {
|
|
iVar11 = iVar11 * 10 >> 8;
|
|
}
|
|
|
|
// axisRotationX
|
|
*(ushort *)(param_2 + 0x396) =
|
|
*(short *)(param_2 + 0x396) + (short)(iVar11 * iVar8 >> 0xd) & 0xfff;
|
|
|
|
// VehPhysForce_RotAxisAngle
|
|
FUN_8005f89c((undefined4 *)(param_2 + 0x310),param_2 + 0x360,uVar10);
|
|
gte_SetRotMatrix((MATRIX *)(param_2 + 0x310));
|
|
|
|
// VehPhysForce_AccelTerrainSlope
|
|
FUN_8005fb4c(param_2);
|
|
return;
|
|
}
|
|
|
|
|
|
// VehPhysGeneral_LerpQuarterStrength
|
|
int FUN_80060458(int param_1,int param_2)
|
|
|
|
{
|
|
// desired != 0
|
|
if (param_2 != 0)
|
|
{
|
|
// desired /= 4
|
|
param_2 = param_2 >> 2,
|
|
|
|
// if desired == 0
|
|
if (param_2 == 0)
|
|
{
|
|
// desired = 1
|
|
param_2 = 1;
|
|
}
|
|
}
|
|
|
|
// if current >= desired/4
|
|
if (param_2 <= param_1)
|
|
{
|
|
// current = desired/4
|
|
param_1 = param_2;
|
|
}
|
|
|
|
return param_1;
|
|
}
|
|
|
|
|
|
// VehPhysGeneral_LerpToForwards
|
|
// "return 0;" will make car stay in "drift steer" rotation,
|
|
// and not interpolate to rotate a forwards direction
|
|
int FUN_80060488(int param_1,int param_2,int param_3,int param_4)
|
|
|
|
{
|
|
bool bVar1;
|
|
uint uVar2;
|
|
int iVar3;
|
|
|
|
bVar1 = false;
|
|
*(undefined2 *)(param_1 + 0x3ca) = 0;
|
|
if ((param_4 < 0) || ((param_4 == 0 && (param_2 < 0)))) {
|
|
bVar1 = true;
|
|
param_2 = -param_2;
|
|
param_3 = -param_3;
|
|
param_4 = -param_4;
|
|
}
|
|
iVar3 = 0;
|
|
|
|
// if not rubbing on wall
|
|
if (*(short *)(param_1 + 0x3fe) != 0xf0)
|
|
{
|
|
if (param_4 < param_2) {
|
|
if (*(short *)(param_1 + 0x452) < param_2) {
|
|
uVar2 = (uint)*(byte *)(param_1 + 0x458) * 0xf;
|
|
}
|
|
else {
|
|
uVar2 = (uint)*(byte *)(param_1 + 0x458);
|
|
}
|
|
iVar3 = FUN_80060458(uVar2,param_2 - param_4,0);
|
|
iVar3 = -iVar3;
|
|
}
|
|
else {
|
|
if (param_2 < param_4) {
|
|
if (param_2 < 0) {
|
|
iVar3 = FUN_80060458((uint)*(byte *)(param_1 + 0x459),param_4 - param_2,0);
|
|
}
|
|
else {
|
|
iVar3 = FUN_80060458((uint)*(byte *)(param_1 + 0x457),param_4 - param_2,0);
|
|
*(undefined2 *)(param_1 + 0x3ca) = (short)param_4;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Interpolate rotation by speed
|
|
iVar3 = FUN_80058f54(param_3,(uint)*(byte *)(param_1 + 0x45a),iVar3);
|
|
if (bVar1) {
|
|
iVar3 = -iVar3;
|
|
}
|
|
return iVar3;
|
|
}
|
|
|
|
|
|
// VehPhysGeneral_JumpGetVelY
|
|
// param_1: normalVec (driver 0x360, 0x368, 0x378)
|
|
// param_2: speedCoord (driver 0x88)
|
|
// if "return 0;" then you jump off a ramp and get no height
|
|
int FUN_800605a0(short *param_1,int *param_2)
|
|
|
|
{
|
|
int iVar1;
|
|
int iVar2;
|
|
|
|
// y1 (normal vector Y)
|
|
iVar2 = (int)param_1[1];
|
|
|
|
iVar1 = iVar2;
|
|
if (iVar2 < 0) {
|
|
iVar1 = -iVar2;
|
|
}
|
|
|
|
if (0x14 < iVar1)
|
|
{
|
|
// this determines if you fly off a ramp or not,
|
|
// regardless if you press L1 or R1
|
|
|
|
// if quadblock is flat, normalvec x and z are zero,
|
|
// causing the multiply product to also be zero (no fly)
|
|
|
|
// if X points up, and you drive along the X,
|
|
// then you get a high number to fly off the ramp
|
|
|
|
iVar1 =
|
|
|
|
// x2 * x1
|
|
*param_2 * (int)*param_1 +
|
|
|
|
// z2 * z1
|
|
param_2[2] * (int)param_1[2];
|
|
|
|
// alert debugger on error
|
|
if (iVar2 == 0) trap(0x1c00);
|
|
if ((iVar2 == -1) && (iVar1 == -0x80000000)) trap(0x1800);
|
|
|
|
return iVar1 / iVar2;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
// VehPhysGeneral_JumpAndFriction
|
|
void FUN_80060630(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
bool bVar1;
|
|
int iVar2;
|
|
int iVar3;
|
|
int iVar4;
|
|
int iVar5;
|
|
short sVar6;
|
|
int iVar7;
|
|
short sVar8;
|
|
short sVar9;
|
|
int iVar10;
|
|
uint uVar11;
|
|
uint uVar12;
|
|
uint uVar13;
|
|
int local_28;
|
|
uint local_24;
|
|
int local_20;
|
|
|
|
// driver -> 0x310
|
|
gte_SetRotMatrix((MATRIX *)(param_2 + 0x310));
|
|
|
|
if (
|
|
(
|
|
// if driver is not drifting
|
|
(*(char *)(param_2 + 0x376) != '\x02') &&
|
|
|
|
//if driver is not using mask weapon
|
|
((*(uint *)(param_2 + 0x2c8) & 0x800000) == 0)
|
|
) &&
|
|
|
|
// no reserves
|
|
(*(short *)(param_2 + 0x3e2) == 0)
|
|
)
|
|
{
|
|
iVar7 = (int)((uint)*(ushort *)(param_2 + 0xc0) << 0x10) >> 0x18;
|
|
if (iVar7 < 0) {
|
|
iVar7 = -iVar7;
|
|
}
|
|
|
|
// Map value from [oldMin, oldMax] to [newMin, newMax]
|
|
// inverting newMin and newMax will give an inverse range mapping
|
|
iVar2 = FUN_80058f9c(iVar7,0,(uint)*(byte *)(param_2 + 0x43b),0,(int)*(short *)(param_2 + 0x43c)
|
|
);
|
|
iVar10 = (int)*(short *)(param_2 + 0x39c);
|
|
iVar7 = iVar10;
|
|
if (iVar10 < 0) {
|
|
iVar7 = -iVar10;
|
|
}
|
|
sVar6 = (short)iVar2;
|
|
if (iVar7 < iVar2) {
|
|
sVar6 = (short)iVar7;
|
|
}
|
|
sVar8 = -sVar6;
|
|
if (iVar10 < 0) {
|
|
sVar8 = sVar6;
|
|
}
|
|
*(short *)(param_2 + 0x39c) = *(short *)(param_2 + 0x39c) + sVar8;
|
|
}
|
|
|
|
// if rubbing on wall now, or recenlty
|
|
if (*(short *)(param_2 + 0x3fe) != 0)
|
|
{
|
|
if (*(short *)(param_2 + 0x38a) < *(short *)(param_2 + 0x39c)) {
|
|
*(undefined2 *)(param_2 + 0x39c) = *(undefined2 *)(param_2 + 0x38a);
|
|
}
|
|
if ((int)*(short *)(param_2 + 0x39c) < -(int)*(short *)(param_2 + 0x38a)) {
|
|
*(short *)(param_2 + 0x39c) = -*(short *)(param_2 + 0x38a);
|
|
}
|
|
}
|
|
local_28 = *(int *)(param_2 + 0x88);
|
|
local_24 = *(uint *)(param_2 + 0x8c);
|
|
local_20 = *(int *)(param_2 + 0x90);
|
|
uVar13 = 0;
|
|
iVar7 = 0;
|
|
|
|
// if driver is not on quadblock, or if not forced to jump (via GOTO)
|
|
if ((*(uint *)(param_2 + 0x2c8) & 1) == 0) {
|
|
LAB_80060ab0:
|
|
|
|
if (
|
|
// If you want to fire a weapon
|
|
((*(uint *)(param_2 + 0x2c8) & 0x8000) != 0) &&
|
|
|
|
// If that weapon is a spring
|
|
(*(char *)(param_2 + 0x36) == '\x05')
|
|
)
|
|
{
|
|
// Remove the request to fire a weapon, since we will use it now
|
|
*(uint *)(param_2 + 0x2c8) = *(uint *)(param_2 + 0x2c8) & 0xffff7fff;
|
|
|
|
// if coyoteTimerMS has not expired, and cooldownMS is over
|
|
if ((*(short *)(param_2 + 0x3f4) != 0) && (*(short *)(param_2 + 0x3f2) == 0))
|
|
{
|
|
// driver is now forced to jump
|
|
*(undefined2 *)(param_2 + 0x3f6) = 0xa0;
|
|
|
|
// const_Jump * 9
|
|
iVar7 = (int)*(short *)(param_2 + 0x418) * 9;
|
|
|
|
// always true
|
|
if (iVar7 < 0)
|
|
{
|
|
// add 3
|
|
iVar7 = iVar7 + 3;
|
|
}
|
|
|
|
// jump_InitialVelY = big jump from spring
|
|
*(undefined2 *)(param_2 + 0x3f8) = (short)(iVar7 >> 2);
|
|
|
|
// OtherFX_Play_Echo
|
|
// spring weapon sound
|
|
FUN_80028494(9,1,(uint)*(ushort *)(param_2 + 0x2ca) & 1);
|
|
|
|
*(undefined2 *)(param_2 + 0x3fa) = 0x180;
|
|
goto LAB_80060c30;
|
|
}
|
|
*(undefined2 *)(param_2 + 0x3c) = 0;
|
|
}
|
|
|
|
// if not being forced to jump (turtles), this should cause the tiny jumps on top of walls.
|
|
if (*(char *)(param_2 + 0x366) == '\0')
|
|
{
|
|
if (
|
|
(
|
|
// if driver left quadblock more than 0.16s ago
|
|
(*(short *)(param_2 + 0x3f4) == 0) ||
|
|
|
|
// if haven't jumped in last 10 frames
|
|
(*(short *)(param_2 + 0x3f0) == 0)
|
|
) ||
|
|
|
|
// jump_CooldownMS not over (so can't jump again)
|
|
(*(short *)(param_2 + 0x3f2) != 0)
|
|
)
|
|
{
|
|
if (
|
|
(
|
|
// if player is touching ground
|
|
((*(uint *)(param_2 + 0x2c8) & 1) != 0) &&
|
|
|
|
// if player is over a quadblock
|
|
(*(int *)(param_2 + 0x350) != 0)
|
|
) &&
|
|
(
|
|
// unknown quadblock variable
|
|
iVar7 = (int)*(char *)(*(int *)(param_2 + 0x350) + 0x3b),
|
|
iVar7 != 0
|
|
)
|
|
)
|
|
{
|
|
// player speed
|
|
iVar2 = (int)*(short *)(param_2 + 0x38e);
|
|
if (iVar2 < 0) { // change sign of player speed
|
|
iVar2 = -iVar2;
|
|
}
|
|
|
|
gte_ldVXY0((iVar7 * iVar2 >> 8) << 0x10);
|
|
gte_ldVZ0(0);
|
|
gte_rtv0();
|
|
read_mt(iVar7,iVar2,iVar10);
|
|
|
|
local_28 = local_28 + iVar7;
|
|
local_20 = local_20 + iVar10;
|
|
local_24 = local_24 + iVar2;
|
|
}
|
|
goto LAB_80060e1c;
|
|
}
|
|
|
|
// implied "else",
|
|
// if (jump_cooldownMS is over) &&
|
|
// (haven't left quadblock || no jump in over 10 frames)
|
|
|
|
// force driver to jump
|
|
*(undefined2 *)(param_2 + 0x3f6) = 0xa0;
|
|
|
|
// increment jump counter
|
|
*(short *)(param_2 + 0x554) = *(short *)(param_2 + 0x554) + 1;
|
|
|
|
// jump_InitialVelY = const_Jump
|
|
*(undefined2 *)(param_2 + 0x3f8) = *(undefined2 *)(param_2 + 0x418);
|
|
|
|
// OtherFX_Play_Echo
|
|
// play jump sound
|
|
FUN_80028494(8,1,(uint)*(ushort *)(param_2 + 0x2ca) & 1);
|
|
}
|
|
|
|
// if being forced to jump (by turtles)
|
|
else
|
|
{
|
|
// if first frame (basically)
|
|
if (
|
|
// if not currently airborne from forced jump
|
|
(*(short *)(param_2 + 0x3f6) == 0) ||
|
|
|
|
// if jump_InitialVelY was just now set to const_jump
|
|
(*(short *)(param_2 + 0x3f8) == *(short *)(param_2 + 0x418)))
|
|
{
|
|
// OtherFX_Play
|
|
FUN_80028468(0x7e,1);
|
|
}
|
|
|
|
// currently forced airborne
|
|
*(undefined2 *)(param_2 + 0x3f6) = 0xa0;
|
|
|
|
// if big force jump (turtles)
|
|
if (*(char *)(param_2 + 0x366) == '\x02')
|
|
{
|
|
*(undefined2 *)(param_2 + 0x3fa) = 0x180;
|
|
|
|
// const_Jump * 3
|
|
*(short *)(param_2 + 0x3f8) = *(short *)(param_2 + 0x418) * 3;
|
|
}
|
|
|
|
// if small force jump (turtles)
|
|
else
|
|
{
|
|
// jump_InitialVelY = const_Jump * 1.5
|
|
*(undefined2 *)(param_2 + 0x3f8) = (short)(((int)*(short *)(param_2 + 0x418) * 3) / 2);
|
|
}
|
|
|
|
// remove force jump (turtles)
|
|
*(undefined *)(param_2 + 0x366) = 0;
|
|
}
|
|
}
|
|
|
|
// if driver is on a quadblock
|
|
else
|
|
{
|
|
if (
|
|
// if driver is not on any turbo pad
|
|
((*(uint *)(param_2 + 0xbc) & 3) == 0) ||
|
|
|
|
(*(short *)(param_2 + 0x39c) < 1)
|
|
)
|
|
{
|
|
if (*(short *)(param_2 + 0x39c) != 0)
|
|
{
|
|
// terrain related
|
|
if ((((*(uint *)(*(int *)(param_2 + 0x358) + 4) & 4) == 0) ||
|
|
(*(short *)(param_2 + 0x39c) < 1)) || (-1 < *(short *)(param_2 + 0x38e)))
|
|
{
|
|
iVar10 = (int)*(short *)(param_2 + 0x38e);
|
|
iVar2 = iVar10;
|
|
if (iVar10 < 0) {
|
|
iVar2 = -iVar10;
|
|
}
|
|
if (((0x2ff < iVar2) && ((*(short *)(param_2 + 0x39c) < 1 || (iVar10 < 1)))) &&
|
|
((-1 < *(short *)(param_2 + 0x39c) || (-1 < iVar10)))) goto LAB_800608fc;
|
|
}
|
|
|
|
// const_accel_noReserves + driver-specific acceleration
|
|
iVar7 = (int)*(short *)(param_2 + 0x428) + ((int)*(char *)(param_2 + 0x33) << 5) / 5;
|
|
|
|
// if you're not on any turbo pad
|
|
if ((*(uint *)(param_2 + 0xbc) & 3) == 0)
|
|
{
|
|
if (
|
|
// if reserves are not zero
|
|
(*(short *)(param_2 + 0x3e2) != 0) &&
|
|
|
|
(0 < *(short *)(param_2 + 0x39c))
|
|
)
|
|
{
|
|
// const_Accel_Reserves
|
|
iVar7 = (int)*(short *)(param_2 + 0x42a);
|
|
}
|
|
|
|
// driver -> terrain meta -> slowUntilSpeed,
|
|
// if 0, driver will slow down until completely stuck
|
|
iVar2 = *(int *)(*(int *)(param_2 + 0x358) + 0xc);
|
|
|
|
if (
|
|
(iVar2 != 0x100) &&
|
|
|
|
// if driver is not using mask weapon
|
|
((*(uint *)(param_2 + 0x2c8) & 0x800000) == 0)
|
|
)
|
|
{
|
|
iVar7 = iVar2 * iVar7 >> 8;
|
|
}
|
|
}
|
|
else {
|
|
if (0 < *(short *)(param_2 + 0x39c)) goto LAB_8006089c;
|
|
}
|
|
}
|
|
}
|
|
|
|
// if driver is on a turbo pad
|
|
else
|
|
{
|
|
LAB_8006089c:
|
|
|
|
// high acceleration
|
|
iVar7 = 8000;
|
|
}
|
|
LAB_800608fc:
|
|
// elapsed milliseconds per frame, ~32
|
|
uVar11 = iVar7 * *(int *)(PTR_DAT_8008d2ac + 0x1d04) >> 5;
|
|
|
|
gte_ldVXY0(0);
|
|
gte_ldVZ0(uVar11 & 0xffff);
|
|
gte_rtv0();
|
|
read_mt(sVar6,sVar8,sVar9);
|
|
|
|
if (*(short *)(param_2 + 0x39c) < 0) {
|
|
*(short *)(param_2 + 0x3b2) = -(short)uVar11;
|
|
iVar7 = -iVar7;
|
|
iVar2 = -iVar2;
|
|
iVar10 = -iVar10;
|
|
*(short *)(param_2 + 0x3ac) = -sVar6;
|
|
*(short *)(param_2 + 0x3ae) = -sVar8;
|
|
*(short *)(param_2 + 0x3b0) = -sVar9;
|
|
}
|
|
else {
|
|
*(short *)(param_2 + 0x3b2) = (short)uVar11;
|
|
*(short *)(param_2 + 0x3ac) = sVar6;
|
|
*(short *)(param_2 + 0x3ae) = sVar8;
|
|
*(short *)(param_2 + 0x3b0) = sVar9;
|
|
}
|
|
local_20 = local_20 + iVar2;
|
|
local_24 = local_24 + iVar10;
|
|
local_28 = local_28 + iVar7;
|
|
|
|
// uVar13 = sqrt(x2+y2+z2 << 0x10)
|
|
uVar13 = FUN_80059070(local_28 * local_28 + local_24 * local_24 + local_20 * local_20,0x10);
|
|
|
|
iVar7 = (int)*(short *)(param_2 + 0x39c);
|
|
if (iVar7 < 0) {
|
|
iVar7 = -iVar7;
|
|
}
|
|
uVar13 = (uVar13 >> 8) - iVar7;
|
|
bVar1 = (int)uVar11 < (int)uVar13;
|
|
if ((int)uVar13 < 0) {
|
|
uVar13 = 0;
|
|
bVar1 = (int)uVar11 < 0;
|
|
}
|
|
if (bVar1) {
|
|
uVar13 = uVar11;
|
|
}
|
|
|
|
// if not on quadblock, or if not forced to jump
|
|
if (((*(uint *)(param_2 + 0x2c8) & 1) == 0) || (*(short *)(param_2 + 0x3f6) == 0))
|
|
goto LAB_80060ab0;
|
|
|
|
if (*(short *)(param_2 + 0x3fa) != 0) {
|
|
*(undefined2 *)(param_2 + 0x3fa) = 0x180;
|
|
}
|
|
|
|
// If you're "blasted", flipping around after hit by missile, bomb, etc
|
|
if (*(char *)(param_2 + 0x376) == '\x06')
|
|
{
|
|
// GAMEPAD_ShockFreq and GAMEPAD_ShockForce1
|
|
FUN_80026440(param_2,8,0);
|
|
FUN_800264c0(param_2,8,0x7f);
|
|
}
|
|
}
|
|
LAB_80060c30:
|
|
iVar7 = 0;
|
|
iVar10 = 0x378;
|
|
|
|
// jump timer
|
|
*(undefined2 *)(param_2 + 0x3f2) = 0x180;
|
|
|
|
*(undefined2 *)(param_2 + 0x3f0) = 0;
|
|
*(uint *)(param_2 + 0x2c8) = *(uint *)(param_2 + 0x2c8) | 0x480;
|
|
|
|
// this loop has one iteration
|
|
iVar2 = iVar7;
|
|
do
|
|
{
|
|
// Driver_RampVelY
|
|
iVar3 = FUN_800605a0(param_2 + iVar10,&local_28);
|
|
|
|
iVar5 = iVar3;
|
|
if (iVar3 < 0) {
|
|
iVar5 = -iVar3;
|
|
}
|
|
iVar4 = iVar7;
|
|
if (iVar7 < 0) {
|
|
iVar4 = -iVar7;
|
|
}
|
|
if (iVar4 < iVar5) {
|
|
iVar7 = iVar3;
|
|
}
|
|
iVar2 = iVar2 + 1;
|
|
iVar10 = iVar10 + 8;
|
|
} while (iVar2 < 1);
|
|
|
|
iVar2 = param_2 + 0x360;
|
|
if ((*(uint *)(param_2 + 0x2c8) & 1) == 0) {
|
|
iVar2 = param_2 + 0x368;
|
|
}
|
|
|
|
// Driver_RampVelY
|
|
iVar10 = FUN_800605a0(iVar2,&local_28);
|
|
|
|
iVar2 = iVar10;
|
|
if (iVar10 < 0) {
|
|
iVar2 = -iVar10;
|
|
}
|
|
iVar5 = iVar7;
|
|
if (iVar7 < 0) {
|
|
iVar5 = -iVar7;
|
|
}
|
|
iVar3 = iVar7 * iVar7;
|
|
if (iVar5 < iVar2) {
|
|
iVar3 = iVar10 * iVar10;
|
|
iVar7 = iVar10;
|
|
}
|
|
|
|
// iVar2 = sqrt( (ramp+jump*jump>>8) << 8),
|
|
// iVar2 = sqrt( "basically" ramp+jump*jump )
|
|
// last byte is cleared cause only 3 bytes in driver->0x2D4
|
|
// are rendered, and the last byte is sub-pixel percision
|
|
|
|
// iVar2 = sqrt(ramp+jump*jump)
|
|
iVar2 = FUN_80059070(
|
|
// param_1
|
|
iVar3 +
|
|
(int)*(short *)(param_2 + 0x3f8) *
|
|
(int)*(short *)(param_2 + 0x3f8) >> 8,
|
|
|
|
// param_2
|
|
8);
|
|
|
|
// zero in all arcade maps, idk adv, battle, cutscene, or credits
|
|
uVar11 = (uint)*(byte *)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0x18c) << 8;
|
|
|
|
if (*(byte *)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0x18c) == 0)
|
|
{
|
|
uVar11 = 0x3700;
|
|
}
|
|
else
|
|
{
|
|
if (0x5000 < uVar11)
|
|
{
|
|
uVar11 = 0x5000;
|
|
}
|
|
}
|
|
|
|
uVar12 = iVar2 - iVar7;
|
|
if ((int)uVar11 < iVar2 - iVar7) {
|
|
uVar12 = uVar11;
|
|
}
|
|
|
|
// max value for movementY (on stack)
|
|
if ((int)local_24 < (int)uVar12)
|
|
{
|
|
// set movementY to the speed that
|
|
// you should have, on first frame of jump
|
|
local_24 = uVar12;
|
|
}
|
|
|
|
// [end of the first frame of jump]
|
|
|
|
// skip here if not jumping
|
|
LAB_80060e1c:
|
|
|
|
// VehPhysCrash_ConvertVecToSpeed
|
|
FUN_8005cd1c(param_2,&local_28,0);
|
|
|
|
// decrease speed
|
|
iVar7 = *(ushort *)(param_2 + 0x38c) - uVar13;
|
|
*(undefined2 *)(param_2 + 0x38c) = (short)iVar7;
|
|
if (iVar7 * 0x10000 < 0) {
|
|
*(undefined2 *)(param_2 + 0x38c) = 0;
|
|
}
|
|
|
|
iVar7 = (int)*(short *)(param_2 + 0x38e);
|
|
|
|
if (iVar7 < 0) {
|
|
if (iVar7 < 0) {
|
|
iVar7 = -iVar7;
|
|
}
|
|
if (iVar7 < 0x100) {
|
|
sVar6 = *(short *)(param_2 + 0x36e) - (*(short *)(param_2 + 0x36e) >> 3);
|
|
}
|
|
else {
|
|
sVar6 = (short)((int)*(short *)(param_2 + 0x36e) * 0xd +
|
|
(*(uint *)(PTR_DAT_8008d2ac + 0x1cec) & 7) * 0x300 >> 4);
|
|
}
|
|
}
|
|
else {
|
|
sVar6 = (short)((int)*(short *)(param_2 + 0x36e) * 0xd + iVar7 * 3 >> 4);
|
|
}
|
|
*(short *)(param_2 + 0x36e) = sVar6;
|
|
return;
|
|
}
|
|
|
|
|
|
// VehPhysGeneral_SetHeldItem
|
|
void FUN_80060f0c(int param_1)
|
|
{
|
|
char cVar1;
|
|
int iVar2;
|
|
uint uVar3;
|
|
int iVar4;
|
|
|
|
// refer to chart
|
|
// https://media.discordapp.net/attachments/637616020177289236/982513721354092564/unknown.png?width=602&height=431
|
|
|
|
//iVar4 = Place division
|
|
iVar4 = -1;
|
|
|
|
// If you're not in Battle Mode
|
|
if ((*(uint *)PTR_DAT_8008d2ac & 0x20) == 0) {
|
|
// If you're not in Crystal Challenge (in adventure mode)
|
|
if ((*(uint *)PTR_DAT_8008d2ac & 0x8000000) == 0) {
|
|
// number of Drivers + number of AIs
|
|
switch((uint)(byte)PTR_DAT_8008d2ac[0x1ca8] + (uint)(byte)PTR_DAT_8008d2ac[0x1cab]) {
|
|
// 2P VS
|
|
// 1P Boss Race
|
|
case 2:
|
|
//if racer is 2nd, give 7th Place division
|
|
iVar4 = 7;
|
|
|
|
//if racer is 1st, give 1st Place division
|
|
if (*(short *)(param_1 + 0x482) == 0) {
|
|
LAB_80061060:
|
|
iVar4 = 0;
|
|
}
|
|
break;
|
|
|
|
// 3P Splitscreen
|
|
// 3 Players
|
|
case 3:
|
|
//if driver is 1st, give 1st Place division
|
|
if (*(short *)(param_1 + 0x482) == 0) goto LAB_80061060;
|
|
|
|
//if driver is 3rd, give 4th Place division
|
|
iVar4 = 3;
|
|
|
|
//if driver is 2nd, give 2nd or 3rd Place division (~50% chance)
|
|
if (*(short *)(param_1 + 0x482) == 1) {
|
|
//iVar4 = 3rd Place division
|
|
iVar4 = 2;
|
|
|
|
//Get random number to decide Place division
|
|
uVar3 = FUN_8003ea28();
|
|
|
|
//if the number is odd (~50% chance)
|
|
if ((uVar3 & 1) != 0)
|
|
{
|
|
//iVar4 = 2nd Place division
|
|
goto LAB_80061040;
|
|
}
|
|
}
|
|
break;
|
|
|
|
// 4P Splitscreen
|
|
// 4 Players
|
|
case 4:
|
|
//give (place in race)th Place division
|
|
iVar4 = (int)*(short *)(param_1 + 0x482);
|
|
break;
|
|
|
|
// Purple Gem Cup
|
|
// 1 player, 4 AIs
|
|
case 5:
|
|
//give (place in race)th Place division
|
|
iVar4 = (int)*(short *)(param_1 + 0x482);
|
|
|
|
//if racer is 5th
|
|
if (iVar4 == 4) {
|
|
//make 5th count in 4th Place division
|
|
iVar4 = 3;
|
|
}
|
|
break;
|
|
|
|
// 2P Splitscreen
|
|
// 2 players, 4 AIs
|
|
case 6:
|
|
//give (place in race)th Place division
|
|
iVar4 = (int)*(short *)(param_1 + 0x482);
|
|
|
|
//if racer is in 1st place, give 1st Place division
|
|
if (iVar4 == 0) goto LAB_80061060;
|
|
|
|
//if racer is 6th
|
|
if (iVar4 == 5) {
|
|
//make it count in 4th Place division
|
|
iVar4 = 3;
|
|
}
|
|
// if racer is not 1st or 6th
|
|
else {
|
|
//give Place division 2nd / 3rd
|
|
iVar4 = (iVar4 + -1) / 2 + 1;
|
|
}
|
|
break;
|
|
|
|
// 1P Arcade, Adventure
|
|
// 1 player, 7 AIs
|
|
case 8:
|
|
//iVar2 = place in race * 0x10000
|
|
iVar2 = (uint)*(ushort *)(param_1 + 0x482) << 0x10;
|
|
//iVar4 = place in race
|
|
iVar4 = iVar2 >> 0x10;
|
|
//if racer is second
|
|
if (iVar4 == 1) {
|
|
LAB_80061040:
|
|
//give 2nd Place division
|
|
iVar4 = 1;
|
|
}
|
|
else {
|
|
//give Place division 1st to 4th
|
|
iVar4 = iVar4 - (iVar2 >> 0x1f) >> 1;
|
|
}
|
|
}
|
|
}
|
|
// if you are in Crystal Challenge
|
|
else {
|
|
iVar4 = 6;
|
|
}
|
|
}
|
|
// If you are in Battle Mode
|
|
else
|
|
{
|
|
// battle, custom weapon set
|
|
iVar4 = 5;
|
|
|
|
// battle, default set
|
|
if (*(int *)(PTR_DAT_8008d2ac + 0x1da0) == 0x34de) {
|
|
iVar4 = 4;
|
|
}
|
|
}
|
|
|
|
//simulate you're in 3rd Place division instead of 4th in first lap
|
|
if ((iVar4 == 3) && (*(char *)(param_1 + 0x44) == '\0')) {
|
|
iVar4 = 2;
|
|
}
|
|
|
|
// Get random number to decide item
|
|
iVar2 = FUN_8003ea28();
|
|
// Reduce random number to a range of 0 - 199
|
|
uVar3 = (iVar2 >> 3) % 200;
|
|
|
|
//based on Place division and a 1-200 number, give item
|
|
switch(iVar4)
|
|
{
|
|
|
|
//if you're in 1st Place division
|
|
case 0:
|
|
// weapon = RNG/10 (range of 0 - 19)
|
|
*(undefined *)(param_1 + 0x36) = (&DAT_80089b6c)[uVar3 / 10];
|
|
break;
|
|
|
|
//if you're in 2nd Place division
|
|
case 1:
|
|
// weapon = (range of 0 - 52)
|
|
*(undefined *)(param_1 + 0x36) = (&DAT_80089b80)[(uVar3 * 0x34) / 200];
|
|
break;
|
|
|
|
//if you're in 3rd Place division
|
|
case 2:
|
|
// weapon = RNG/10 (range of 0 - 19)
|
|
*(undefined *)(param_1 + 0x36) = (&DAT_80089bb4)[uVar3 / 10];
|
|
break;
|
|
|
|
//if you're in 4th Place division (last place: arcade, VS, not Boss, etc)
|
|
case 3:
|
|
// weapon = (range of 0 - 18)
|
|
*(undefined *)(param_1 + 0x36) = (&DAT_80089bc8)[(uVar3 * 0x13) / 200];
|
|
break;
|
|
|
|
// Battle, default set
|
|
case 4:
|
|
// weapon = RNG/10 (range of 0 - 19)
|
|
*(undefined *)(param_1 + 0x36) = (&DAT_80089bf0)[uVar3 / 10];
|
|
break;
|
|
|
|
// Battle, custom set
|
|
case 5:
|
|
// weapon = RNG out of custom (int) array
|
|
*(undefined *)(param_1 + 0x36) =
|
|
PTR_DAT_8008d2ac[((int)(uVar3 * *(int *)(PTR_DAT_8008d2ac + 0x1df0)) / 200) * 4 + 0x1df4];
|
|
break;
|
|
|
|
// If you are in Crystal Challenge
|
|
case 6:
|
|
// Only true at Rocky Road and Nitro Court
|
|
if (
|
|
// if Level ID is not 21 (Skull Rock)
|
|
(*(int *)(PTR_DAT_8008d2ac + 0x1a10) != 0x15) &&
|
|
(
|
|
// Item = Bomb
|
|
cVar1 = '\x01',
|
|
// if Level ID is not 19 (Rampage Ruins)
|
|
*(int *)(PTR_DAT_8008d2ac + 0x1a10) != 0x13
|
|
)
|
|
) goto LAB_800612c4;
|
|
// Only true at Skull Rock and Rampage Ruins
|
|
//set held Item to Turbo
|
|
*(undefined *)(param_1 + 0x36) = 0;
|
|
break;
|
|
|
|
//if racer is 2nd in a 2 racer race
|
|
//7th Place division
|
|
case 7:
|
|
*(undefined *)(param_1 + 0x36) = (&DAT_80089bdc)[uVar3 / 10];
|
|
break;
|
|
|
|
//-1st Place division (place in race is 0xFFFF when not decided)
|
|
default:
|
|
// Get random number
|
|
iVar4 = FUN_8003ea28();
|
|
// Pick a random Item
|
|
cVar1 = (char)iVar4 + ((char)(iVar4 / 6 + (iVar4 >> 0x1f) >> 1) - (char)(iVar4 >> 0x1f)) * -0xc;
|
|
LAB_800612c4:
|
|
// Give racer said Item
|
|
*(char *)(param_1 + 0x36) = cVar1;
|
|
}
|
|
|
|
// If you're in a Boss Race
|
|
// 0x80000000
|
|
if (*(int *)PTR_DAT_8008d2ac < 0)
|
|
{
|
|
//cVar1 = Times lost against boss
|
|
cVar1 = (&DAT_8008fbeb)[*(int *)(PTR_DAT_8008d2ac + 0x1eb8)];
|
|
|
|
if (cVar1 < '\x03')
|
|
{
|
|
//if Held item is Mask, Clock or Warpball
|
|
if ((uint)*(byte *)(param_1 + 0x36) - 7 < 3)
|
|
{
|
|
//replace Held item with 3 Missiles
|
|
*(undefined *)(param_1 + 0x36) = 0xb;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (cVar1 < '\x04')
|
|
{
|
|
//if Held item is Mask or Clock
|
|
if ((uint)*(byte *)(param_1 + 0x36) - 7 < 2)
|
|
{
|
|
//replace Held item with 3 Missiles
|
|
*(undefined *)(param_1 + 0x36) = 0xb;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (
|
|
(cVar1 < '\x05') &&
|
|
//if Held item is Clock (\b = Backspace, 0x8 in ASCII)
|
|
(*(char *)(param_1 + 0x36) == '\b')
|
|
)
|
|
{
|
|
//replace Held item with 3 Missiles
|
|
*(undefined *)(param_1 + 0x36) = 0xb;
|
|
}
|
|
}
|
|
}
|
|
|
|
// If Level ID is 1
|
|
// If you're at Dragon Mines
|
|
if (*(int *)(PTR_DAT_8008d2ac + 0x1a10) == 1)
|
|
{
|
|
// Get your current Item
|
|
cVar1 = *(char *)(param_1 + 0x36);
|
|
|
|
//if Held item is not 3 Missiles
|
|
//skip next 2 lines of code
|
|
if (cVar1 != '\v') goto LAB_800613a4;
|
|
//if Held item is 3 Missiles
|
|
//replace it with 1 Missile
|
|
*(undefined *)(param_1 + 0x36) = 2;
|
|
}
|
|
}
|
|
|
|
// Get your current Item
|
|
cVar1 = *(char *)(param_1 + 0x36);
|
|
LAB_800613a4:
|
|
|
|
// If Item ID is unused Spring powerup
|
|
if (cVar1 == '\x05')
|
|
{
|
|
// Change Item to Turbo
|
|
*(undefined *)(param_1 + 0x36) = 0;
|
|
}
|
|
|
|
// if Item is warpball
|
|
// Make sure Warpball is only used once per race
|
|
if (*(char *)(param_1 + 0x36) == '\t')
|
|
{
|
|
//if 13th flag of 0x96B20 is off (means there isn't a warpball held / waddling around)
|
|
if ((*(uint *)PTR_DAT_8008d2ac & 0x1000) == 0)
|
|
{
|
|
//turn 13th flag of 0x96B20 on (means warpball is active)
|
|
*(uint *)PTR_DAT_8008d2ac = *(uint *)PTR_DAT_8008d2ac | 0x1000;
|
|
}
|
|
// if warpball is held or waddling around
|
|
else
|
|
{
|
|
//change Item to 3 missiles to prevent having two warpballs waddling around at once
|
|
*(undefined *)(param_1 + 0x36) = 0xb;
|
|
}
|
|
}
|
|
|
|
// To prevent having too many missiles,
|
|
// If you are in 3P or 4P mode, make it
|
|
// so a maximum of 2 players can have
|
|
// multiple missiles, during "normal race"
|
|
|
|
if (
|
|
(
|
|
// If numPlyrCurrGame is more than 2 and
|
|
(2 < (byte)PTR_DAT_8008d2ac[0x1ca8]) &&
|
|
|
|
// you're not in Battle Mode, and
|
|
((*(uint *)PTR_DAT_8008d2ac & 0x20) == 0)
|
|
) &&
|
|
// racer has 3 missiles
|
|
(*(char *)(param_1 + 0x36) == '\v')
|
|
)
|
|
{
|
|
// If there aren't already 2 players with 3 missiles
|
|
if (*(int *)(PTR_DAT_8008d2ac + 0x1ec4) < 2)
|
|
{
|
|
// increment number of players with 3 missiles
|
|
*(int *)(PTR_DAT_8008d2ac + 0x1ec4) = *(int *)(PTR_DAT_8008d2ac + 0x1ec4) + 1;
|
|
}
|
|
|
|
// if 2 players already have 3 missiles
|
|
else
|
|
{
|
|
// Change Item to one missile
|
|
*(undefined *)(param_1 + 0x36) = 2;
|
|
}
|
|
}
|
|
|
|
//if Held item is either 3 Bombs or 3 Missiles
|
|
//- 10 < 2 is intended in the formula because unsigned negatives are not < 2
|
|
//(Items available excluding Invisibility and Super Engine)
|
|
if ((uint)*(byte *)(param_1 + 0x36) - 10 < 2) {
|
|
//set Held item Quantity to 3
|
|
*(undefined *)(param_1 + 0x37) = 3;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
// VehPhysGeneral_GetBaseSpeed
|
|
int FUN_80061488(int param_1)
|
|
{
|
|
int iVar1;
|
|
int iVar2;
|
|
int iVar3;
|
|
int iVar4;
|
|
|
|
//iVar3 = Wumpa count, assume max of 9
|
|
iVar3 = (int)*(char *)(param_1 + 0x30);
|
|
if (9 < iVar3) {
|
|
iVar3 = 9;
|
|
}
|
|
|
|
// Turbo multiplier, limit to 5,
|
|
// part of Super Engine from beta builds
|
|
// still used?
|
|
iVar4 = (int)*(char *)(param_1 + 0x35);
|
|
if (5 < iVar4) {
|
|
iVar4 = 5;
|
|
}
|
|
|
|
//iVar2 = Character's Speed stat
|
|
iVar2 = (int)*(short *)(param_1 + 0x42c);
|
|
|
|
//iVar1 = Net Speed stat
|
|
//iVar1 = (((Negative Speedometer offset - Character's Speed stat) * 0x1000) / 5) - 1
|
|
iVar1 = ((*(short *)(param_1 + 0x42e) - iVar2) * 0x1000) / 5 + -1;
|
|
|
|
//iVar3 = Speed Additional
|
|
//iVar3 = ((Wumpa count * Net Speed stat) / 10) + (Speed multiplier * Net Speed stat) >> 0xC
|
|
iVar3 = (iVar3 * iVar1) / 10 + iVar4 * iVar1 >> 0xc;
|
|
|
|
//if racer is using mask weapon
|
|
if ((*(uint *)(param_1 + 0x2c8) & 0x800000) != 0) {
|
|
//add Mask speed Constant to Speed Additional
|
|
iVar3 = iVar3 + *(short *)(param_1 + 0x436);
|
|
}
|
|
|
|
//if racer has reserves
|
|
if (*(short *)(param_1 + 0x3e2) != 0) {
|
|
//iVar4 = Net Speed cap
|
|
//iVar4 = (Sacred fire Cap * 2 - Single turbo Cap) - Current Speed cap
|
|
iVar4 = ((int)*(short *)(param_1 + 0x432) * 2 - (int)*(short *)(param_1 + 0x430)) -
|
|
(int)*(short *)(param_1 + 0x3e4);
|
|
|
|
//iVar2 = Stat Additional
|
|
//iVar2 = Gross Speed stat + Current Speed cap
|
|
iVar2 = iVar2 + (int)*(short *)(param_1 + 0x3e4);
|
|
|
|
//prevent Net Speed cap from going negative
|
|
if (iVar4 < 0) {
|
|
iVar4 = 0;
|
|
}
|
|
|
|
//prevent Speed from going above Speed cap
|
|
//if Speed Additional > Net Speed cap
|
|
if (iVar4 < iVar3) {
|
|
//Speed Additional = Net Speed cap
|
|
iVar3 = iVar4;
|
|
}
|
|
}
|
|
//iVar4 is not Net Speed cap anymore
|
|
//iVar4 will now be some form of Damaged speed Constant
|
|
iVar4 = 0;
|
|
|
|
//if racer has TNT over them
|
|
if (*(int *)(param_1 + 0x18) != 0) {
|
|
//iVar4 = Damaged speed Constant/2
|
|
iVar4 = (int)((uint)*(ushort *)(param_1 + 0x438) << 0x10) >> 0x11;
|
|
}
|
|
|
|
//if racer is burnt or squished, or 0x50A = 0
|
|
if (((*(short *)(param_1 + 0x402) != 0) || (*(short *)(param_1 + 0x404) != 0)) ||
|
|
(*(short *)(param_1 + 0x50a) == 0)) {
|
|
//iVar4 = Damaged speed Constant
|
|
//iVar4 = 0x1000
|
|
iVar4 = (int)*(short *)(param_1 + 0x438);
|
|
}
|
|
|
|
//if racer is affected by Clock item and
|
|
//definition: iVar1 = Damaged speed Constant * ((0x14 - Place in race) >> 4)
|
|
//(iVar1 = Damaged speed Constant (0x1000) when racer is 1st to 5th, iVar1 = 0 when 6th to 8th),
|
|
//iVar4 < iVar1 (if racer has a TNT over them)
|
|
if ((*(short *)(param_1 + 0xc) != 0) && (iVar1 = (int)*(short *)(param_1 + 0x438) *
|
|
(0x14 - (int)*(short *)(param_1 + 0x482)) >> 4, iVar4 < iVar1)) {
|
|
//correct 0x800 to 0x1000
|
|
iVar4 = iVar1;
|
|
}
|
|
|
|
//iVar4 = Net Speed
|
|
//iVar4 = (Stat Additional + Speed Additional) - Damaged speed Constant
|
|
iVar4 = (iVar2 + iVar3) - iVar4;
|
|
|
|
//if Net Speed is higher than USF Speed
|
|
if (0x6400 < iVar4) {
|
|
//prevent Speed from going over USF Speed
|
|
iVar4 = 0x6400;
|
|
}
|
|
//return Net Speed for racer
|
|
return iVar4;
|
|
}
|
|
|
|
|
|
// VehPhysJoystick_ReturnToRest
|
|
int FUN_8006163c(int param_1,undefined4 param_2,short *param_3)
|
|
|
|
{
|
|
int iVar1;
|
|
int iVar2;
|
|
int iVar3;
|
|
|
|
// if not using racing wheel
|
|
if (param_3 == (short *)0x0)
|
|
{
|
|
// deadzone
|
|
iVar2 = 0x30;
|
|
|
|
// range
|
|
iVar3 = 0x7f;
|
|
|
|
// center of wheel
|
|
iVar1 = 0x80;
|
|
}
|
|
|
|
// if using racing wheel
|
|
else
|
|
{
|
|
// deadzone
|
|
iVar2 = (int)param_3[1];
|
|
|
|
// range
|
|
iVar3 = (int)param_3[2];
|
|
|
|
// center of wheel
|
|
iVar1 = (int)*param_3;
|
|
}
|
|
|
|
// convert from [0,0xff] to [-0x7f,0x7f]
|
|
param_1 = param_1 - iVar1;
|
|
|
|
// negative strength
|
|
if (param_1 < 0)
|
|
{
|
|
// map value
|
|
iVar1 = FUN_80058f9c(
|
|
-param_1, // [stickVal]
|
|
iVar2, iVar3, // [deadzone, range]
|
|
0, param_2 // [0, const 0x80 (halfway lerp)]
|
|
);
|
|
iVar1 = -iVar1;
|
|
}
|
|
|
|
// positive strength
|
|
else
|
|
{
|
|
// map value
|
|
iVar1 = FUN_80058f9c(
|
|
param_1, // [stickVal]
|
|
iVar2,iVar3, // [deadzone, range]
|
|
0, param_2 // [0, const 0x80 (halfway lerp)]
|
|
);
|
|
}
|
|
return iVar1;
|
|
}
|
|
|
|
|
|
// param_1 is desired steer strength
|
|
// param_2 is max possible steer
|
|
// param_3 RacingWheelData struct
|
|
|
|
// VehPhysJoystick_GetStrength
|
|
// can only be positive (negated elsewhere)
|
|
int FUN_800616b0(int param_1,int param_2,int param_3)
|
|
|
|
{
|
|
int iVar1;
|
|
int iVar2;
|
|
int iVar3;
|
|
|
|
// dead zone
|
|
iVar1 = 0x30;
|
|
|
|
// if not using a racing wheel
|
|
if (param_3 == 0)
|
|
{
|
|
// range of steering
|
|
iVar2 = 0x7f;
|
|
|
|
// RangeMinusDeadzone
|
|
iVar3 = 0x5e;
|
|
}
|
|
|
|
// if using a racing wheel
|
|
else
|
|
{
|
|
// dead zone
|
|
iVar1 = (int)*(short *)(param_3 + 2);
|
|
|
|
// range
|
|
iVar2 = (int)*(short *)(param_3 + 4);
|
|
|
|
// RangeMinusDeadzone
|
|
iVar3 = iVar2 - iVar1;
|
|
}
|
|
|
|
// if desired steer < Deadzone
|
|
if (param_1 < iVar1)
|
|
{
|
|
// dont steer
|
|
return 0;
|
|
}
|
|
|
|
// SteerMinusDeadzone
|
|
iVar1 = param_1 - iVar1;
|
|
|
|
// if desired steer > Range
|
|
if (iVar2 <= param_1)
|
|
{
|
|
// default to max desired steer
|
|
return param_2;
|
|
}
|
|
|
|
// if SteerMinusDeadzone >= Half RangeMinusDeadzone
|
|
if (iVar3 / 2 <= iVar1)
|
|
{
|
|
iVar1 = (iVar1 - iVar3 / 2) * (param_2 - param_2 / 5) * 2;
|
|
|
|
// check error
|
|
if (iVar3 == 0) trap(0x1c00);
|
|
if ((iVar3 == -1) && (iVar1 == -0x80000000)) trap(0x1800);
|
|
|
|
return iVar1 / iVar3 + param_2 / 5;
|
|
}
|
|
|
|
// if SteerMinusDeadzone < Half RangeMinusDeadzone
|
|
|
|
iVar1 = iVar1 * (param_2 / 5) * 2;
|
|
|
|
// check error
|
|
if (iVar3 == 0) trap(0x1c00);
|
|
if ((iVar3 == -1) && (iVar1 == -0x80000000)) trap(0x1800);
|
|
|
|
// xxx / RangeMinusDeadzone
|
|
return iVar1 / iVar3;
|
|
}
|
|
|
|
|
|
// param_1 is steer
|
|
// DPAD: 00 for left, 80 for neutral, FF for right
|
|
// Analog: anything 00 - FF
|
|
// param_2 is max possible steer
|
|
// param_3 RacingWheelData struct
|
|
|
|
// VehPhysJoystick_GetStrengthAbsolute
|
|
// can be positive or negative
|
|
int FUN_800617cc(int param_1,undefined4 param_2,short *param_3)
|
|
|
|
{
|
|
int iVar1;
|
|
|
|
// center steering
|
|
iVar1 = 0x80;
|
|
|
|
// if racing wheel data exists
|
|
if (param_3 != (short *)0x0)
|
|
{
|
|
// get center of wheel
|
|
iVar1 = (int)*param_3;
|
|
}
|
|
|
|
// if steering right
|
|
if (param_1 - iVar1 < 0)
|
|
{
|
|
// VehPhysJoystick_GetStrength
|
|
iVar1 = FUN_800616b0(-(param_1 - iVar1), param_2, param_3);
|
|
|
|
// negate result to steer right
|
|
iVar1 = -iVar1;
|
|
}
|
|
|
|
// if steer left
|
|
else
|
|
{
|
|
// VehPhysJoystick_GetStrength
|
|
iVar1 = FUN_800616b0(param_1 - iVar1, param_2, param_3);
|
|
}
|
|
|
|
// steer result
|
|
return iVar1;
|
|
}
|
|
|
|
|
|
|
|
// VehPhysProc_Driving_PhysLinear
|
|
void FUN_8006181c(int param_1,int param_2)
|
|
{
|
|
char cVar1;
|
|
char cVar2;
|
|
short sVar3;
|
|
bool bVar4;
|
|
undefined *puVar5;
|
|
ushort uVar6;
|
|
undefined2 uVar7;
|
|
int iVar8;
|
|
uint uVar9;
|
|
int iVar10;
|
|
int iVar11;
|
|
undefined4 *puVar12;
|
|
short sVar13;
|
|
int iVar14;
|
|
uint uVar15;
|
|
undefined4 uVar16;
|
|
undefined uVar17;
|
|
ushort uVar18;
|
|
int iVar19;
|
|
uint uVar20;
|
|
int iVar21;
|
|
uint uVar22;
|
|
int iVar23;
|
|
undefined *puVar24;
|
|
uint local_38;
|
|
uint local_34;
|
|
|
|
// If race timer is not supposed to stop for this racer
|
|
if ((*(uint *)(param_2 + 0x2c8) & 0x40000) == 0)
|
|
{
|
|
// set racer's timer to the time on the clock
|
|
*(undefined4 *)(param_2 + 0x514) = *(undefined4 *)(PTR_DAT_8008d2ac + 0x1d10);
|
|
}
|
|
|
|
// elapsed milliseconds per frame, ~32
|
|
iVar14 = *(int *)(PTR_DAT_8008d2ac + 0x1d04);
|
|
|
|
// negative elapsed milliseconds per frame
|
|
iVar8 = -iVar14;
|
|
|
|
if (
|
|
// time on the clock
|
|
(*(int *)(PTR_DAT_8008d2ac + 0x1d10) < 0x8ca00) &&
|
|
|
|
// race timer is not frozen for this player
|
|
((*(uint *)(param_2 + 0x2c8) & 0x40000) == 0)
|
|
)
|
|
{
|
|
// increment timer by (speed * time)
|
|
*(int *)(param_2 + 0x518) =
|
|
*(int *)(param_2 + 0x518) +
|
|
(*(short *)(param_2 + 0x38e) * iVar14 >> 8);
|
|
}
|
|
|
|
// Next 7 lines are repetitive, this time for Reserves (0x3e2)
|
|
// Make "desired" amount by subtracting elapsed time from "current" amount,
|
|
// store desired into iVar11, then copy it into iVar7. If current is more than 0,
|
|
// then handle subtraction. In subtraction, make sure desired is not negative,
|
|
// then set current to desired
|
|
|
|
iVar11 = (int)*(short *)(param_2 + 0x3e2) + iVar8;
|
|
uVar7 = (undefined2)iVar11;
|
|
if (0 < (int)*(short *)(param_2 + 0x3e2)) {
|
|
if (iVar11 < 0) {
|
|
uVar7 = 0;
|
|
}
|
|
*(undefined2 *)(param_2 + 0x3e2) = uVar7;
|
|
|
|
//adds *spent* Reserves to cumulative counter
|
|
*(int *)(param_2 + 0x534) = *(int *)(param_2 + 0x534) + iVar14;
|
|
}
|
|
|
|
// Next 7 lines are repetitive, this time for Outside Turbo Timer (0x3de)
|
|
// Make "desired" amount by subtracting elapsed time from "current" amount,
|
|
// store desired into iVar11, then copy it into iVar7. If current is more than 0,
|
|
// then handle subtraction. In subtraction, make sure desired is not negative,
|
|
// then set current to desired
|
|
|
|
iVar11 = (int)*(short *)(param_2 + 0x3de) + iVar8;
|
|
uVar7 = (undefined2)iVar11;
|
|
if (0 < (int)*(short *)(param_2 + 0x3de)) {
|
|
if (iVar11 < 0) {
|
|
uVar7 = 0;
|
|
}
|
|
*(undefined2 *)(param_2 + 0x3de) = uVar7;
|
|
}
|
|
|
|
// Next 7 lines are repetitive, this time for Outside Turbo Sound (0x3e0)
|
|
// Make "desired" amount by subtracting elapsed time from "current" amount,
|
|
// store desired into iVar11, then copy it into iVar7. If current is more than 0,
|
|
// then handle subtraction. In subtraction, make sure desired is not negative,
|
|
// then set current to desired
|
|
|
|
iVar11 = (int)*(short *)(param_2 + 0x3e0) + iVar8;
|
|
uVar7 = (undefined2)iVar11;
|
|
if (0 < (int)*(short *)(param_2 + 0x3e0)) {
|
|
if (iVar11 < 0) {
|
|
uVar7 = 0;
|
|
}
|
|
*(undefined2 *)(param_2 + 0x3e0) = uVar7;
|
|
}
|
|
|
|
// Next 7 lines are repetitive, this time for Collision (0x3fe)
|
|
// Make "desired" amount by subtracting elapsed time from "current" amount,
|
|
// store desired into iVar11, then copy it into iVar7. If current is more than 0,
|
|
// then handle subtraction. In subtraction, make sure desired is not negative,
|
|
// then set current to desired
|
|
|
|
iVar11 = (int)*(short *)(param_2 + 0x3fe) + iVar8;
|
|
uVar7 = (undefined2)iVar11;
|
|
if (0 < (int)*(short *)(param_2 + 0x3fe)) {
|
|
if (iVar11 < 0) {
|
|
uVar7 = 0;
|
|
}
|
|
*(undefined2 *)(param_2 + 0x3fe) = uVar7;
|
|
|
|
// Add elapsed time to a counter for how long you've driven against a wall
|
|
*(int *)(param_2 + 0x530) = *(int *)(param_2 + 0x530) + iVar14;
|
|
}
|
|
|
|
// Next 7 lines are repetitive, this time for Jump Animation (0x3f6)
|
|
// Make "desired" amount by subtracting elapsed time from "current" amount,
|
|
// store desired into iVar11, then copy it into iVar7. If current is more than 0,
|
|
// then handle subtraction. In subtraction, make sure desired is not negative,
|
|
// then set current to desired
|
|
|
|
iVar11 = (int)*(short *)(param_2 + 0x3f6) + iVar8;
|
|
uVar7 = (undefined2)iVar11;
|
|
if (0 < (int)*(short *)(param_2 + 0x3f6)) {
|
|
if (iVar11 < 0) {
|
|
uVar7 = 0;
|
|
}
|
|
*(undefined2 *)(param_2 + 0x3f6) = uVar7;
|
|
}
|
|
|
|
// Next 7 lines are repetitive, this time for Unknown (0x3f2)
|
|
// Make "desired" amount by subtracting elapsed time from "current" amount,
|
|
// store desired into iVar11, then copy it into iVar7. If current is more than 0,
|
|
// then handle subtraction. In subtraction, make sure desired is not negative,
|
|
// then set current to desired
|
|
|
|
iVar11 = (int)*(short *)(param_2 + 0x3f2) + iVar8;
|
|
uVar7 = (undefined2)iVar11;
|
|
if (0 < (int)*(short *)(param_2 + 0x3f2)) {
|
|
if (iVar11 < 0) {
|
|
uVar7 = 0;
|
|
}
|
|
*(undefined2 *)(param_2 + 0x3f2) = uVar7;
|
|
}
|
|
|
|
// Next 7 lines are repetitive, this time for Unknown (0x3fa)
|
|
// Make "desired" amount by subtracting elapsed time from "current" amount,
|
|
// store desired into iVar11, then copy it into iVar7. If current is more than 0,
|
|
// then handle subtraction. In subtraction, make sure desired is not negative,
|
|
// then set current to desired
|
|
|
|
iVar11 = (int)*(short *)(param_2 + 0x3fa) + iVar8;
|
|
uVar7 = (undefined2)iVar11;
|
|
if (0 < (int)*(short *)(param_2 + 0x3fa)) {
|
|
if (iVar11 < 0) {
|
|
uVar7 = 0;
|
|
}
|
|
*(undefined2 *)(param_2 + 0x3fa) = uVar7;
|
|
}
|
|
|
|
// Next 7 lines are repetitive, this time for Burnt Effect Timer (0x402)
|
|
// Make "desired" amount by subtracting elapsed time from "current" amount,
|
|
// store desired into iVar11, then copy it into iVar7. If current is more than 0,
|
|
// then handle subtraction. In subtraction, make sure desired is not negative,
|
|
// then set current to desired
|
|
|
|
iVar11 = (int)*(short *)(param_2 + 0x402) + iVar8;
|
|
uVar7 = (undefined2)iVar11;
|
|
if (0 < (int)*(short *)(param_2 + 0x402)) {
|
|
if (iVar11 < 0) {
|
|
uVar7 = 0;
|
|
}
|
|
*(undefined2 *)(param_2 + 0x402) = uVar7;
|
|
|
|
// increment timer for total frames burnt
|
|
*(int *)(param_2 + 0x54c) = *(int *)(param_2 + 0x54c) + iVar14;
|
|
}
|
|
|
|
// Next 7 lines are repetitive, this time for Squished Effect Timer (0x404)
|
|
// Make "desired" amount by subtracting elapsed time from "current" amount,
|
|
// store desired into iVar11, then copy it into iVar7. If current is more than 0,
|
|
// then handle subtraction. In subtraction, make sure desired is not negative,
|
|
// then set current to desired
|
|
|
|
iVar11 = (int)*(short *)(param_2 + 0x404) + iVar8;
|
|
uVar7 = (undefined2)iVar11;
|
|
if (0 < (int)*(short *)(param_2 + 0x404)) {
|
|
if (iVar11 < 0) {
|
|
uVar7 = 0;
|
|
}
|
|
*(undefined2 *)(param_2 + 0x404) = uVar7;
|
|
|
|
// increment timer for total frames squished
|
|
*(int *)(param_2 + 0x544) = *(int *)(param_2 + 0x544) + iVar14;
|
|
}
|
|
|
|
// Next 7 lines are repetitive, this time for Unknown (0x406)
|
|
// Make "desired" amount by subtracting elapsed time from "current" amount,
|
|
// store desired into iVar11, then copy it into iVar7. If current is more than 0,
|
|
// then handle subtraction. In subtraction, make sure desired is not negative,
|
|
// then set current to desired
|
|
|
|
iVar11 = (int)*(short *)(param_2 + 0x406) + iVar8;
|
|
uVar7 = (undefined2)iVar11;
|
|
if (0 < (int)*(short *)(param_2 + 0x406)) {
|
|
if (iVar11 < 0) {
|
|
uVar7 = 0;
|
|
}
|
|
*(undefined2 *)(param_2 + 0x406) = uVar7;
|
|
}
|
|
|
|
// Next 7 lines are repetitive, this time for Unknown (0x408)
|
|
// Make "desired" amount by subtracting elapsed time from "current" amount,
|
|
// store desired into iVar11, then copy it into iVar7. If current is more than 0,
|
|
// then handle subtraction. In subtraction, make sure desired is not negative,
|
|
// then set current to desired
|
|
|
|
iVar11 = (int)*(short *)(param_2 + 0x408) + iVar8;
|
|
uVar7 = (undefined2)iVar11;
|
|
if (0 < (int)*(short *)(param_2 + 0x408)) {
|
|
if (iVar11 < 0) {
|
|
uVar7 = 0;
|
|
}
|
|
*(undefined2 *)(param_2 + 0x408) = uVar7;
|
|
}
|
|
|
|
// If Super Engine Cheat is not enabled
|
|
if ((*(uint *)(PTR_DAT_8008d2ac + 8) & 0x10000) == 0)
|
|
{
|
|
// Next 7 lines are repetitive, this time for Super Engine Timer (0x38)
|
|
// Make "desired" amount by subtracting elapsed time from "current" amount,
|
|
// store desired into iVar11, then copy it into iVar7. If current is more than 0,
|
|
// then handle subtraction. In subtraction, make sure desired is not negative,
|
|
// then set current to desired
|
|
|
|
iVar11 = (int)*(short *)(param_2 + 0x38) + iVar8;
|
|
uVar7 = (undefined2)iVar11;
|
|
if (0 < (int)*(short *)(param_2 + 0x38)) {
|
|
if (iVar11 < 0) {
|
|
uVar7 = 0;
|
|
}
|
|
*(undefined2 *)(param_2 + 0x38) = uVar7;
|
|
}
|
|
}
|
|
|
|
// Next 7 lines are repetitive, this time for Clock Weapon Timer (0xC)
|
|
// Make "desired" amount by subtracting elapsed time from "current" amount,
|
|
// store desired into iVar11, then copy it into iVar7. If current is more than 0,
|
|
// then handle subtraction. In subtraction, make sure desired is not negative,
|
|
// then set current to desired
|
|
|
|
iVar11 = (int)*(short *)(param_2 + 0xc) + iVar8;
|
|
uVar7 = (undefined2)iVar11;
|
|
if (0 < (int)*(short *)(param_2 + 0xc)) {
|
|
if (iVar11 < 0) {
|
|
uVar7 = 0;
|
|
}
|
|
*(undefined2 *)(param_2 + 0xc) = uVar7;
|
|
}
|
|
|
|
// Next 7 lines are repetitive, this time for "Mashing X makes it big" (0x3c0)
|
|
// Make "desired" amount by subtracting elapsed time from "current" amount,
|
|
// store desired into iVar11, then copy it into iVar7. If current is more than 0,
|
|
// then handle subtraction. In subtraction, make sure desired is not negative,
|
|
// then set current to desired
|
|
|
|
iVar11 = (int)*(short *)(param_2 + 0x3c0) + iVar8;
|
|
uVar7 = (undefined2)iVar11;
|
|
if (0 < (int)*(short *)(param_2 + 0x3c0)) {
|
|
if (iVar11 < 0) {
|
|
uVar7 = 0;
|
|
}
|
|
*(undefined2 *)(param_2 + 0x3c0) = uVar7;
|
|
}
|
|
|
|
// This one is a frame timer, not a millisecond timer,
|
|
// Decrease one frame from Jump Buffering as long as timer is more than zero
|
|
if (0 < *(short *)(param_2 + 0x3f0)) {
|
|
*(short *)(param_2 + 0x3f0) = *(short *)(param_2 + 0x3f0) + -1;
|
|
}
|
|
|
|
//keep track of time spent with full wumpa
|
|
if ('\t' < *(char *)(param_2 + 0x30)) {
|
|
*(int *)(param_2 + 0x52c) = *(int *)(param_2 + 0x52c) + iVar14;
|
|
}
|
|
|
|
//keep track of time spent in mud
|
|
if (*(char *)(param_2 + 0xc2) == '\x0e') {
|
|
*(int *)(param_2 + 0x524) = *(int *)(param_2 + 0x524) + iVar14;
|
|
}
|
|
|
|
// Get placement of racer (1st place, 2nd, 3rd, etc)
|
|
sVar13 = *(short *)(param_2 + 0x482);
|
|
|
|
// Basically, if racer is in last place in any possible race scenario
|
|
if (
|
|
(
|
|
(
|
|
(
|
|
// If racer is in 8th place
|
|
(sVar13 == 7) &&
|
|
|
|
// If numPlyrCurrGame is 1
|
|
(PTR_DAT_8008d2ac[0x1ca8] == '\x01')
|
|
) ||
|
|
|
|
(
|
|
(
|
|
// If racer is in 6th place
|
|
sVar13 == 5 &&
|
|
|
|
// if numPlyrCurrGame is 2
|
|
(PTR_DAT_8008d2ac[0x1ca8] == '\x02')
|
|
)
|
|
)
|
|
) ||
|
|
(
|
|
(
|
|
// if racer is in 4th place
|
|
sVar13 == 3 &&
|
|
|
|
// if numPlyrCurrGame is more than 2
|
|
(2 < (byte)PTR_DAT_8008d2ac[0x1ca8])
|
|
)
|
|
)
|
|
) &&
|
|
(
|
|
// race timer is not frozen for this player
|
|
(*(uint *)(param_2 + 0x2c8) & 0x40000) == 0)
|
|
)
|
|
{
|
|
// Increase the time racer has been in last place by elapsed milliseconds
|
|
*(int *)(param_2 + 0x528) = *(int *)(param_2 + 0x528) + iVar14;
|
|
}
|
|
|
|
sVar13 = 4;
|
|
|
|
// if you have a raincloud over your head from potion
|
|
if (*(int *)(param_2 + 0x4a0) != 0) {
|
|
sVar13 = *(short *)(*(int *)(*(int *)(param_2 + 0x4a0) + 0x30) + 6);
|
|
}
|
|
|
|
// get approximate speed
|
|
iVar11 = (int)*(short *)(param_2 + 0x38e);
|
|
|
|
// Action flags (isRaceOver, isTimeFrozen, etc)
|
|
uVar22 = *(uint *)(param_2 + 0x2c8);
|
|
|
|
// driver->clockReceive
|
|
iVar19 = (int)*(short *)(param_2 + 0xc);
|
|
|
|
*(short *)(param_2 + 0x50a) = sVar13;
|
|
|
|
// absolute value of speed
|
|
if (iVar11 < 0) {
|
|
iVar11 = -iVar11;
|
|
}
|
|
|
|
if (
|
|
(
|
|
// if you are not impacted by clock weapon
|
|
(iVar19 == 0) &&
|
|
(
|
|
// get squished timer
|
|
iVar19 = (int)*(short *)(param_2 + 0x404),
|
|
|
|
// if you are not squished
|
|
iVar19 == 0
|
|
)
|
|
) &&
|
|
(
|
|
(
|
|
sVar13 != 0 ||
|
|
(
|
|
// if time on the clock is zero
|
|
iVar19 = *(int *)(PTR_DAT_8008d2ac + 0x1d10),
|
|
iVar19 == 0
|
|
)
|
|
)
|
|
)
|
|
)
|
|
{
|
|
//uVar20 = Hazard Timer (sign extended 2 to 4 bytes)
|
|
uVar20 = SEXT24(*(short *)(param_2 + 0xe));
|
|
|
|
// hazard timer will not go
|
|
// down unless you keep moving,
|
|
// is this for red potion raincloud?
|
|
|
|
// if you have high speed
|
|
if (0x100 < iVar11)
|
|
{
|
|
// decrease hazard by elapsed time
|
|
uVar20 = uVar20 + iVar8;
|
|
}
|
|
|
|
uVar7 = (undefined2)(uVar20 & 0xfffffffe);
|
|
if (-1 < (int)(uVar20 & 0xfffffffe)) {
|
|
uVar7 = 0xfffe;
|
|
}
|
|
|
|
//Hazard Timer = uVar7
|
|
*(undefined2 *)(param_2 + 0xe) = uVar7;
|
|
}
|
|
|
|
// if you are not impacted by hazard (other than clock)
|
|
else {
|
|
uVar18 = (ushort)iVar19;
|
|
|
|
// if you are not touching the ground
|
|
if ((uVar22 & 1) == 0)
|
|
{
|
|
// if speed is low
|
|
if (iVar11 < 0x101) goto LAB_80061cf8;
|
|
|
|
// if speed is high...
|
|
|
|
// absolute value of clock hazard
|
|
if (iVar19 < 0) {
|
|
uVar18 = -uVar18;
|
|
}
|
|
|
|
LAB_80061d0c:
|
|
uVar6 = -uVar18 | 1;
|
|
}
|
|
|
|
// if you are touching the ground
|
|
else
|
|
{
|
|
// if speed is low
|
|
if (iVar11 < 0x101)
|
|
{
|
|
LAB_80061cf8:
|
|
//uVar18 = Hazard Timer
|
|
uVar18 = *(ushort *)(param_2 + 0xe);
|
|
uVar6 = uVar18 | 1;
|
|
if (0 < (short)uVar18) goto LAB_80061d0c;
|
|
}
|
|
|
|
// if speed is high
|
|
else
|
|
{
|
|
// absolute value of clock hazard
|
|
if (iVar19 < 0) {
|
|
uVar18 = -uVar18;
|
|
}
|
|
|
|
// Use trigonometry with speed and
|
|
// clock timer to make the car waddle
|
|
|
|
//iVar8 = Clock Item (Receive) Timer << 0x10
|
|
iVar8 = (uint)*(ushort *)(param_2 + 0xc) << 0x10;
|
|
|
|
iVar19 = iVar8 >> 0x16;
|
|
if (0x40 < iVar19) {
|
|
iVar19 = 0x40;
|
|
}
|
|
|
|
uVar20 = (iVar8 >> 0x10) << 4;
|
|
|
|
// approximate trigonometry
|
|
iVar8 = *(int *)(&DAT_800845a0 + (uVar20 & 0x3ff) * 4);
|
|
|
|
if ((uVar20 & 0x400) == 0) {
|
|
iVar8 = iVar8 << 0x10;
|
|
}
|
|
iVar8 = iVar8 >> 0x10;
|
|
if ((uVar20 & 0x800) != 0) {
|
|
iVar8 = -iVar8;
|
|
}
|
|
iVar21 = iVar11 >> 8;
|
|
if (0x20 < iVar21) {
|
|
iVar21 = 0x20;
|
|
}
|
|
|
|
// GAMEPAD_ShockForce1
|
|
FUN_800264c0(param_2,4,iVar19 + (iVar8 >> 5) + iVar21 + 0x18);
|
|
|
|
uVar6 = uVar18 | 1;
|
|
}
|
|
}
|
|
//Hazard Timer = uVar6
|
|
*(ushort *)(param_2 + 0xe) = uVar6;
|
|
}
|
|
|
|
//trigger Item roll / selection
|
|
//if Held Item = None
|
|
if (*(char *)(param_2 + 0x36) == '\x10') {
|
|
|
|
//if Item roll is done
|
|
if (*(short *)(param_2 + 0x3a) == 0)
|
|
{
|
|
// Select a random weapon for driver
|
|
FUN_80060f0c(param_2);
|
|
|
|
// if 9 < number of wumpa
|
|
// if wumpa is 10
|
|
bVar4 = '\t' < *(char *)(param_2 + 0x30);
|
|
|
|
// if you have less than 10 wumpa
|
|
|
|
// "ding" sound
|
|
uVar16 = 0x5e;
|
|
|
|
// if you have 10 wumpa
|
|
if (bVar4)
|
|
{
|
|
// "ka-ching" sound
|
|
uVar16 = 0x41;
|
|
}
|
|
|
|
// OtherFX_Play of getting weapon
|
|
FUN_80028468(uVar16,(uint)bVar4);
|
|
}
|
|
|
|
//if Item roll is not done
|
|
else
|
|
{
|
|
//Item roll Timer--
|
|
*(short *)(param_2 + 0x3a) = *(short *)(param_2 + 0x3a) + -1;
|
|
}
|
|
}
|
|
|
|
//sVar3 = No Item Timer
|
|
sVar3 = *(short *)(param_2 + 0x3c);
|
|
|
|
//if Item is going away
|
|
if (sVar3 != 0) {
|
|
|
|
//if Item is about to be gone and Number of Items = 0
|
|
if ((sVar3 == 1) && (*(char *)(param_2 + 0x37) == '\0')) {
|
|
|
|
// if numPlyrCurrGame is > 2
|
|
if ((2 < (byte)PTR_DAT_8008d2ac[0x1ca8]) &&
|
|
|
|
// If you're not in Battle Mode
|
|
((((*(uint *)PTR_DAT_8008d2ac & 0x20) == 0 &&
|
|
|
|
// your weapon is 3 missiles
|
|
(*(char *)(param_2 + 0x36) == '\v')) &&
|
|
|
|
// If there are racers that had 3 missiles
|
|
(0 < *(int *)(PTR_DAT_8008d2ac + 0x1ec4)))))
|
|
{
|
|
// decrement the number of players that had 3 missiles
|
|
*(int *)(PTR_DAT_8008d2ac + 0x1ec4) = *(int *)(PTR_DAT_8008d2ac + 0x1ec4) + -1;
|
|
}
|
|
|
|
// take away weapon
|
|
*(undefined *)(param_2 + 0x36) = 0xf;
|
|
}
|
|
|
|
//No Item Timer--
|
|
*(short *)(param_2 + 0x3c) = sVar3 + -1;
|
|
}
|
|
|
|
// If Invinsibility effect is active (timer at 0x24)
|
|
// Make "desired" timer by subtracting elapsed time from "current",
|
|
// set "current" to "desired", then set "current" to zero if "desired" is negative
|
|
|
|
if ((*(int *)(param_2 + 0x24) != 0) &&
|
|
(iVar8 = *(int *)(param_2 + 0x24) - *(int *)(PTR_DAT_8008d2ac + 0x1d04),
|
|
*(int *)(param_2 + 0x24) = iVar8, iVar8 < 0)) {
|
|
*(undefined4 *)(param_2 + 0x24) = 0;
|
|
}
|
|
|
|
// If Invincibility effect is active (timer at 0x28) and if Cheat Code is Disabled
|
|
// Make "desired" timer by subtracting elapsed time from "current",
|
|
// set "current" to "desired", then set "current" to zero if "desired" is negative
|
|
|
|
if (
|
|
// if driver is invisible
|
|
(*(int *)(param_2 + 0x28) != 0) &&
|
|
|
|
// If Permanent Invisibility Cheat is Disabled
|
|
((*(uint *)(PTR_DAT_8008d2ac + 8) & 0x8000) == 0)
|
|
)
|
|
{
|
|
// decrease invisibility timer,
|
|
// can not go below zero
|
|
iVar8 = *(int *)(param_2 + 0x28) - *(int *)(PTR_DAT_8008d2ac + 0x1d04);
|
|
*(int *)(param_2 + 0x28) = iVar8;
|
|
if (iVar8 < 0) {
|
|
*(undefined4 *)(param_2 + 0x28) = 0;
|
|
}
|
|
|
|
// If the timer expires, make yourself visible
|
|
if (*(int *)(param_2 + 0x28) == 0)
|
|
{
|
|
// restore backup of instance flags
|
|
*(undefined4 *)(*(int *)(param_2 + 0x1c) + 0x28) = *(undefined4 *)(param_2 + 0x2c);
|
|
|
|
// set instance transparency to zero
|
|
*(undefined2 *)(*(int *)(param_2 + 0x1c) + 0x22) = 0;
|
|
|
|
// OtherFX_Play
|
|
FUN_80028468(0x62,1);
|
|
}
|
|
}
|
|
|
|
// Random guess, this next block is probably for making a backup
|
|
// of current position and rotation, to calculate linear + angular
|
|
// velocity by comparing two frames
|
|
|
|
*(undefined4 *)(param_2 + 0x2f4) = *(undefined4 *)(param_2 + 0x2ec);
|
|
puVar24 = PTR_DAT_8008d2ac;
|
|
|
|
// action flags
|
|
*(uint *)(param_2 + 0x2cc) = uVar22;
|
|
|
|
*(undefined4 *)(param_2 + 0x2e4) = *(undefined4 *)(param_2 + 0x2d8);
|
|
*(undefined4 *)(param_2 + 0x2e8) = *(undefined4 *)(param_2 + 0x2dc);
|
|
*(undefined2 *)(param_2 + 0x2f8) = *(undefined2 *)(param_2 + 0x2f0);
|
|
*(undefined2 *)(param_2 + 0x392) = *(undefined2 *)(param_2 + 0x390);
|
|
*(undefined2 *)(param_2 + 0x3c8) = *(undefined2 *)(param_2 + 0x3c6);
|
|
*(undefined4 *)(param_2 + 0x2e0) = *(undefined4 *)(param_2 + 0x2d4);
|
|
|
|
uVar20 = uVar22 & 0x7f1f83d5;
|
|
|
|
// disable input if opening adv hub door with key
|
|
if ((*(uint *)(puVar24 + 8) & 0x4004) != 0) goto LAB_800629f8;
|
|
|
|
iVar19 = (uint)*(byte *)(param_2 + 0x380) + 1;
|
|
uVar17 = (undefined)iVar19;
|
|
|
|
// this is always zero, there's no possible
|
|
// way for it not to be, so AxisAngle4
|
|
iVar8 = iVar19 * 8;
|
|
|
|
if (iVar19 != 0) {
|
|
uVar17 = 0;
|
|
iVar8 = 0;
|
|
}
|
|
|
|
// always AxisAngle4
|
|
puVar12 = (undefined4 *)(param_2 + iVar8 + 0x378);
|
|
|
|
// if not touching ground
|
|
if ((uVar22 & 1) == 0)
|
|
{
|
|
// AngleAxis2_NormalVec
|
|
*puVar12 = *(undefined4 *)(param_2 + 0x368);
|
|
*(undefined2 *)(puVar12 + 1) = *(undefined2 *)(param_2 + 0x36c);
|
|
}
|
|
|
|
// if touching ground
|
|
else
|
|
{
|
|
// AngleAxis1_NormalVec
|
|
*puVar12 = *(undefined4 *)(param_2 + 0x360);
|
|
*(undefined2 *)(puVar12 + 1) = *(undefined2 *)(param_2 + 0x364);
|
|
}
|
|
|
|
*(undefined *)(param_2 + 0x380) = uVar17;
|
|
|
|
// driver -> instBubble
|
|
iVar8 = *(int *)(param_1 + 0x14);
|
|
|
|
uVar22 = uVar20;
|
|
|
|
// loop through all, find mask if it exists
|
|
while (iVar8 != 0)
|
|
{
|
|
// If thread->modelIndex is Aku or Uka
|
|
if ((*(short *)(iVar8 + 0x44) == 0x3a) || (*(short *)(iVar8 + 0x44) == 0x39)) {
|
|
uVar22 = uVar20 | 0x800000;
|
|
break;
|
|
}
|
|
|
|
// check next bubble in linked list
|
|
iVar8 = *(int *)(iVar8 + 0x10);
|
|
}
|
|
|
|
// pointer to gamepad input of current player (param_2)
|
|
puVar24 = PTR_DAT_8008d2b0 + (uint)*(byte *)(param_2 + 0x4a) * 0x50;
|
|
|
|
// by default, hold no buttons
|
|
uVar20 = 0;
|
|
|
|
// If you're not in End-Of-Race menu
|
|
if ((*(uint *)PTR_DAT_8008d2ac & 0x200000) == 0)
|
|
{
|
|
// Get which button is held
|
|
uVar20 = *(uint *)(puVar24 + 0x10);
|
|
}
|
|
|
|
// by default, tap no buttons
|
|
uVar15 = 0;
|
|
|
|
// If you're not in End-Of-Race menu
|
|
if ((*(uint *)PTR_DAT_8008d2ac & 0x200000) == 0)
|
|
{
|
|
// Get which button is tapped
|
|
uVar15 = *(uint *)(puVar24 + 0x14);
|
|
}
|
|
|
|
// If you hold Cross
|
|
local_38 = uVar20 & 0x10;
|
|
|
|
// If you hold Square
|
|
local_34 = uVar20 & 0x20;
|
|
|
|
// state of kart
|
|
cVar1 = *(char *)(param_2 + 0x376);
|
|
|
|
if (
|
|
(
|
|
// If you press circle
|
|
((uVar15 & 0x40) != 0) &&
|
|
|
|
|
|
(
|
|
// if neutral driving
|
|
((cVar1 == '\0' ||
|
|
|
|
// or sliding
|
|
(cVar1 == '\x02')) ||
|
|
|
|
// or ???
|
|
(cVar1 == '\t'))
|
|
)
|
|
) &&
|
|
|
|
// if there is no tnt on your head
|
|
(*(int *)(param_2 + 0x18) == 0)
|
|
)
|
|
{
|
|
// If there is no Bomb pointer
|
|
if (*(int *)(param_2 + 0x10) == 0) {
|
|
|
|
// If there is no Bubble pointer
|
|
if (*(int *)(param_2 + 0x14) == 0) {
|
|
|
|
// If there is no "weapon roulette" animation
|
|
sVar3 = *(short *)(param_2 + 0x3a);
|
|
if (sVar3 == 0) {
|
|
|
|
// If you dont have "roulette" weapon (0x10), and if you dont have "no weapon" (0xf)
|
|
// and if you did not have a weapon last frame (0x3c->0),
|
|
// and if (unknown sVar13 related to 0x4a0),
|
|
// and if you are not being effected by Clock Weapon
|
|
cVar2 = *(char *)(param_2 + 0x36);
|
|
if (((cVar2 != '\x0f') && (cVar2 != '\x10')) &&
|
|
((*(short *)(param_2 + 0x3c) == 0 &&
|
|
((sVar13 != 1 && (*(short *)(param_2 + 0xc) == 0))))))
|
|
{
|
|
// This driver wants to fire a weapon (0x2c8 flags)
|
|
uVar22 = uVar22 | 0x8000;
|
|
|
|
// If "held item quantity" is zero
|
|
if (*(char *)(param_2 + 0x37) == '\0')
|
|
{
|
|
*(undefined2 *)(param_2 + 0x3c) = 0x1e;
|
|
goto LAB_800621cc;
|
|
}
|
|
|
|
// If you have the Spring weapon
|
|
if (cVar2 == '\x05')
|
|
{
|
|
if (*(short *)(param_2 + 0x3f4) != 0) {
|
|
uVar9 = SEXT24(*(short *)(param_2 + 0x3f2));
|
|
goto LAB_80062188;
|
|
}
|
|
}
|
|
|
|
// any other weapon
|
|
else
|
|
{
|
|
// CHEAT_MASK, CHEAT_TURBO, or CHEAT_BOMBS
|
|
uVar9 = *(uint *)(PTR_DAT_8008d2ac + 8) & 0x400c00;
|
|
LAB_80062188:
|
|
// if cheats aren't enabled
|
|
if (uVar9 == 0)
|
|
{
|
|
// reduce number of items held
|
|
*(char *)(param_2 + 0x37) = *(char *)(param_2 + 0x37) + -1;
|
|
}
|
|
}
|
|
|
|
// 5-frame cooldown before next weapon
|
|
*(undefined2 *)(param_2 + 0x3c) = 5;
|
|
|
|
goto LAB_800621cc;
|
|
}
|
|
sVar3 = *(short *)(param_2 + 0x3a);
|
|
}
|
|
|
|
// if there are less than 70 frames (2.3 sec remaining)
|
|
if (sVar3 < 0x46)
|
|
{
|
|
// skip to the end of the countdown
|
|
*(undefined2 *)(param_2 + 0x3a) = 0;
|
|
}
|
|
}
|
|
|
|
// If there is a Bubble Pointer
|
|
else
|
|
{
|
|
// Shoot the bubble
|
|
|
|
// We can see the bubble pointer (driver + 0x14)
|
|
|
|
// instance -> thread -> object
|
|
iVar8 = *(int *)(*(int *)(*(int *)(param_2 + 0x14) + 0x6c) + 0x30);
|
|
|
|
*(ushort *)(iVar8 + 6) = *(ushort *)(iVar8 + 6) | 2;
|
|
|
|
// Reset to nullptr
|
|
*(undefined4 *)(param_2 + 0x14) = 0;
|
|
}
|
|
}
|
|
|
|
// If there is a Bomb Pointer
|
|
else
|
|
{
|
|
// Detonate the bomb
|
|
|
|
// We can see the bomb pointer (driver + 0x10)
|
|
|
|
// instance -> thread -> object
|
|
iVar8 = *(int *)(*(int *)(*(int *)(param_2 + 0x10) + 0x6c) + 0x30);
|
|
|
|
// always face camera
|
|
*(ushort *)(iVar8 + 0x16) = *(ushort *)(iVar8 + 0x16) | 2;
|
|
|
|
// Reset to nullptr
|
|
*(undefined4 *)(param_2 + 0x10) = 0;
|
|
}
|
|
}
|
|
LAB_800621cc:
|
|
|
|
// Check for Tapping L1 and R1
|
|
uVar15 = uVar15 & 0xc00;
|
|
|
|
if (
|
|
//if you're not pressing L1 or R1
|
|
(uVar15 == 0) ||
|
|
|
|
// or you are sliding
|
|
(*(char *)(param_2 + 0x376) == '\x02')
|
|
)
|
|
{
|
|
if (
|
|
// If you are holding L1 or R1 and
|
|
((uVar20 & 0xc00) != 0) &&
|
|
(sVar13 != 3)
|
|
)
|
|
{
|
|
if ((uVar22 & 4) == 0)
|
|
{
|
|
// 10 frame jump buffer
|
|
*(undefined2 *)(param_2 + 0x3f0) = 10;
|
|
}
|
|
goto LAB_8006222c;
|
|
}
|
|
uVar22 = uVar22 & 0xfffffffb;
|
|
if (0 < *(short *)(param_2 + 0x3f0)) {
|
|
*(undefined2 *)(param_2 + 0x3f0) = 0;
|
|
}
|
|
}
|
|
|
|
//if you're pressing jump buttons and not sliding
|
|
else
|
|
{
|
|
//if L1 and R1 were being tapped at once
|
|
if (uVar15 == 0xc00)
|
|
{
|
|
//set Last Jump button pressed to R1
|
|
*(undefined2 *)(param_2 + 0x382) = 0x400;
|
|
}
|
|
|
|
//if you're not tapping L1 and R1 at once
|
|
else
|
|
{
|
|
//Last Jump button pressed = uVar15
|
|
*(undefined2 *)(param_2 + 0x382) = (short)uVar15;
|
|
}
|
|
|
|
if (sVar13 != 3)
|
|
{
|
|
// 10 frame jump buffer
|
|
*(undefined2 *)(param_2 + 0x3f0) = 10;
|
|
LAB_8006222c:
|
|
uVar22 = uVar22 | 4;
|
|
}
|
|
}
|
|
|
|
if (
|
|
// If you are holding Square
|
|
(local_34 != 0) &&
|
|
|
|
// if you're not on any turbo pad
|
|
((*(uint *)(param_2 + 0xbc) & 3) == 0)
|
|
)
|
|
{
|
|
// Set Reserves to zero
|
|
*(undefined2 *)(param_2 + 0x3e2) = 0;
|
|
}
|
|
|
|
// assume normal gas pedal
|
|
iVar8 = 0x80;
|
|
|
|
// If you're not in End-Of-Race menu
|
|
if ((*(uint *)PTR_DAT_8008d2ac & 0x200000) == 0)
|
|
{
|
|
// gamepadBuffer -> stickRY (for gas or reverse)
|
|
iVar8 = (int)*(short *)(puVar24 + 0xe);
|
|
}
|
|
|
|
if (
|
|
// If Reserves are not zero
|
|
(*(short *)(param_2 + 0x3e2) != 0) ||
|
|
|
|
(sVar13 == 6)
|
|
)
|
|
{
|
|
if (
|
|
// If you are not holding Cross
|
|
(local_38 == 0) &&
|
|
|
|
// VehPhysJoystick_ReturnToRest
|
|
(iVar19 = FUN_8006163c(iVar8,0x80,0), -1 < iVar19)
|
|
)
|
|
{
|
|
uVar22 = uVar22 | 0x400000;
|
|
}
|
|
|
|
|
|
if (
|
|
// If are holding Square
|
|
(local_34 != 0) &&
|
|
|
|
(0x300 < iVar11)
|
|
)
|
|
{
|
|
uVar22 = uVar22 | 0x800;
|
|
}
|
|
|
|
// if you're on any turbo pad
|
|
if ((*(uint *)(param_2 + 0xbc) & 3) != 0)
|
|
{
|
|
// assume not holding square until boost is over
|
|
local_34 = 0;
|
|
}
|
|
|
|
// Assume you're holding Cross, because
|
|
// you have Reserves and you aren't slowing down
|
|
local_38 = 0x10;
|
|
}
|
|
|
|
iVar19 = 0x80;
|
|
|
|
// If you're not in End-Of-Race menu
|
|
if ((*(uint *)PTR_DAT_8008d2ac & 0x200000) == 0)
|
|
{
|
|
// gamepadBuffer -> stickLY
|
|
iVar19 = (int)*(short *)(puVar24 + 6);
|
|
}
|
|
|
|
if ((*(char *)(param_2 + 0x4b) < '\0') ||
|
|
(uVar22 = uVar22 & 0xdfffffff, *(char *)(param_2 + 0x4b) < '\x01')) {
|
|
uVar22 = uVar22 & 0xbfffffff;
|
|
}
|
|
iVar21 = (int)*(short *)(param_2 + 0x38e);
|
|
if (iVar21 < 0) {
|
|
iVar21 = -iVar21;
|
|
}
|
|
if (iVar21 < 0x300) {
|
|
uVar22 = uVar22 & 0x9fffffff;
|
|
}
|
|
|
|
iVar21 = 0;
|
|
|
|
// VehPhysGeneral_GetBaseSpeed
|
|
iVar10 = FUN_80061488(param_2);
|
|
uVar7 = (undefined2)iVar10;
|
|
|
|
// If you are not holding Square
|
|
if (local_34 == 0) {
|
|
//iVar23 = Racer's Base Speed
|
|
iVar23 = iVar10;
|
|
|
|
// If you are holding Cross, or if you have Reserves
|
|
if (local_38 != 0) {
|
|
LAB_8006253c:
|
|
uVar22 = uVar22 & 0xfffdffff;
|
|
goto LAB_80062548;
|
|
}
|
|
|
|
// if you are not holding cross, or have no Reserves...
|
|
//iVar23 is replaced
|
|
|
|
// VehPhysJoystick_ReturnToRest
|
|
iVar23 = FUN_8006163c(iVar8,0x80,0);
|
|
|
|
iVar8 = -iVar23;
|
|
if (iVar23 < 1) {
|
|
if ((iVar8 == 0) &&
|
|
|
|
// VehPhysJoystick_ReturnToRest
|
|
((iVar19 = FUN_8006163c(iVar19,0x80,0), 99 < iVar19 ||
|
|
|
|
((0 < iVar19 && ((uVar22 & 0x20000) != 0))))))
|
|
{
|
|
// driver is steering?
|
|
uVar22 = uVar22 | 0x20000;
|
|
|
|
iVar23 = -(int)*(short *)(param_2 + 0x434);
|
|
goto LAB_80062548;
|
|
}
|
|
iVar8 = iVar10 * iVar8;
|
|
iVar23 = iVar8 >> 7;
|
|
if (iVar8 < 0) {
|
|
iVar23 = iVar8 + 0x7f >> 7;
|
|
}
|
|
goto LAB_8006253c;
|
|
}
|
|
if ((*(short *)(param_2 + 0x38e) < 0x301) && ((uVar22 & 0x60000000) == 0)) {
|
|
iVar8 = *(short *)(param_2 + 0x434) * iVar8;
|
|
if (iVar8 < 0) {
|
|
iVar8 = iVar8 + 0x7f;
|
|
}
|
|
iVar21 = iVar8 >> 7;
|
|
uVar15 = 0x20000;
|
|
LAB_800625c4:
|
|
uVar20 = uVar22 | uVar15;
|
|
}
|
|
else {
|
|
uVar20 = uVar22 | 8;
|
|
if ('\0' < *(char *)(param_2 + 0x4b)) {
|
|
uVar20 = uVar22 | 0x40000008;
|
|
}
|
|
if (*(char *)(param_2 + 0x4b) < '\0') {
|
|
uVar15 = 0x20000000;
|
|
uVar22 = uVar20;
|
|
goto LAB_800625c4;
|
|
}
|
|
}
|
|
}
|
|
// If you are holding Square
|
|
else
|
|
{
|
|
// VehPhysJoystick_ReturnToRest
|
|
iVar19 = FUN_8006163c(iVar19,0x80,0);
|
|
|
|
if ((iVar19 < 100) && ((iVar19 < 1 || ((uVar22 & 0x20000) == 0))))
|
|
{
|
|
// if you are not holding cross, and you have no Reserves
|
|
if (local_38 == 0)
|
|
{
|
|
// VehPhysJoystick_ReturnToRest
|
|
iVar8 = FUN_8006163c(iVar8,0x80,0);
|
|
|
|
iVar23 = iVar10 * -iVar8;
|
|
if (iVar8 < 0) {
|
|
if (iVar23 < 0) {
|
|
iVar23 = iVar23 + 0xff;
|
|
}
|
|
iVar23 = iVar23 >> 8;
|
|
|
|
// gas and breaks together
|
|
uVar22 = uVar22 | 0x20;
|
|
|
|
goto LAB_80062548;
|
|
}
|
|
|
|
if (0 < iVar8) {
|
|
iVar8 = (int)*(short *)(param_2 + 0x434) * -iVar8;
|
|
iVar23 = iVar8 >> 8;
|
|
if (iVar8 < 0) {
|
|
iVar23 = iVar8 + 0xff >> 8;
|
|
}
|
|
|
|
// reversing, and gas+break
|
|
goto LAB_8006248c;
|
|
}
|
|
uVar22 = uVar22 | 8;
|
|
iVar23 = iVar21;
|
|
}
|
|
// If you are holding cross, or you have Reserves
|
|
else {
|
|
uVar22 = uVar22 | 0x20;
|
|
iVar23 = iVar10 / 2;
|
|
}
|
|
goto LAB_8006253c;
|
|
}
|
|
iVar8 = (int)*(short *)(param_2 + 0x434) * -3;
|
|
iVar23 = iVar8 >> 2;
|
|
if (iVar8 < 0) {
|
|
iVar23 = iVar8 + 3 >> 2;
|
|
}
|
|
LAB_8006248c:
|
|
uVar22 = uVar22 | 0x20020;
|
|
LAB_80062548:
|
|
uVar20 = uVar22 & 0x9fffffff;
|
|
//iVar21 = Racer's Base Speed
|
|
iVar21 = iVar23;
|
|
}
|
|
|
|
if ((uVar20 & 0x20000) == 0)
|
|
{
|
|
uVar22 = uVar20 & 8;
|
|
if (*(short *)(param_2 + 0x38) != 0) {
|
|
//if Racer is moving
|
|
if (0 < iVar21) {
|
|
uVar22 = uVar20 & 8;
|
|
if ((uVar20 & 0x400020) != 0) goto LAB_80062648;
|
|
|
|
// if you have less than 10 wumpa
|
|
uVar16 = 0x80;
|
|
|
|
*(uint *)(param_2 + 0x2c8) = uVar20;
|
|
|
|
// if 9 < number of wumpa
|
|
// if wumpa is 10
|
|
if ('\t' < *(char *)(param_2 + 0x30)) {
|
|
uVar16 = 0x100;
|
|
}
|
|
|
|
// VehFire_Increment
|
|
// add 0.12s reserves
|
|
FUN_8005abfc(param_2,0x78,0x14,uVar16);
|
|
|
|
uVar20 = *(uint *)(param_2 + 0x2c8);
|
|
}
|
|
goto code_r0x80062644;
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
// Increase amount of time reversing,
|
|
// counts whenever holding "down" on d-pad
|
|
*(int *)(param_2 + 0x520) = *(int *)(param_2 + 0x520) + iVar14;
|
|
code_r0x80062644:
|
|
uVar22 = uVar20 & 8;
|
|
}
|
|
|
|
LAB_80062648:
|
|
if (uVar22 != 0) {
|
|
iVar8 = (int)*(short *)(param_2 + 0x38e);
|
|
if (iVar8 < 0) {
|
|
iVar8 = -iVar8;
|
|
}
|
|
|
|
if (0x300 < iVar8)
|
|
{
|
|
// record amount of time with high speed
|
|
*(int *)(param_2 + 0x51c) = *(int *)(param_2 + 0x51c) + iVar14;
|
|
}
|
|
}
|
|
|
|
if ((*(short *)(param_2 + 0x3c0) == 0) ||
|
|
|
|
// kart state not 0, and kart state not 9
|
|
((*(char *)(param_2 + 0x376) != '\0' && (*(char *)(param_2 + 0x376) != '\t'))))
|
|
{
|
|
*(undefined2 *)(param_2 + 0x3c2) = 0;
|
|
}
|
|
|
|
if (*(short *)(param_2 + 0x39e) < 1) {
|
|
//if Racer is moving, skip next 4 lines of code
|
|
if (0 < iVar21) goto LAB_800626d4;
|
|
LAB_800626fc:
|
|
//Racer struct + 0x39E = Racer's Base Speed
|
|
*(undefined2 *)(param_2 + 0x39e) = (short)iVar21;
|
|
}
|
|
else {
|
|
//if Racer is not moving
|
|
if (iVar21 < 1) {
|
|
LAB_800626d4:
|
|
if (*(short *)(param_2 + 0x3c0) != 0) {
|
|
*(short *)(param_2 + 0x3c2) = *(short *)(param_2 + 0x3c2) + 1;
|
|
}
|
|
*(undefined2 *)(param_2 + 0x3c0) = 0x100;
|
|
goto LAB_800626fc;
|
|
}
|
|
//Racer struct + 0x39E = Racer's Base Speed
|
|
*(undefined2 *)(param_2 + 0x39e) = (short)iVar21;
|
|
}
|
|
if ((uVar20 & 0x800020) == 0) {
|
|
iVar8 = *(int *)(*(int *)(param_2 + 0x35c) + 8);
|
|
//if racer is out of normal driving conditions?
|
|
//for example, 0x35C[0x8] is 0xB4 when in water at Cove
|
|
//and the value of 0x39C fits the result perfectly
|
|
if (iVar8 != 0x100) {
|
|
//Base Speed = 0xB4 (at Cove water) * Base Speed >> 8
|
|
iVar21 = iVar8 * iVar21 >> 8;
|
|
uVar7 = (undefined2)((uint)(iVar8 * iVar10) >> 8);
|
|
}
|
|
}
|
|
*(undefined2 *)(param_2 + 0x3c4) = uVar7;
|
|
//Basic Speed = iVar21
|
|
*(undefined2 *)(param_2 + 0x39c) = (short)iVar21;
|
|
|
|
// assume neutral steer (drive straight)
|
|
iVar8 = 0x80;
|
|
|
|
puVar5 = PTR_DAT_8008d2ac;
|
|
|
|
// If you're not in End-Of-Race menu
|
|
if ((*(uint *)puVar5 & 0x200000) == 0)
|
|
{
|
|
// gamepadBuffer -> stickLX
|
|
iVar8 = (int)*(short *)(puVar24 + 4);
|
|
}
|
|
|
|
iVar14 = (uint)*(byte *)(param_2 + 0x43a) + ((int)*(char *)(param_2 + 0x34) << 1) / 5;
|
|
if ((*(short *)(param_2 + 0x3c2) < 7) || (0x25ff < iVar11)) {
|
|
if (*(short *)(param_2 + 0x3fe) == 0) {
|
|
if ((uVar20 & 0x28) == 0)
|
|
{
|
|
// gamepadBuffer -> racingWheelData
|
|
uVar16 = *(undefined4 *)(puVar24 + 0x4c);
|
|
}
|
|
else
|
|
{
|
|
// if you are not holding cross
|
|
if (local_38 == 0)
|
|
{
|
|
// gamepadBuffer -> racingWheelData
|
|
uVar16 = *(undefined4 *)(puVar24 + 0x4c);
|
|
|
|
iVar14 = 0x40;
|
|
}
|
|
|
|
// if you are holding cross
|
|
else
|
|
{
|
|
// get speed
|
|
iVar19 = (int)*(short *)(param_2 + 0x38c);
|
|
|
|
// set speed to absolute value
|
|
if (iVar19 < 0) {
|
|
iVar19 = -iVar19;
|
|
}
|
|
|
|
// Map value from [oldMin, oldMax] to [newMin, newMax]
|
|
// inverting newMin and newMax will give an inverse range mapping
|
|
iVar14 = FUN_80058f9c(iVar19,0x300,
|
|
(int)((uint)*(ushort *)(param_2 + 0x42c) << 0x10) >> 0x11,0x40,
|
|
iVar14);
|
|
|
|
// gamepadBuffer -> racingWheelData
|
|
uVar16 = *(undefined4 *)(puVar24 + 0x4c);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// gamepadBuffer -> racingWheelData
|
|
uVar16 = *(undefined4 *)(puVar24 + 0x4c);
|
|
iVar14 = 0x30;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// gamepadBuffer -> racingWheelData
|
|
uVar16 = *(undefined4 *)(puVar24 + 0x4c);
|
|
|
|
iVar14 = 0x5a;
|
|
}
|
|
|
|
// Steer
|
|
iVar14 = FUN_800617cc(iVar8,iVar14,uVar16);
|
|
|
|
if (-iVar14 == 0) {
|
|
*(undefined2 *)(param_2 + 0x3e6) = 10000;
|
|
}
|
|
else {
|
|
if ((iVar14 < 1) || (*(char *)(param_2 + 0x4b) < '\0')) {
|
|
if ((-1 < iVar14) || ('\0' < *(char *)(param_2 + 0x4b))) goto LAB_800628b0;
|
|
uVar20 = uVar20 | 0x10;
|
|
}
|
|
else {
|
|
uVar20 = uVar20 & 0xffffffef;
|
|
}
|
|
*(undefined2 *)(param_2 + 0x3e6) = 0;
|
|
}
|
|
LAB_800628b0:
|
|
*(undefined *)(param_2 + 0x4b) = (char)-iVar14;
|
|
|
|
// Steer
|
|
iVar8 = FUN_800617cc(iVar8,0x40,*(undefined4 *)(puVar24 + 0x4c));
|
|
|
|
// Interpolate rotation by speed
|
|
uVar7 = FUN_80058f54((int)*(short *)(param_2 + 6),0x18,-iVar8);
|
|
|
|
iVar8 = (int)*(short *)(param_2 + 0x39e);
|
|
*(undefined2 *)(param_2 + 6) = uVar7;
|
|
if (iVar8 < 0) {
|
|
iVar8 = -iVar8;
|
|
}
|
|
if (((*(uint *)(param_2 + 0x2cc) & 1) == 0) || (cVar1 == '\x02')) {
|
|
iVar8 = iVar8 + 0xf00;
|
|
}
|
|
else {
|
|
iVar8 = iVar8 + iVar11 >> 1;
|
|
}
|
|
sVar13 = (short)((iVar8 * 0x89 + (int)*(short *)(param_2 + 0x3be) * 0x177) * 8 >> 0xc);
|
|
*(short *)(param_2 + 0x3be) = sVar13;
|
|
if ((*(uint *)(param_2 + 0x2cc) & 8) == 0) {
|
|
//prevent Basic Speed from being negative
|
|
if (iVar21 < 0) {
|
|
iVar21 = -iVar21;
|
|
}
|
|
//if Base Speed > 0x200 or iVar11 = 0x200 (?)
|
|
if ((0x200 < iVar21) || (0x200 < iVar11)) {
|
|
*(short *)(param_2 + 0x3bc) = *(short *)(param_2 + 0x3bc) - sVar13;
|
|
}
|
|
}
|
|
//if 0x3BC <= 0 and last bit of jittery number 2 is off and
|
|
if (((*(short *)(param_2 + 0x3bc) < 1) && ((*(uint *)(param_2 + 8) & 1) == 0)) &&
|
|
(cVar1 != '\x04')) {
|
|
//reset 0x3BC
|
|
*(undefined2 *)(param_2 + 0x3bc) = 0x1e00;
|
|
//Jittery number 1
|
|
*(undefined4 *)(param_2 + 8) = 0x2e606061;
|
|
}
|
|
else {
|
|
//jittery number 2
|
|
*(undefined4 *)(param_2 + 8) = 0x2e808080;
|
|
}
|
|
LAB_800629f8:
|
|
*(uint *)(param_2 + 0x2c8) = uVar20;
|
|
return;
|
|
}
|
|
|
|
|
|
// VehPhysProc_Driving_Audio (universal)
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80062a2c(undefined4 param_1,undefined4 param_2)
|
|
{
|
|
// EngineSound_Player
|
|
FUN_8002f5f4(param_2);
|
|
return;
|
|
}
|
|
|
|
|
|
// VehPhysProc_Driving_Update
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80062a4c(undefined4 param_1,int param_2)
|
|
{
|
|
int iVar1;
|
|
|
|
//if racer touched the ground in this frame
|
|
if ((*(uint *)(param_2 + 0x2c8) & 2) != 0)
|
|
{
|
|
//iVar1 = Simplified Turning state
|
|
iVar1 = (int)*(char *)(param_2 + 0x4b);
|
|
|
|
//set Simplified Turning state to its own absolute value
|
|
if (iVar1 < 0) {
|
|
iVar1 = -iVar1;
|
|
}
|
|
|
|
if (
|
|
(
|
|
(
|
|
// if steering hard enough to start a drift
|
|
(
|
|
// (Character's Turn stat + (Turning multiplier? << 1) / 5) >> 1)
|
|
(int)((uint)*(byte *)(param_2 + 0x43a) +
|
|
((int)*(char *)(param_2 + 0x34) << 1) / 5) >> 1
|
|
|
|
// < Simplified turning state
|
|
< iVar1
|
|
) &&
|
|
|
|
(
|
|
//player has jump buttons held
|
|
(*(uint *)(PTR_DAT_8008d2b0 + (uint)*(byte *)(param_2 + 0x4a) * 0x50 + 0x10) &
|
|
(int)*(short *)(param_2 + 0x382)) != 0
|
|
)
|
|
) &&
|
|
|
|
//player is not in accel prevention or braking and
|
|
((*(uint *)(param_2 + 0x2c8) & 8) == 0)
|
|
) &&
|
|
|
|
//Character's Speed stat (divided by 2?) <= Speed Approximate
|
|
(
|
|
(int)((uint)*(ushort *)(param_2 + 0x42c) << 0x10) >> 0x11 <=
|
|
(int)*(short *)(param_2 + 0x38e)
|
|
)
|
|
)
|
|
{
|
|
// VehPhysProc_PowerSlide_Init
|
|
FUN_80063934(param_1);
|
|
|
|
//exit the function
|
|
return;
|
|
}
|
|
}
|
|
|
|
// at this point, assume driver is not touching ground
|
|
|
|
if (
|
|
// if driver has been "Player_Driving" more than 0.1 seconds?
|
|
(*(short *)(param_2 + 0x406) == 0) &&
|
|
|
|
// if V_Shift happened too many times,
|
|
// meaning you jitter between two quadblocks
|
|
// in a "V" shape
|
|
(4 < *(short *)(param_2 + 0x40a))
|
|
)
|
|
{
|
|
|
|
// Stop driving, until you press X, prevents jitters
|
|
|
|
// VehPhysProc_FreezeVShift_Init
|
|
FUN_80062e94(param_1);
|
|
}
|
|
|
|
else {
|
|
|
|
// if driver has been "rolling backwards" more than 0.64 seconds
|
|
if (*(short *)(param_2 + 0x408) == 0)
|
|
{
|
|
// wipe
|
|
*(undefined2 *)(param_2 + 0x40a) = 0;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
// VehPhysProc_Driving_Init
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80062b74(undefined4 param_1,int param_2)
|
|
{
|
|
// spawn function that gives you immediate control,
|
|
// used for adventure spawn, and dropping a mask-grab
|
|
|
|
int iVar1;
|
|
|
|
// This if-statement prevents driving in Main Menu,
|
|
// Cutscenes, Naughty Dog Box Scene, etc
|
|
|
|
if (
|
|
// if Level ID is not an adv hub
|
|
(4 < *(int *)(PTR_DAT_8008d2ac + 0x1a10) - 0x19U) ||
|
|
(
|
|
// or, this is an adv hub, and 232 is loaded
|
|
|
|
//if 232 dll is loaded
|
|
iVar1 = FUN_80034920(),
|
|
iVar1 != 0
|
|
)
|
|
)
|
|
{
|
|
if (
|
|
// If you're in Battle Mode and
|
|
((*(uint *)PTR_DAT_8008d2ac & 0x20) != 0) &&
|
|
|
|
//player is blasted
|
|
(*(char *)(param_2 + 0x376) == '\x06')
|
|
)
|
|
{
|
|
//set Invincibility Timer to 0xB40
|
|
*(undefined4 *)(param_2 + 0x24) = 0xb40;
|
|
}
|
|
|
|
*(undefined2 *)(param_2 + 0x406) = 0x60;
|
|
*(undefined2 *)(param_2 + 0x408) = 0x280;
|
|
|
|
// VehPhysProc_Driving_Update
|
|
*(undefined4 *)(param_2 + 0x58) = 0x80062a4c;
|
|
|
|
// VehPhysProc_Driving_PhysLinear
|
|
*(undefined4 *)(param_2 + 0x5c) = 0x8006181c;
|
|
|
|
*(undefined4 *)(param_2 + 0x60) = 0x80062a2c; // OnAudio
|
|
*(undefined4 *)(param_2 + 100) = 0x8005fc8c; // OnPhysAngular
|
|
*(undefined4 *)(param_2 + 0x68) = 0x8005ea60; // VehPhysForce_OnApplyForces
|
|
*(undefined4 *)(param_2 + 0x6c) = 0x80020410; // COLL_StartSearch_NearPlayer
|
|
*(undefined4 *)(param_2 + 0x70) = 0x8005ebac; // VehPhysForce_CollideDrivers
|
|
*(undefined4 *)(param_2 + 0x74) = 0x8001d944; // COLL_StartSearch_Player
|
|
*(undefined4 *)(param_2 + 0x78) = 0x80060630; // JumpAndFriction
|
|
*(undefined4 *)(param_2 + 0x7c) = 0x8005ee34; // VehPhysForce_TranslateMatrix -- move position to instance matrix
|
|
*(undefined4 *)(param_2 + 0x80) = 0x8005b178; // VehFrameProc_Driving
|
|
|
|
//Kart state = normal
|
|
*(undefined *)(param_2 + 0x376) = 0;
|
|
|
|
//Turbo meter = full
|
|
*(undefined2 *)(param_2 + 0x3dc) = 0;
|
|
|
|
*(undefined2 *)(param_2 + 0x40a) = 0;
|
|
*(undefined4 *)(param_2 + 0x54) = 0;
|
|
|
|
// VehEmitter_DriverMain
|
|
*(undefined4 *)(param_2 + 0x84) = 0x80059a18;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// VehPhysProc_FreezeEndEvent_PhysLinear
|
|
void FUN_80062ca8(undefined4 param_1,int param_2)
|
|
{
|
|
uint uVar1;
|
|
|
|
// VehPhysProc_Driving_PhysLinear
|
|
FUN_8006181c();
|
|
|
|
// get flags
|
|
uVar1 = *(uint *)(param_2 + 0x2c8);
|
|
|
|
// reset two speed variables
|
|
*(undefined2 *)(param_2 + 0x39c) = 0;
|
|
*(undefined2 *)(param_2 + 0x39e) = 0;
|
|
|
|
// reset amplified turn state
|
|
*(undefined2 *)(param_2 + 0xc0) = 0;
|
|
|
|
// reset turn state
|
|
*(undefined *)(param_2 + 0x4b) = 0;
|
|
|
|
// reset wheel Y rotation
|
|
*(undefined2 *)(param_2 + 6) = 0;
|
|
|
|
// edit flags
|
|
*(uint *)(param_2 + 0x2c8) = uVar1 | 8;
|
|
*(uint *)(param_2 + 0x2c8) = uVar1 & 0xfffffffb | 8;
|
|
|
|
if (0 < *(short *)(param_2 + 0x3f0)) {
|
|
*(undefined2 *)(param_2 + 0x3f0) = 0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
// VehPhysProc_FreezeEndEvent_Init
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80062d04(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
if (*(char *)(param_2 + 0x376) != 0xb)
|
|
{
|
|
// VehPhysProc_FreezeEndEvent_PhysLinear
|
|
*(undefined4 *)(param_2 + 0x5c) = 0x80062ca8;
|
|
|
|
*(undefined4 *)(param_2 + 0x60) = 0x80062a2c; // OnAudio
|
|
*(undefined4 *)(param_2 + 100) = 0x8005fc8c; // OnPhysAngular
|
|
*(undefined4 *)(param_2 + 0x68) = 0x8005ea60; // VehPhysForce_OnApplyForces
|
|
*(undefined4 *)(param_2 + 0x6c) = 0x80020410; // COLL_StartSearch_NearPlayer
|
|
*(undefined4 *)(param_2 + 0x70) = 0x8005ebac; // VehPhysForce_CollideDrivers
|
|
*(undefined4 *)(param_2 + 0x74) = 0x8001d944; // COLL_StartSearch_Player
|
|
*(undefined4 *)(param_2 + 0x78) = 0x80060630; // JumpAndFriction
|
|
*(undefined4 *)(param_2 + 0x7c) = 0x8005ee34; // VehPhysForce_TranslateMatrix -- move position to instance matrix
|
|
*(undefined4 *)(param_2 + 0x80) = 0x8005b178; // VehFrameProc_Driving
|
|
|
|
// kart state = 11
|
|
*(undefined *)(param_2 + 0x376) = 0xb;
|
|
|
|
*(undefined2 *)(param_2 + 0x38c) = 0;
|
|
*(undefined2 *)(param_2 + 0x38e) = 0;
|
|
*(undefined4 *)(param_2 + 0x54) = 0;
|
|
*(undefined4 *)(param_2 + 0x58) = 0;
|
|
|
|
// VehEmitter_DriverMain
|
|
*(undefined4 *)(param_2 + 0x84) = 0x80059a18;
|
|
}
|
|
return;
|
|
}
|
|
|
|
// VehPhysProc_FreezeVShift_Update
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80062db0(undefined4 param_1,int param_2)
|
|
//seems to handle end of blasted effect
|
|
{
|
|
//if 0x39E of player struct = 0 and
|
|
//(player is not in accel prevention (4),
|
|
//not pressing Square (4, 6),
|
|
if (
|
|
(*(short *)(param_2 + 0x39e) == 0) &&
|
|
|
|
// not in player-on-player collision
|
|
((*(uint *)(param_2 + 0x2c8) & 0x10000028) == 0)
|
|
)
|
|
{
|
|
//player's speed = 0
|
|
*(undefined2 *)(param_2 + 0x38c) = 0;
|
|
|
|
//player's speed approximate = 0
|
|
*(undefined2 *)(param_2 + 0x38e) = 0;
|
|
}
|
|
else
|
|
{
|
|
// VehPhysProc_Driving_Init
|
|
FUN_80062b74();
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// VehPhysProc_FreezeVShift_ReverseOneFrame
|
|
// param1 = thread, param2 = driver
|
|
// reverse one frame of position
|
|
void FUN_80062e04(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
// VehPhysGeneral_JumpAndFriction
|
|
FUN_80060630();
|
|
|
|
// if player did not start jumping this frame
|
|
if ((*(uint *)(param_2 + 0x2c8) & 0x400) == 0)
|
|
{
|
|
// if there are not two humans colliding
|
|
if ((*(uint *)(param_2 + 0x2c8) & 0x10000000) == 0)
|
|
{
|
|
// remove speed (x, y, z)
|
|
*(undefined4 *)(param_2 + 0x3a0) = 0;
|
|
*(undefined4 *)(param_2 + 0x3a4) = 0;
|
|
*(undefined4 *)(param_2 + 0x3a8) = 0;
|
|
|
|
// remove speed and speedApprox
|
|
*(undefined2 *)(param_2 + 0x38c) = 0;
|
|
*(undefined2 *)(param_2 + 0x38e) = 0;
|
|
|
|
// set position to previous position
|
|
*(undefined4 *)(param_2 + 0x2d4) = *(undefined4 *)(param_2 + 0x2e0);
|
|
*(undefined4 *)(param_2 + 0x2d8) = *(undefined4 *)(param_2 + 0x2e4);
|
|
*(undefined4 *)(param_2 + 0x2dc) = *(undefined4 *)(param_2 + 0x2e8);
|
|
}
|
|
}
|
|
|
|
// if player did start jumping this frame
|
|
else
|
|
{
|
|
// VehPhysProc_Driving_Init
|
|
FUN_80062b74(param_1,param_2);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
// VehPhysProc_FreezeVShift_Init
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80062e94(undefined4 param_1,int param_2)
|
|
{
|
|
// kart state 9
|
|
*(undefined *)(param_2 + 0x376) = 9;
|
|
|
|
// OnUpdate
|
|
*(undefined4 *)(param_2 + 0x58) = 0x80062db0;
|
|
|
|
// VehPhysProc_Driving_PhysLinear
|
|
*(undefined4 *)(param_2 + 0x5c) = 0x8006181c;
|
|
|
|
*(undefined4 *)(param_2 + 0x60) = 0x80062a2c; // OnAudio
|
|
*(undefined4 *)(param_2 + 100) = 0x8005fc8c; // OnPhysAngular
|
|
*(undefined4 *)(param_2 + 0x68) = 0x8005ea60; // VehPhysForce_OnApplyForces
|
|
*(undefined4 *)(param_2 + 0x6c) = 0x80020410; // COLL_StartSearch_NearPlayer
|
|
*(undefined4 *)(param_2 + 0x70) = 0x8005ebac; // VehPhysForce_CollideDrivers
|
|
*(undefined4 *)(param_2 + 0x74) = 0x8001d944; // COLL_StartSearch_Player
|
|
*(undefined4 *)(param_2 + 0x78) = 0x80062e04; // alter jump mechanics
|
|
*(undefined4 *)(param_2 + 0x7c) = 0x8005ee34; // VehPhysForce_TranslateMatrix -- move position to instance matrix
|
|
*(undefined4 *)(param_2 + 0x80) = 0x8005b178; // VehFrameProc_Driving
|
|
|
|
//Turbo meter = full
|
|
*(undefined2 *)(param_2 + 0x3dc) = 0;
|
|
|
|
*(undefined4 *)(param_2 + 0x54) = 0;
|
|
|
|
// VehEmitter_DriverMain
|
|
*(undefined4 *)(param_2 + 0x84) = 0x80059a18;
|
|
|
|
//turn off 29th flag of actions flag set (means players dont collide anymore)
|
|
*(uint *)(param_2 + 0x2c8) = *(uint *)(param_2 + 0x2c8) & 0xefffffff;
|
|
return;
|
|
}
|
|
|
|
// VehPhysProc_PowerSlide_PhysAngular
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80062f4c(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
char cVar1;
|
|
bool bVar2;
|
|
bool bVar3;
|
|
undefined *puVar4;
|
|
short sVar5;
|
|
undefined2 uVar6;
|
|
ushort uVar7;
|
|
int iVar8;
|
|
int iVar9;
|
|
uint uVar10;
|
|
int iVar11;
|
|
int iVar12;
|
|
int iVar13;
|
|
uint uVar14;
|
|
int iVar15;
|
|
|
|
iVar12 = (((int)*(short *)(param_2 + 0x396) - (int)*(short *)(param_2 + 0x39a)) + 0x800U & 0xfff)
|
|
- 0x800;
|
|
iVar13 = iVar12 >> 3;
|
|
if (iVar12 != 0) {
|
|
if (iVar13 == 0) {
|
|
iVar13 = 1;
|
|
}
|
|
|
|
// elapsed milliseconds per frame, ~32
|
|
iVar12 = (*(int *)(PTR_DAT_8008d2ac + 0x1d04) << 6) >> 5;
|
|
|
|
if (iVar12 < iVar13) {
|
|
iVar13 = iVar12;
|
|
}
|
|
sVar5 = (short)iVar13;
|
|
if (iVar13 < -iVar12) {
|
|
sVar5 = (short)-iVar12;
|
|
}
|
|
|
|
// change player rotation
|
|
*(short *)(param_2 + 0x39a) = *(short *)(param_2 + 0x39a) + sVar5;
|
|
|
|
*(ushort *)(param_2 + 0x396) = *(short *)(param_2 + 0x396) - sVar5 & 0xfff;
|
|
}
|
|
|
|
if (*(short *)(param_2 + 0x3da) < 0)
|
|
{
|
|
// negative cam spin rate
|
|
iVar13 = -(int)*(short *)(param_2 + 0x468);
|
|
}
|
|
else
|
|
{
|
|
// positive cam spin rate
|
|
iVar13 = (int)*(short *)(param_2 + 0x468);
|
|
}
|
|
|
|
// get camera rotation
|
|
iVar12 = *(short *)(param_2 + 0x2f2) - iVar13;
|
|
|
|
// make sure it's not negative
|
|
if (iVar12 < 0) {
|
|
iVar12 = -iVar12;
|
|
}
|
|
|
|
uVar14 = iVar12 >> 3;
|
|
if (uVar14 == 0) {
|
|
uVar14 = 1;
|
|
}
|
|
uVar10 = (uint)*(byte *)(param_2 + 0x46a);
|
|
if ((int)uVar14 < (int)(uint)*(byte *)(param_2 + 0x46a)) {
|
|
uVar10 = uVar14;
|
|
}
|
|
|
|
// Interpolate rotation by speed
|
|
sVar5 = FUN_80058f54((int)*(short *)(param_2 + 0x2fa),8,uVar10);
|
|
puVar4 = PTR_DAT_8008d2ac;
|
|
*(short *)(param_2 + 0x2fa) = sVar5;
|
|
|
|
// Interpolate rotation by speed
|
|
uVar6 = FUN_80058f54((int)*(short *)(param_2 + 0x2f2),(int)sVar5 * *(int *)(puVar4 + 0x1d04) >> 5,
|
|
iVar13);
|
|
|
|
// turning rate
|
|
iVar12 = (int)*(short *)(param_2 + 0x3b4);
|
|
|
|
// drift direction
|
|
iVar15 = (int)*(short *)(param_2 + 0x3da);
|
|
|
|
bVar3 = false;
|
|
|
|
// set new rotation variable
|
|
*(undefined2 *)(param_2 + 0x2f2) = uVar6;
|
|
|
|
// simpTurningState
|
|
iVar9 = (int)*(char *)(param_2 + 0x4b);
|
|
|
|
iVar13 = iVar9 * 0x100;
|
|
|
|
// if drifting to the right
|
|
if (iVar15 < 0)
|
|
{
|
|
// if steering to the right
|
|
if (iVar13 < 1)
|
|
{
|
|
iVar13 = iVar9 * -0x100;
|
|
|
|
// const_SteerVel_DriftStandard
|
|
iVar9 = -(int)*(char *)(param_2 + 0x45f);
|
|
}
|
|
|
|
// if steering to the left
|
|
else
|
|
{
|
|
// const_SteerVel_DriftSwitchWay
|
|
iVar9 = -(int)*(char *)(param_2 + 0x45e);
|
|
}
|
|
}
|
|
|
|
// if drifting to the left
|
|
else
|
|
{
|
|
// if steering to the right
|
|
if (iVar13 < 0)
|
|
{
|
|
iVar13 = iVar9 * -0x100;
|
|
|
|
// const_SteerVel_DriftSwitchWay
|
|
cVar1 = *(char *)(param_2 + 0x45e);
|
|
}
|
|
|
|
// if steering to the left
|
|
else
|
|
{
|
|
// const_SteerVel_DriftStandard
|
|
cVar1 = *(char *)(param_2 + 0x45f);
|
|
}
|
|
|
|
iVar9 = (int)cVar1;
|
|
}
|
|
|
|
// Map "simpTurnState" from [0, const_TurnRate] to [0, driftDirection]
|
|
iVar13 = FUN_80058f9c(iVar13,0,((uint)*(byte *)(param_2 + 0x43a) +
|
|
((int)*(char *)(param_2 + 0x34) << 1) / 5) * 0x100,0,iVar9 << 8);
|
|
|
|
if (
|
|
(iVar13 < 0) ||
|
|
(
|
|
(
|
|
// compare two turning rates
|
|
bVar2 = iVar13 < iVar12,
|
|
|
|
iVar13 == 0 && (iVar12 < 0)
|
|
)
|
|
)
|
|
)
|
|
{
|
|
bVar3 = true;
|
|
iVar13 = -iVar13;
|
|
iVar12 = -iVar12;
|
|
iVar15 = -iVar15;
|
|
bVar2 = iVar13 < iVar12;
|
|
}
|
|
|
|
// 0x464 and 0x466 impact turning somehow
|
|
|
|
if (bVar2)
|
|
{
|
|
// elapsed milliseconds per frame, ~32
|
|
iVar12 = iVar12 - ((int)*(short *)(param_2 + 0x466) * *(int *)(PTR_DAT_8008d2ac + 0x1d04) >> 5);
|
|
bVar2 = iVar12 < iVar13;
|
|
}
|
|
else
|
|
{
|
|
// elapsed milliseconds per frame, ~32
|
|
iVar12 = iVar12 + ((int)*(short *)(param_2 + 0x464) * *(int *)(PTR_DAT_8008d2ac + 0x1d04) >> 5);
|
|
bVar2 = iVar13 < iVar12;
|
|
}
|
|
|
|
if (bVar2) {
|
|
iVar12 = iVar13;
|
|
}
|
|
|
|
// if not steering,
|
|
// then interpolate to "neutral" drift
|
|
if (iVar13 == 0)
|
|
{
|
|
LAB_80063244:
|
|
|
|
// Interpolate by 1 unit, until zero
|
|
uVar6 = FUN_80058f54((int)*(short *)(param_2 + 0x580),1,0);
|
|
*(undefined2 *)(param_2 + 0x580) = uVar6;
|
|
}
|
|
|
|
// if steering
|
|
else
|
|
{
|
|
// if drifting right
|
|
if (iVar15 < 1)
|
|
{
|
|
// if less than zero, reset to zero
|
|
if (-1 < iVar15) goto LAB_80063244;
|
|
|
|
// decrease positive number
|
|
uVar7 = *(short *)(param_2 + 0x580) - 1;
|
|
*(ushort *)(param_2 + 0x580) = uVar7;
|
|
|
|
// skip to zero if already positive
|
|
if (0 < (int)((uint)uVar7 << 0x10)) {
|
|
*(undefined2 *)(param_2 + 0x580) = 0;
|
|
}
|
|
}
|
|
|
|
// if drifting left
|
|
else
|
|
{
|
|
// increase number
|
|
uVar7 = *(short *)(param_2 + 0x580) + 1;
|
|
*(ushort *)(param_2 + 0x580) = uVar7;
|
|
|
|
// skip to zero if already negative
|
|
if ((int)((uint)uVar7 << 0x10) < 0) {
|
|
*(undefined2 *)(param_2 + 0x580) = 0;
|
|
}
|
|
}
|
|
}
|
|
if (bVar3) {
|
|
iVar12 = -iVar12;
|
|
iVar15 = -iVar15;
|
|
}
|
|
|
|
// Map value from [oldMin, oldMax] to [newMin, newMax]
|
|
// inverting newMin and newMax will give an inverse range mapping
|
|
iVar13 = FUN_80058f9c((int)*(short *)(param_2 + 0x584),0,(uint)*(byte *)(param_2 + 0x462) << 5,
|
|
(int)*(char *)(param_2 + 0x461) * (int)*(short *)(param_2 + 0x3da) >> 8,
|
|
iVar15);
|
|
if (-1 < iVar13) {
|
|
if (iVar12 < -iVar13) {
|
|
iVar12 = -iVar13;
|
|
}
|
|
sVar5 = (short)iVar12;
|
|
if (0 < iVar13) goto LAB_800632cc;
|
|
}
|
|
sVar5 = (short)iVar12;
|
|
if (-iVar13 < iVar12) {
|
|
sVar5 = (short)-iVar13;
|
|
}
|
|
LAB_800632cc:
|
|
iVar12 = iVar13;
|
|
if (iVar13 < 0) {
|
|
iVar12 = -iVar13;
|
|
}
|
|
*(short *)(param_2 + 0x3b4) = sVar5;
|
|
iVar9 = (int)sVar5;
|
|
|
|
// Map value from [oldMin, oldMax] to [newMin, newMax]
|
|
// inverting newMin and newMax will give an inverse range mapping
|
|
iVar12 = FUN_80058f9c(iVar12,0,(int)*(char *)(param_2 + 0x460) +
|
|
((int)*(char *)(param_2 + 0x34) << 2) / 5,0,
|
|
(int)*(short *)(param_2 + 0x474));
|
|
|
|
iVar15 = iVar9;
|
|
|
|
if (iVar13 < 0)
|
|
{
|
|
iVar12 = -iVar12;
|
|
|
|
if (iVar9 < 0)
|
|
{
|
|
if (iVar9 < 0) {
|
|
iVar15 = -iVar9;
|
|
}
|
|
|
|
// const_SteerVel_DriftStandard
|
|
iVar11 = (int)*(char *)(param_2 + 0x45f) << 8;
|
|
|
|
iVar8 = -(int)*(short *)(param_2 + 0x470);
|
|
}
|
|
|
|
else
|
|
{
|
|
// const_SteerVel_DriftSwitchWay
|
|
iVar11 = (int)*(char *)(param_2 + 0x45e) << 8;
|
|
|
|
iVar8 = -(int)*(short *)(param_2 + 0x472);
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
if (iVar9 < 0)
|
|
{
|
|
if (iVar9 < 0)
|
|
{
|
|
iVar15 = -iVar9;
|
|
}
|
|
|
|
// const_SteerVel_DriftSwitchWay
|
|
cVar1 = *(char *)(param_2 + 0x45e);
|
|
|
|
sVar5 = *(short *)(param_2 + 0x472);
|
|
}
|
|
|
|
else
|
|
{
|
|
// const_SteerVel_DriftStandard
|
|
cVar1 = *(char *)(param_2 + 0x45f);
|
|
|
|
sVar5 = *(short *)(param_2 + 0x470);
|
|
}
|
|
iVar8 = (int)sVar5;
|
|
iVar11 = (int)cVar1 << 8;
|
|
}
|
|
|
|
// Map value from [oldMin, oldMax] to [newMin, newMax]
|
|
// inverting newMin and newMax will give an inverse range mapping
|
|
iVar15 = FUN_80058f9c(iVar15,0,iVar11,0,iVar8);
|
|
iVar12 = (iVar12 + iVar15) - (int)*(short *)(param_2 + 0x3c6);
|
|
iVar15 = iVar12 >> 3;
|
|
sVar5 = (short)iVar15;
|
|
if (iVar12 != 0) {
|
|
if (iVar15 == 0) {
|
|
sVar5 = 1;
|
|
}
|
|
*(short *)(param_2 + 0x3c6) = *(short *)(param_2 + 0x3c6) + sVar5;
|
|
}
|
|
|
|
// numFramesDrifting (negative if switchway)
|
|
iVar12 = (int)*(short *)(param_2 + 0x580);
|
|
if (iVar12 < 0) {
|
|
iVar12 = -iVar12;
|
|
}
|
|
|
|
// get half of spin-out constant, this determines
|
|
// when to start making tire sound effects, after the
|
|
// turbo meter finishes filling past it's max capacity
|
|
|
|
// if you drift beyond the limit of the turbo meter
|
|
if ((int)(uint)(*(byte *)(param_2 + 0x463) >> 1) < iVar12)
|
|
{
|
|
iVar12 = (int)*(short *)(param_2 + 0x3d4);
|
|
if (iVar12 < 0) {
|
|
iVar12 = -iVar12;
|
|
}
|
|
if (iVar12 < 10) {
|
|
*(undefined2 *)(param_2 + 0x3d8) = 8;
|
|
*(undefined2 *)(param_2 + 0x3d6) = 0x14;
|
|
if (iVar13 < 0) {
|
|
*(undefined2 *)(param_2 + 0x3d6) = 0xffec;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
*(undefined2 *)(param_2 + 0x3d8) = 0;
|
|
}
|
|
|
|
iVar12 = (int)*(short *)(param_2 + 0x3d4);
|
|
if (iVar12 < 0) {
|
|
iVar12 = -iVar12;
|
|
}
|
|
|
|
if (0x32 < iVar12) {
|
|
*(undefined2 *)(param_2 + 0x3d8) = 0;
|
|
}
|
|
|
|
if (*(short *)(param_2 + 0x3d8) == 0) {
|
|
*(undefined2 *)(param_2 + 0x3d6) = 10;
|
|
if (0 < *(short *)(param_2 + 0x3d4)) {
|
|
*(undefined2 *)(param_2 + 0x3d6) = 0xfff6;
|
|
}
|
|
iVar12 = (int)*(short *)(param_2 + 0x3d6);
|
|
if (iVar12 < 0) {
|
|
iVar12 = -iVar12;
|
|
}
|
|
|
|
// Interpolate rotation by speed
|
|
sVar5 = FUN_80058f54((int)*(short *)(param_2 + 0x3d4),iVar12,0);
|
|
}
|
|
else {
|
|
*(short *)(param_2 + 0x3d8) = *(short *)(param_2 + 0x3d8) + -1;
|
|
sVar5 = *(short *)(param_2 + 0x3d4) + *(short *)(param_2 + 0x3d6);
|
|
}
|
|
*(short *)(param_2 + 0x3d4) = sVar5;
|
|
puVar4 = PTR_DAT_8008d2ac;
|
|
*(undefined2 *)(param_2 + 0xc0) = (short)(iVar9 + iVar13);
|
|
*(ushort *)(param_2 + 0x39a) =
|
|
*(short *)(param_2 + 0x39a) + (short)((iVar9 + iVar13) * *(int *)(puVar4 + 0x1d04) >> 0xd) &
|
|
0xfff;
|
|
|
|
if (*(short *)(param_2 + 0x582) != 0)
|
|
{
|
|
// decrease by elpased time
|
|
iVar13 = (uint)*(ushort *)(param_2 + 0x582) - (uint)*(ushort *)(puVar4 + 0x1d04);
|
|
*(undefined2 *)(param_2 + 0x582) = (short)iVar13;
|
|
if (iVar13 * 0x10000 < 0) {
|
|
*(undefined2 *)(param_2 + 0x582) = 0;
|
|
}
|
|
|
|
sVar5 = (short)((int)((uint)*(byte *)(param_2 + 0x47a) *
|
|
|
|
// elapsed milliseconds per frame, ~32
|
|
*(int *)(PTR_DAT_8008d2ac + 0x1d04)) >> 5);
|
|
|
|
if (*(short *)(param_2 + 0x3c6) < 0) {
|
|
sVar5 = -sVar5;
|
|
}
|
|
*(ushort *)(param_2 + 0x396) = *(short *)(param_2 + 0x396) + sVar5 & 0xfff;
|
|
}
|
|
|
|
puVar4 = PTR_DAT_8008d2ac;
|
|
*(short *)(param_2 + 0x2ee) =
|
|
*(short *)(param_2 + 0x3d4) + *(short *)(param_2 + 0x39a) + *(short *)(param_2 + 0x3c6);
|
|
|
|
// increment this by milliseconds
|
|
sVar5 = *(short *)(param_2 + 0x584) + *(short *)(puVar4 + 0x1d04);
|
|
*(short *)(param_2 + 0x584) = sVar5;
|
|
|
|
if ((int)((uint)*(byte *)(param_2 + 0x462) << 5) < (int)sVar5) {
|
|
*(short *)(param_2 + 0x584) = (ushort)*(byte *)(param_2 + 0x462) << 5;
|
|
}
|
|
|
|
// VehPhysForce_RotAxisAngle
|
|
FUN_8005f89c((undefined4 *)(param_2 + 0x310),param_2 + 0x360,(int)*(short *)(param_2 + 0x39a));
|
|
gte_SetRotMatrix((MATRIX *)(param_2 + 0x310));
|
|
|
|
// VehPhysForce_AccelTerrainSlope
|
|
FUN_8005fb4c(param_2);
|
|
return;
|
|
}
|
|
|
|
|
|
// VehPhysProc_PowerSlide_Finalize
|
|
void FUN_80063634(int param_1)
|
|
|
|
{
|
|
*(undefined2 *)(param_1 + 0x3ea) = *(undefined2 *)(param_1 + 0x3da);
|
|
*(short *)(param_1 + 0x3ec) = (ushort)*(byte *)(param_1 + 0x46b) << 5;
|
|
return;
|
|
}
|
|
|
|
|
|
// VehPhysProc_PowerSlide_Update
|
|
// param1 = thread, param2 = driver
|
|
void FUN_8006364c(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
char cVar1;
|
|
undefined2 uVar2;
|
|
undefined4 uVar3;
|
|
int iVar4;
|
|
int iVar5;
|
|
|
|
// If you do not press L1 or R1
|
|
if ((*(uint *)(PTR_DAT_8008d2b0 + (uint)*(byte *)(param_2 + 0x4a) * 0x50 + 0x14) & 0xc00) == 0) {
|
|
|
|
// If there is no room in the turbo meter left to fill
|
|
if (*(short *)(param_2 + 0x3dc) == 0) {
|
|
|
|
// If you have not attempted to boost 3 times in a row
|
|
if (*(char *)(param_2 + 0x586) < '\x03')
|
|
{
|
|
// set turbo meter to empty
|
|
*(short *)(param_2 + 0x3dc) = (ushort)*(byte *)(param_2 + 0x476) << 5;
|
|
}
|
|
}
|
|
|
|
// If the turbo meter is not full
|
|
else
|
|
{
|
|
// decreaes the amoutn of room remaining, by elapsed milliseconds per frame, ~32
|
|
iVar4 = (uint)*(ushort *)(param_2 + 0x3dc) - (uint)*(ushort *)(PTR_DAT_8008d2ac + 0x1d04);
|
|
*(undefined2 *)(param_2 + 0x3dc) = (short)iVar4;
|
|
|
|
// if the bar goes beyond full
|
|
if (iVar4 * 0x10000 < 0)
|
|
{
|
|
// set bar to full
|
|
*(undefined2 *)(param_2 + 0x3dc) = 0;
|
|
}
|
|
|
|
// If bar is full
|
|
if (*(short *)(param_2 + 0x3dc) == 0)
|
|
{
|
|
// Make a sound
|
|
FUN_80028494(0xf,1,(uint)*(ushort *)(param_2 + 0x2ca) & 1);
|
|
|
|
// Add to your number of boost attempts, this makes it
|
|
// so you can't attempt to boost again until you release L1 + R1
|
|
*(char *)(param_2 + 0x586) = *(char *)(param_2 + 0x586) + '\x03';
|
|
}
|
|
}
|
|
}
|
|
|
|
// If you do press L1 or R1
|
|
else {
|
|
|
|
// Get P1's turbo meter
|
|
// This is the distance remaining that can be filled
|
|
iVar4 = (int)*(short *)(param_2 + 0x3dc);
|
|
|
|
// Set drift timer to zero, start the drift
|
|
*(undefined2 *)(param_2 + 0x580) = 0;
|
|
|
|
// If turbo meter is not empty
|
|
if (iVar4 != 0) {
|
|
|
|
// const_turboLowRoomWarning
|
|
// get length where turbo turns from green to red
|
|
iVar5 = (uint)*(byte *)(param_2 + 0x477) << 5;
|
|
|
|
// If distance remaining to be filled in turbo bar, is less than,
|
|
// the distance remaining from the red/green "turning point" to the end,
|
|
|
|
// If meter is in the red
|
|
if (iVar4 < iVar5)
|
|
{
|
|
// reserves_gain = map from old range to new range,
|
|
// the more room remaining to fill, the less boost you get
|
|
// old minMax: [zero -> const_turboLowRoomWarning]
|
|
// new minMax: [const_turboFullBarReserveGain, -> zero]
|
|
uVar3 = FUN_80058f9c(iVar4,0,iVar5,(uint)*(byte *)(param_2 + 0x478) << 5,0);
|
|
|
|
// VehFire_Increment
|
|
FUN_8005abfc(
|
|
|
|
// driver
|
|
param_2,
|
|
|
|
// amount of reserves
|
|
uVar3,
|
|
|
|
2,
|
|
|
|
// fire level, bigger boost for attempt number (1,2, or 3)
|
|
(int)*(char *)(param_2 + 0x587) << 6);
|
|
|
|
|
|
// increase the counter for number of times you've boosted in a row (0-3)
|
|
cVar1 = *(char *)(param_2 + 0x587) + '\x01';
|
|
*(char *)(param_2 + 0x587) = cVar1;
|
|
|
|
// if you've boosted less than 3 times in a row
|
|
if (cVar1 < '\x03')
|
|
{
|
|
// give a chance to boost again
|
|
*(uint *)(param_2 + 0x2c8) = *(uint *)(param_2 + 0x2c8) | 0x80;
|
|
}
|
|
|
|
// drift boost meter = constant
|
|
*(short *)(param_2 + 0x582) = (ushort)*(byte *)(param_2 + 0x479) << 5;
|
|
}
|
|
|
|
// If meter is in the green
|
|
else
|
|
{
|
|
// reset meter to beginning
|
|
*(undefined *)(param_2 + 0x381) = 8;
|
|
}
|
|
|
|
*(undefined2 *)(param_2 + 0x3dc) = 0;
|
|
|
|
// increase number of boost attempts (both success and failure)
|
|
*(char *)(param_2 + 0x586) = *(char *)(param_2 + 0x586) + '\x01';
|
|
}
|
|
}
|
|
|
|
// 1.0 seconds
|
|
uVar2 = 0x3c0;
|
|
|
|
if (
|
|
// If the "spin-out" constant is less than your drift counter
|
|
((int)(uint)*(byte *)(param_2 + 0x463) < (int)*(short *)(param_2 + 0x580)) ||
|
|
|
|
(
|
|
(
|
|
*(short *)(param_2 + 0x38e) < 0 &&
|
|
(
|
|
// 2.0 seconds
|
|
uVar2 = 0x780,
|
|
|
|
// if you're not on any turbo pad
|
|
(*(uint *)(param_2 + 0xbc) & 3) == 0
|
|
)
|
|
)
|
|
)
|
|
)
|
|
{
|
|
// Make the character spin out from too much drifting
|
|
|
|
// Set amount of NoInput
|
|
*(undefined2 *)(param_2 + 0x400) = uVar2;
|
|
|
|
// VehPhysProc_SpinFirst_Init
|
|
FUN_80063ec0(param_1,param_2);
|
|
}
|
|
|
|
// if you aren't spinning out
|
|
else {
|
|
|
|
if (
|
|
// drift counter counts backwards during switchway drift: did switchway too long?
|
|
((int)*(short *)(param_2 + 0x580) < (int)-(uint)*(byte *)(param_2 + 0x463)) ||
|
|
|
|
((
|
|
// speed is less than half the driver's speed classStat
|
|
((int)*(short *)(param_2 + 0x38c) < (int)((uint)*(ushort *)(param_2 + 0x42c) << 0x10) >> 0x11 ||
|
|
|
|
((*(uint *)(param_2 + 0x2c8) & 0x2028) != 0)) ||
|
|
|
|
// If the gamepad input is...
|
|
((*(uint *)(PTR_DAT_8008d2b0 + (uint)*(byte *)(param_2 + 0x4a) * 0x50 + 0x10) &
|
|
|
|
// does not include the jump button that you used to start drifting
|
|
(int)*(short *)(param_2 + 0x382)) == 0)
|
|
))
|
|
)
|
|
{
|
|
// Stop drifting, just drive
|
|
|
|
// VehPhysProc_PowerSlide_Finalize
|
|
FUN_80063634(param_2);
|
|
|
|
// VehPhysProc_Driving_Init
|
|
FUN_80062b74(param_1,param_2);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// VehPhysProc_PowerSlide_PhysLinear
|
|
void FUN_800638d4(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
undefined *puVar1;
|
|
|
|
// VehPhysProc_Driving_PhysLinear
|
|
FUN_8006181c();
|
|
|
|
puVar1 = PTR_DAT_8008d2ac;
|
|
|
|
// driver is drifting (0x1000)
|
|
// driver is skidding (0x800)
|
|
*(uint *)(param_2 + 0x2c8) = *(uint *)(param_2 + 0x2c8) | 0x1800;
|
|
|
|
// drift timer += elapsed time
|
|
*(int *)(param_2 + 0x538) = *(int *)(param_2 + 0x538) + *(int *)(puVar1 + 0x1d04);
|
|
return;
|
|
}
|
|
|
|
// VehPhysProc_PowerSlide_InitSetUpdate
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80063920(undefined4 param_1,int param_2)
|
|
{
|
|
// This is so the update function
|
|
// is not called on the first frame,
|
|
// just like spinning
|
|
|
|
*(undefined4 *)(param_2 + 0x54) = 0;
|
|
|
|
// VehPhysProc_PowerSlide_Update
|
|
*(undefined4 *)(param_2 + 0x58) = 0x8006364c;
|
|
return;
|
|
}
|
|
|
|
// VehPhysProc_PowerSlide_Init
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80063934(undefined4 param_1,int param_2)
|
|
//seems to handle start of drifts
|
|
{
|
|
short sVar1;
|
|
|
|
//kart is drifting
|
|
*(undefined *)(param_2 + 0x376) = 2;
|
|
|
|
//sVar1 = Character's Drift stat + ((Turning multiplier? << 2) / 5)
|
|
sVar1 = (short)*(char *)(param_2 + 0x460) + (short)(((int)*(char *)(param_2 + 0x34) << 2) / 5);
|
|
|
|
//Multiplied drift = sVar1 * 100
|
|
*(short *)(param_2 + 0x3da) = sVar1 * 0x100;
|
|
|
|
//if simplified turning state is negative (means you're turning right)
|
|
if (*(char *)(param_2 + 0x4b) < '\0')
|
|
{
|
|
//also make Multiplied drift negative
|
|
*(short *)(param_2 + 0x3da) = sVar1 * -0x100;
|
|
}
|
|
|
|
// VehPhysProc_PowerSlide_InitSetUpdate
|
|
*(undefined4 *)(param_2 + 0x54) = 0x80063920;
|
|
|
|
// VehPhysProc_PowerSlide_PhysLinear
|
|
*(undefined4 *)(param_2 + 0x5c) = 0x800638d4;
|
|
|
|
*(undefined4 *)(param_2 + 0x60) = 0x80062a2c; // OnAudio
|
|
*(undefined4 *)(param_2 + 100) = 0x80062f4c; // OnPhysAngular
|
|
*(undefined4 *)(param_2 + 0x68) = 0x8005ea60; // VehPhysForce_OnApplyForces
|
|
*(undefined4 *)(param_2 + 0x6c) = 0x80020410; // COLL_StartSearch_NearPlayer
|
|
*(undefined4 *)(param_2 + 0x70) = 0x8005ebac; // VehPhysForce_CollideDrivers
|
|
*(undefined4 *)(param_2 + 0x74) = 0x8001d944; // COLL_StartSearch_Player
|
|
*(undefined4 *)(param_2 + 0x78) = 0x80060630; // JumpAndFriction
|
|
*(undefined4 *)(param_2 + 0x7c) = 0x8005ee34; // VehPhysForce_TranslateMatrix -- move position to instance matrix
|
|
*(undefined4 *)(param_2 + 0x80) = 0x8005b178; // VehFrameProc_Driving
|
|
|
|
// erase union in driver struct
|
|
*(undefined2 *)(param_2 + 0x580) = 0;
|
|
*(undefined2 *)(param_2 + 0x584) = 0;
|
|
*(undefined2 *)(param_2 + 0x582) = 0;
|
|
*(undefined *)(param_2 + 0x586) = 0;
|
|
*(undefined *)(param_2 + 0x587) = 0;
|
|
|
|
*(undefined2 *)(param_2 + 0x3b4) = 0;
|
|
*(undefined2 *)(param_2 + 0x3d2) = 0;
|
|
*(undefined2 *)(param_2 + 0x3ec) = 0;
|
|
*(undefined4 *)(param_2 + 0x58) = 0;
|
|
|
|
// VehEmitter_DriverMain
|
|
*(undefined4 *)(param_2 + 0x84) = 0x80059a18;
|
|
|
|
//Turbo meter space left to fill = Length of Turbo meter << 5
|
|
*(short *)(param_2 + 0x3dc) = (ushort)*(byte *)(param_2 + 0x476) << 5;
|
|
return;
|
|
}
|
|
|
|
// VehPhysProc_SlamWall_PhysAngular
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80063a44(undefined4 param_1,int param_2)
|
|
{
|
|
undefined *puVar1;
|
|
ushort uVar2;
|
|
undefined2 uVar3;
|
|
|
|
puVar1 = PTR_DAT_8008d2ac;
|
|
|
|
// increase spin by (lastFrameSpinRate * elapsedTime)
|
|
uVar2 = *(short *)(param_2 + 0x39a) + // elapsed milliseconds per frame, ~32
|
|
(short)((int)*(short *)(param_2 + 0xc0) * *(int *)(PTR_DAT_8008d2ac + 0x1d04) >> 0xd) &
|
|
0xfff;
|
|
|
|
*(ushort *)(param_2 + 0x39a) = uVar2;
|
|
|
|
// cameraRotY = spinRate + kart angle + drift angle,
|
|
// spin rate is added so you're one frame ahead
|
|
*(short *)(param_2 + 0x2ee) = *(short *)(param_2 + 0x3d4) + uVar2 + *(short *)(param_2 + 0x3c6);
|
|
|
|
// Interpolate rotation by speed
|
|
uVar3 = FUN_80058f54((int)*(short *)(param_2 + 0x2f2),(*(int *)(puVar1 + 0x1d04) << 5) >> 5,0);
|
|
|
|
puVar1 = PTR_DAT_8008d2ac;
|
|
|
|
// set camera rotation angle around player
|
|
*(undefined2 *)(param_2 + 0x2f2) = uVar3;
|
|
|
|
// Interpolate rotation by speed
|
|
uVar3 = FUN_80058f54((int)*(short *)(param_2 + 0x3c6),(*(int *)(puVar1 + 0x1d04) << 7) >> 5,0);
|
|
*(undefined2 *)(param_2 + 0x3c6) = uVar3;
|
|
|
|
// VehPhysForce_RotAxisAngle
|
|
FUN_8005f89c(param_2 + 0x310,param_2 + 0x360,(int)*(short *)(param_2 + 0x39a));
|
|
return;
|
|
}
|
|
|
|
// VehPhysProc_SlamWall_Update
|
|
void FUN_80063af8(void)
|
|
|
|
{
|
|
return;
|
|
}
|
|
|
|
// VehPhysProc_SlamWall_PhysLinear
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80063b00(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
// VehPhysProc_Driving_PhysLinear
|
|
FUN_8006181c();
|
|
|
|
// reset two speed variables
|
|
*(undefined2 *)(param_2 + 0x39c) = 0;
|
|
*(undefined2 *)(param_2 + 0x39e) = 0;
|
|
|
|
return;
|
|
}
|
|
|
|
// VehPhysProc_SlamWall_Animate
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80063b2c(int param_1,int param_2)
|
|
|
|
{
|
|
short sVar1;
|
|
undefined2 uVar2;
|
|
int iVar3;
|
|
int iVar4;
|
|
|
|
// get instance from thread
|
|
iVar4 = *(int *)(param_1 + 0x34);
|
|
|
|
// increase animation frame
|
|
*(short *)(iVar4 + 0x54) = *(short *)(iVar4 + 0x54) + 1;
|
|
|
|
*(char *)(param_2 + 0x4d) = *(char *)(param_2 + 0x4d) + '\x01';
|
|
|
|
// get animation frame
|
|
sVar1 = *(short *)(iVar4 + 0x54);
|
|
|
|
// get number of frames in animation
|
|
iVar3 = FUN_8005b0f4(iVar4,(uint)*(byte *)(iVar4 + 0x52));
|
|
|
|
// if animation is finished
|
|
if (iVar3 + -1 <= (int)sVar1)
|
|
{
|
|
// get number of frames in anim #0
|
|
iVar3 = FUN_8005b0f4(iVar4,0);
|
|
|
|
// if it has frames
|
|
if (0 < iVar3)
|
|
{
|
|
// reset animation
|
|
*(undefined *)(iVar4 + 0x52) = 0;
|
|
|
|
// VehFrameInst_GetStartFrame(midpoint, numFrames)
|
|
uVar2 = FUN_8005b0c4(0,iVar3);
|
|
|
|
// set animation
|
|
*(undefined2 *)(iVar4 + 0x54) = uVar2;
|
|
|
|
*(undefined *)(param_2 + 0x4c) = 0;
|
|
*(undefined *)(param_2 + 0x4d) = 0;
|
|
}
|
|
|
|
// VehPhysProc_Driving_Init
|
|
*(undefined4 *)(param_2 + 0x54) = 0x80062b74;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// VehPhysProc_SlamWall_Init
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80063bd4(int param_1,int param_2)
|
|
|
|
{
|
|
int iVar1;
|
|
|
|
// get instance from thread
|
|
iVar1 = *(int *)(param_1 + 0x34);
|
|
|
|
// Set state to crashing
|
|
*(undefined *)(param_2 + 0x376) = 1;
|
|
|
|
*(undefined2 *)(param_2 + 0x3e6) = 10000;
|
|
*(undefined2 *)(param_2 + 0x3dc) = 0;
|
|
*(undefined2 *)(param_2 + 0x3b4) = 0;
|
|
*(undefined2 *)(param_2 + 0x3d2) = 0;
|
|
*(undefined2 *)(param_2 + 0x3d4) = 0;
|
|
*(undefined2 *)(param_2 + 0x3d6) = 0;
|
|
*(undefined2 *)(param_2 + 0x3d8) = 0;
|
|
*(undefined2 *)(param_2 + 0xc0) = 0;
|
|
*(undefined2 *)(param_2 + 0x38c) = 0;
|
|
*(undefined2 *)(param_2 + 0x38e) = 0;
|
|
*(undefined4 *)(param_2 + 0x3a0) = 0;
|
|
*(undefined4 *)(param_2 + 0x3a4) = 0;
|
|
*(undefined4 *)(param_2 + 0x3a8) = 0;
|
|
*(undefined4 *)(param_2 + 0x88) = 0;
|
|
*(undefined4 *)(param_2 + 0x8c) = 0;
|
|
*(undefined4 *)(param_2 + 0x90) = 0;
|
|
*(undefined2 *)(param_2 + 0x36e) = 0;
|
|
*(undefined2 *)(param_2 + 0x3e2) = 0;
|
|
*(undefined2 *)(param_2 + 0x3de) = 0;
|
|
*(undefined2 *)(param_2 + 0x3e0) = 0;
|
|
*(undefined *)(param_2 + 0x377) = 0;
|
|
*(undefined2 *)(param_2 + 0x3ee) = 0;
|
|
*(undefined2 *)(param_2 + 0x40e) = 0;
|
|
*(undefined2 *)(param_2 + 0x410) = 0;
|
|
*(undefined2 *)(param_2 + 0x40c) = 0;
|
|
*(undefined2 *)(param_2 + 0x39c) = 0;
|
|
*(undefined2 *)(param_2 + 0x39e) = 0;
|
|
|
|
// Set driver scale
|
|
*(undefined2 *)(iVar1 + 0x1e) = 0xccc;
|
|
*(undefined2 *)(iVar1 + 0x1c) = 0xccc;
|
|
|
|
// VehPhysProc_SlamWall_Update
|
|
*(undefined4 *)(param_2 + 0x58) = 0x80063af8;
|
|
|
|
// OnInit
|
|
*(undefined4 *)(param_2 + 0x54) = 0;
|
|
|
|
// VehPhysProc_SlamWall_PhysLinear
|
|
*(undefined4 *)(param_2 + 0x5c) = 0x80063b00;
|
|
|
|
*(undefined4 *)(param_2 + 0x60) = 0x80062a2c; // OnAudio
|
|
*(undefined4 *)(param_2 + 100) = 0x80063a44; // OnPhysAngular
|
|
*(undefined4 *)(param_2 + 0x68) = 0x8005ea60; // VehPhysForce_OnApplyForces
|
|
*(undefined4 *)(param_2 + 0x6c) = 0x80020410; // COLL_StartSearch_NearPlayer
|
|
*(undefined4 *)(param_2 + 0x70) = 0x8005ebac; // VehPhysForce_CollideDrivers
|
|
*(undefined4 *)(param_2 + 0x74) = 0x8001d944; // COLL_StartSearch_Player
|
|
*(undefined4 *)(param_2 + 0x78) = 0x80060630; // JumpAndFriction
|
|
*(undefined4 *)(param_2 + 0x7c) = 0x8005ee34; // VehPhysForce_TranslateMatrix -- move position to instance matrix
|
|
|
|
// VehPhysProc_SlamWall_Animate
|
|
*(undefined4 *)(param_2 + 0x80) = 0x80063b2c;
|
|
|
|
|
|
// VehEmitter_DriverMain
|
|
*(undefined4 *)(param_2 + 0x84) = 0x80059a18;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
// VehPhysProc_SpinFirst_Update
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80063cf4(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
int iVar1;
|
|
|
|
// If you are not done spinning out
|
|
if (*(short *)(param_2 + 0x400) != 0)
|
|
{
|
|
// Get approximate speed
|
|
iVar1 = (int)*(short *)(param_2 + 0x38e);
|
|
|
|
// If your speed somehow goes negative
|
|
if (iVar1 < 0)
|
|
{
|
|
// Make it positive
|
|
iVar1 = -iVar1;
|
|
}
|
|
|
|
// If you have not slown down from spinning
|
|
if (0x2ff < iVar1)
|
|
{
|
|
// End the function
|
|
return;
|
|
}
|
|
}
|
|
|
|
// If you have slown down enough
|
|
|
|
// VehPhysProc_SpinLast_Init
|
|
FUN_80064254(param_1, param_2);
|
|
return;
|
|
}
|
|
|
|
// VehPhysProc_SpinFirst_PhysLinear
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80063d44(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
undefined *puVar1;
|
|
int iVar2;
|
|
|
|
// NoInput timer = NoInput timer - elapsed milliseconds per frame, ~32
|
|
iVar2 = (uint)*(ushort *)(param_2 + 0x400) - (uint)*(ushort *)(PTR_DAT_8008d2ac + 0x1d04);
|
|
*(undefined2 *)(param_2 + 0x400) = (short)iVar2;
|
|
|
|
// If timer is less than zero
|
|
if (iVar2 * 0x10000 < 0)
|
|
{
|
|
// Set to zero
|
|
*(undefined2 *)(param_2 + 0x400) = 0;
|
|
}
|
|
|
|
// VehPhysProc_Driving_PhysLinear
|
|
FUN_8006181c(param_1,param_2);
|
|
|
|
puVar1 = PTR_DAT_8008d2ac;
|
|
|
|
// reset two speed variables
|
|
*(undefined2 *)(param_2 + 0x39c) = 0;
|
|
*(undefined2 *)(param_2 + 0x39e) = 0;
|
|
|
|
// Driver flags
|
|
*(uint *)(param_2 + 0x2c8) = *(uint *)(param_2 + 0x2c8) | 0x5808;
|
|
|
|
// Increment amount of time spent spinning out
|
|
*(int *)(param_2 + 0x540) = *(int *)(param_2 + 0x540) + *(int *)(puVar1 + 0x1d04);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
// VehPhysProc_SpinFirst_PhysAngular
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80063dc8(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
undefined *puVar1;
|
|
ushort uVar2;
|
|
undefined2 uVar3;
|
|
|
|
*(undefined2 *)(param_2 + 0x3e6) = 10000;
|
|
|
|
// decrease turn rate by 1/8 of itself
|
|
*(short *)(param_2 + 0x3b4) = *(short *)(param_2 + 0x3b4) - (*(short *)(param_2 + 0x3b4) >> 3);
|
|
|
|
puVar1 = PTR_DAT_8008d2ac;
|
|
|
|
// Drift angle = (Drift angle + spinRate + 180 degrees) & 0xfff - 180 degrees
|
|
*(short *)(param_2 + 0x3c6) =
|
|
(*(short *)(param_2 + 0x3c6) + *(short *)(param_2 + 0x580) + 0x800U & 0xfff) - 0x800;
|
|
|
|
*(short *)(param_2 + 0xc0) = *(short *)(param_2 + 0x3b4);
|
|
*(short *)(param_2 + 0x3d4) = *(short *)(param_2 + 0x3d4) - (*(short *)(param_2 + 0x3d4) >> 3);
|
|
|
|
// kart angle = (kart angle + (rotationSpinRate * time lapsed between frames)) & 0xFFF
|
|
uVar2 = *(short *)(param_2 + 0x39a) +
|
|
(short)((int)*(short *)(param_2 + 0x3b4) * *(int *)(puVar1 + 0x1d04) >> 0xd) & 0xfff;
|
|
*(ushort *)(param_2 + 0x39a) = uVar2;
|
|
|
|
// cameraRotY = ??? + kart angle + drift angle
|
|
*(short *)(param_2 + 0x2ee) = *(short *)(param_2 + 0x3d4) + uVar2 + *(short *)(param_2 + 0x3c6);
|
|
|
|
// Interpolate rotation by speed
|
|
uVar3 = FUN_80058f54((int)*(short *)(param_2 + 0x2f2),(*(int *)(puVar1 + 0x1d04) << 5) >> 5,0);
|
|
|
|
// set new rotation around player
|
|
*(undefined2 *)(param_2 + 0x2f2) = uVar3;
|
|
|
|
// VehPhysForce_RotAxisAngle
|
|
FUN_8005f89c(param_2 + 0x310,param_2 + 0x360,(int)*(short *)(param_2 + 0x39a));
|
|
return;
|
|
}
|
|
|
|
// VehPhysProc_SpinFirst_InitSetUpdate
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80063eac(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
// This delays setting the
|
|
// update function, by one frame
|
|
|
|
// OnInit
|
|
*(undefined4 *)(param_2 + 0x54) = 0;
|
|
|
|
// VehPhysProc_SpinFirst_Update
|
|
*(undefined4 *)(param_2 + 0x58) = 0x80063cf4;
|
|
return;
|
|
}
|
|
|
|
// VehPhysProc_SpinFirst_Init
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80063ec0(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
int iVar1;
|
|
undefined4 uVar2;
|
|
|
|
// Kart is now spinning out
|
|
*(undefined *)(param_2 + 0x376) = 3;
|
|
|
|
*(undefined2 *)(param_2 + 0x3d2) = 0;
|
|
*(undefined2 *)(param_2 + 0x3dc) = 0;
|
|
|
|
// Check if 231 dll is loaded
|
|
iVar1 = FUN_800348e8();
|
|
|
|
if (
|
|
// if it is loaded
|
|
(iVar1 != 0) &&
|
|
|
|
// If you're not in Adventure Arena
|
|
((*(uint *)PTR_DAT_8008d2ac & 0x100000) == 0)
|
|
)
|
|
{
|
|
// RB_Player_ModifyWumpa, -1
|
|
FUN_800abefc(param_2,0xffffffff);
|
|
}
|
|
|
|
// Make driver talk
|
|
FUN_8002cbe8(3,(int)(short)(&DAT_80086e84)[*(byte *)(param_2 + 0x4a)],0x10);
|
|
|
|
// spin left
|
|
*(undefined2 *)(param_2 + 0x582) = 1;
|
|
|
|
// spin rate = 300
|
|
*(undefined2 *)(param_2 + 0x580) = 300;
|
|
|
|
// if you're spinning to the right
|
|
if (*(short *)(param_2 + 0xc0) < 0)
|
|
{
|
|
// spin rate = -300
|
|
*(undefined2 *)(param_2 + 0x580) = 0xfed4;
|
|
|
|
// spin right (-1)
|
|
*(undefined2 *)(param_2 + 0x582) = 0xffff;
|
|
}
|
|
|
|
// Set function pointers for spinning out
|
|
*(undefined4 *)(param_2 + 0x54) = 0x80063eac // VehPhysProc_SpinFirst_InitSetUpdate
|
|
*(undefined4 *)(param_2 + 0x5c) = 0x80063d44; // VehPhysProc_SpinFirst_PhysLinear
|
|
*(undefined4 *)(param_2 + 0x60) = 0x80062a2c; // OnAudio
|
|
*(undefined4 *)(param_2 + 100) = 0x80063dc8;
|
|
*(undefined4 *)(param_2 + 0x68) = 0x8005ea60; // VehPhysForce_OnApplyForces
|
|
*(undefined4 *)(param_2 + 0x6c) = 0x80020410; // COLL_StartSearch_NearPlayer
|
|
*(undefined4 *)(param_2 + 0x70) = 0x8005ebac; // VehPhysForce_CollideDrivers
|
|
*(undefined4 *)(param_2 + 0x74) = 0x8001d944; // COLL_StartSearch_Player
|
|
*(undefined4 *)(param_2 + 0x78) = 0x80060630; // JumpAndFriction
|
|
*(undefined4 *)(param_2 + 0x7c) = 0x8005ee34; // VehPhysForce_TranslateMatrix -- move position to instance matrix
|
|
|
|
// VehFrameProc_Spinning
|
|
*(undefined4 *)(param_2 + 0x80) = 0x8005b510;
|
|
|
|
*(undefined4 *)(param_2 + 0x58) = 0;
|
|
|
|
// VehEmitter_DriverMain
|
|
*(undefined4 *)(param_2 + 0x84) = 0x80059a18;
|
|
|
|
if (*(char *)(param_2 + 0x4b) < '\x01') {
|
|
uVar2 = 0x19;
|
|
}
|
|
else {
|
|
uVar2 = 0x29;
|
|
}
|
|
|
|
// GAMEPAD_JogCon1
|
|
FUN_800263a0(param_2,uVar2,0x60);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
// VehPhysProc_SpinLast_Update
|
|
// param1 = thread, param2 = driver
|
|
void FUN_8006402c(undefined4 param_1,int param_2)
|
|
{
|
|
// Transition from spinning to driving
|
|
|
|
int iVar1;
|
|
|
|
// Get Drift Angle
|
|
iVar1 = (int)*(short *)(param_2 + 0x3c6);
|
|
|
|
// Get absolute value
|
|
if (iVar1 < 0) {
|
|
iVar1 = -iVar1;
|
|
}
|
|
|
|
// If you're almost fully facing forward
|
|
if (iVar1 < 0x10)
|
|
{
|
|
// Change all funcPtrs to transition
|
|
// from LastSpin to Driving
|
|
// VehPhysProc_SpinStop_Init
|
|
FUN_800644d0(param_1, param_2);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// VehPhysProc_SpinLast_PhysLinear
|
|
// param1 = thread, param2 = driver
|
|
void FUN_8006406c(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
// VehPhysProc_Driving_PhysLinear
|
|
FUN_8006181c();
|
|
|
|
// reset two speed variables
|
|
*(undefined2 *)(param_2 + 0x39c) = 0;
|
|
*(undefined2 *)(param_2 + 0x39e) = 0;
|
|
|
|
*(uint *)(param_2 + 0x2c8) = *(uint *)(param_2 + 0x2c8) | 0x4008;
|
|
return;
|
|
}
|
|
|
|
// VehPhysProc_SpinLast_PhysAngular
|
|
// param1 = thread, param2 = driver
|
|
void FUN_800640a4(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
undefined *puVar1;
|
|
ushort uVar2;
|
|
undefined2 uVar3;
|
|
short sVar4;
|
|
int iVar5;
|
|
|
|
// Get drifting angle
|
|
iVar5 = (int)*(short *)(param_2 + 0x3c6);
|
|
|
|
// Set drift angle (temporarily)
|
|
*(undefined2 *)(param_2 + 0x3e6) = 10000;
|
|
|
|
// decrease rotationSpinRate by 1/8 of itself
|
|
sVar4 = *(short *)(param_2 + 0x3b4) - (*(short *)(param_2 + 0x3b4) >> 3);
|
|
*(short *)(param_2 + 0x3b4) = sVar4;
|
|
|
|
// decrease [what]?
|
|
*(short *)(param_2 + 0x3d4) = *(short *)(param_2 + 0x3d4) - (*(short *)(param_2 + 0x3d4) >> 3);
|
|
|
|
*(short *)(param_2 + 0xc0) = sVar4;
|
|
|
|
if (iVar5 < 1)
|
|
{
|
|
// drifting right,
|
|
// spinning out clockwise
|
|
if (iVar5 < 0)
|
|
{
|
|
if (
|
|
(
|
|
// if spinning hasn't stopped
|
|
(0 < *(short *)(param_2 + 0x580)) &&
|
|
(-400 < iVar5)
|
|
) &&
|
|
(
|
|
// decrease spin rate
|
|
iVar5 = iVar5 * -4 >> 3,
|
|
*(undefined2 *)(param_2 + 0x580) = (short)iVar5,
|
|
|
|
// if spin rate is too low
|
|
iVar5 < 0x20
|
|
)
|
|
)
|
|
{
|
|
// set minimum spin rate if drops below minimum
|
|
*(undefined2 *)(param_2 + 0x580) = 0x20;
|
|
}
|
|
|
|
// Drift angle = (drift angle + spin rate + 180 degrees) & 0xfff - 180 degrees
|
|
uVar2 = (*(short *)(param_2 + 0x3c6) + *(short *)(param_2 + 0x580) + 0x800U & 0xfff) - 0x800;
|
|
*(ushort *)(param_2 + 0x3c6) = uVar2;
|
|
|
|
// if you're almost facing forward while spinning at a slow rate
|
|
if ((0 < *(short *)(param_2 + 0x580)) && (0 < (int)((uint)uVar2 << 0x10)))
|
|
{
|
|
// reset drift angle (but still spin until StopSpin)
|
|
*(undefined2 *)(param_2 + 0x3c6) = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// spinning the other way
|
|
else
|
|
{
|
|
if (
|
|
(
|
|
// if spinning hasn't stopped
|
|
(*(short *)(param_2 + 0x580) < 0) &&
|
|
(iVar5 < 400)
|
|
) &&
|
|
|
|
(
|
|
// decrease spin rate
|
|
iVar5 = iVar5 * -4 >> 3,
|
|
*(undefined2 *)(param_2 + 0x580) = (short)iVar5,
|
|
|
|
// if spin rate is too low
|
|
-0x20 < iVar5
|
|
)
|
|
)
|
|
{
|
|
// set minimum spin rate if drops below minimum (-0x20)
|
|
*(undefined2 *)(param_2 + 0x580) = 0xffe0;
|
|
}
|
|
|
|
// Drift angle = (drift angle + spin rate + 180 degrees) & 0xfff - 180 degrees
|
|
uVar2 = (*(short *)(param_2 + 0x3c6) + *(short *)(param_2 + 0x580) + 0x800U & 0xfff) - 0x800;
|
|
*(ushort *)(param_2 + 0x3c6) = uVar2;
|
|
|
|
// if you're almost facing forward while spinning at a slow rate
|
|
if ((*(short *)(param_2 + 0x580) < 0) && ((int)((uint)uVar2 << 0x10) < 0))
|
|
{
|
|
// reset drift angle (but still spin until StopSpin)
|
|
*(undefined2 *)(param_2 + 0x3c6) = 0;
|
|
}
|
|
}
|
|
|
|
puVar1 = PTR_DAT_8008d2ac;
|
|
|
|
// kart angle = (kart angle +
|
|
uVar2 = *(short *)(param_2 + 0x39a) +
|
|
(short)
|
|
(
|
|
// ampTurnState
|
|
(int)*(short *)(param_2 + 0xc0) *
|
|
|
|
// elapsed milliseconds per frame, ~32
|
|
*(int *)(PTR_DAT_8008d2ac + 0x1d04) >> 0xd
|
|
|
|
// clamp to [0x000-0xfff]
|
|
) & 0xfff;
|
|
|
|
// save
|
|
*(ushort *)(param_2 + 0x39a) = uVar2;
|
|
|
|
// cameraRotY = ??? + kart angle + drift angle
|
|
*(short *)(param_2 + 0x2ee) = *(short *)(param_2 + 0x3d4) + uVar2 + *(short *)(param_2 + 0x3c6);
|
|
|
|
// Interpolate rotation by speed
|
|
uVar3 = FUN_80058f54((int)*(short *)(param_2 + 0x2f2),(*(int *)(puVar1 + 0x1d04) << 5) >> 5,0);
|
|
|
|
// set new camera rotation around player
|
|
*(undefined2 *)(param_2 + 0x2f2) = uVar3;
|
|
|
|
// VehPhysForce_RotAxisAngle
|
|
FUN_8005f89c(param_2 + 0x310,param_2 + 0x360,(int)*(short *)(param_2 + 0x39a));
|
|
return;
|
|
}
|
|
|
|
|
|
// param1 = thread, param2 = driver
|
|
// VehPhysProc_SpinLast_Init
|
|
void FUN_80064254(undefined4 param_1,int param_2)
|
|
{
|
|
// Transition out of spinning
|
|
|
|
// VehPhysProc_SpinLast_Update
|
|
*(undefined4 *)(param_2 + 0x58) = 0x8006402c;
|
|
|
|
// VehPhysProc_SpinLast_PhysLinear
|
|
*(undefined4 *)(param_2 + 0x5c) = 0x8006406c;
|
|
|
|
*(undefined4 *)(param_2 + 0x60) = 0x80062a2c; // OnAudio
|
|
*(undefined4 *)(param_2 + 100) = 0x800640a4; // OnPhysAngular
|
|
*(undefined4 *)(param_2 + 0x68) = 0x8005ea60; // VehPhysForce_OnApplyForces
|
|
*(undefined4 *)(param_2 + 0x6c) = 0x80020410; // COLL_StartSearch_NearPlayer
|
|
*(undefined4 *)(param_2 + 0x70) = 0x8005ebac; // VehPhysForce_CollideDrivers
|
|
*(undefined4 *)(param_2 + 0x74) = 0x8001d944; // COLL_StartSearch_Player
|
|
*(undefined4 *)(param_2 + 0x78) = 0x80060630; // JumpAndFriction
|
|
*(undefined4 *)(param_2 + 0x7c) = 0x8005ee34; // VehPhysForce_TranslateMatrix -- move position to instance matrix
|
|
|
|
// VehFrameProc_LastSpin
|
|
*(undefined4 *)(param_2 + 0x80) = 0x8005b5fc;
|
|
|
|
*(undefined4 *)(param_2 + 0x54) = 0;
|
|
|
|
// VehEmitter_DriverMain
|
|
*(undefined4 *)(param_2 + 0x84) = 0x80059a18;
|
|
|
|
return;
|
|
}
|
|
|
|
// VehPhysProc_SpinStop_Update
|
|
void FUN_800642ec(void)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// VehPhysProc_SpinStop_PhysLinear
|
|
// param1 = thread, param2 = driver
|
|
void FUN_800642f4(undefined4 param_1,int param_2)
|
|
{
|
|
// VehPhysProc_Driving_PhysLinear
|
|
FUN_8006181c();
|
|
|
|
// reset two speed variables
|
|
*(undefined2 *)(param_2 + 0x39c) = 0;
|
|
*(undefined2 *)(param_2 + 0x39e) = 0;
|
|
|
|
return;
|
|
}
|
|
|
|
// VehPhysProc_SpinStop_PhysAngular
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80064320(undefined4 param_1,int param_2)
|
|
{
|
|
undefined *puVar1;
|
|
ushort uVar2;
|
|
undefined2 uVar3;
|
|
|
|
puVar1 = PTR_DAT_8008d2ac;
|
|
|
|
// increase spin by (lastFrameSpinRate * elapsedTime)
|
|
uVar2 = *(short *)(param_2 + 0x39a) +
|
|
(short)((int)*(short *)(param_2 + 0xc0) * *(int *)(PTR_DAT_8008d2ac + 0x1d04) >> 0xd) &
|
|
0xfff;
|
|
|
|
*(ushort *)(param_2 + 0x39a) = uVar2;
|
|
|
|
// cameraRotY = spinRate + kart angle + drift angle,
|
|
// spin rate is added so you're one frame ahead
|
|
*(short *)(param_2 + 0x2ee) = *(short *)(param_2 + 0x3d4) + uVar2 + *(short *)(param_2 + 0x3c6);
|
|
|
|
// Interpolate rotation by speed
|
|
uVar3 = FUN_80058f54((int)*(short *)(param_2 + 0x2f2),(*(int *)(puVar1 + 0x1d04) << 5) >> 5,0);
|
|
|
|
puVar1 = PTR_DAT_8008d2ac;
|
|
|
|
// set new camera rotation around player
|
|
*(undefined2 *)(param_2 + 0x2f2) = uVar3;
|
|
|
|
// Interpolate rotation by speed
|
|
uVar3 = FUN_80058f54((int)*(short *)(param_2 + 0x3c6),(*(int *)(puVar1 + 0x1d04) << 7) >> 5,0);
|
|
*(undefined2 *)(param_2 + 0x3c6) = uVar3;
|
|
|
|
// VehPhysForce_RotAxisAngle
|
|
FUN_8005f89c(param_2 + 0x310,param_2 + 0x360,(int)*(short *)(param_2 + 0x39a));
|
|
return;
|
|
}
|
|
|
|
|
|
// param1 = thread, param2 = driver
|
|
// VehPhysProc_SpinStop_Animate
|
|
void FUN_800643d4(int param_1,int param_2)
|
|
|
|
{
|
|
ushort uVar1;
|
|
short sVar2;
|
|
int iVar3;
|
|
int iVar4;
|
|
|
|
// get instance from thread
|
|
iVar4 = *(int *)(param_1 + 0x34);
|
|
|
|
// get number of frames in animation
|
|
iVar3 = FUN_8005b0f4(iVar4,(uint)*(byte *)(iVar4 + 0x52));
|
|
|
|
// if there are frames
|
|
if (0 < iVar3)
|
|
{
|
|
// if you are spinning right
|
|
if (*(short *)(param_2 + 0x582) == -1)
|
|
{
|
|
// steer from left to right, to exaggerate
|
|
// the force when steering stops abruptly
|
|
sVar2 = *(short *)(iVar4 + 0x54) + 5;
|
|
*(short *)(iVar4 + 0x54) = sVar2;
|
|
|
|
// if not finished, quit function
|
|
if (sVar2 < iVar3) {
|
|
return;
|
|
}
|
|
|
|
// last frame
|
|
*(short *)(iVar4 + 0x54) = (short)iVar3 + -1;
|
|
|
|
// no spinDir anymore
|
|
*(undefined2 *)(param_2 + 0x582) = 0;
|
|
|
|
return;
|
|
}
|
|
|
|
// if you are spinning left
|
|
if (*(short *)(param_2 + 0x582) == 1)
|
|
{
|
|
// steer from right to left, to exaggerate
|
|
// the force when steering stops abruptly
|
|
uVar1 = *(short *)(iVar4 + 0x54) - 5;
|
|
*(ushort *)(iVar4 + 0x54) = uVar1;
|
|
|
|
// if not finished, quit function
|
|
if (-1 < (int)((uint)uVar1 << 0x10)) {
|
|
return;
|
|
}
|
|
|
|
// first frame
|
|
*(undefined2 *)(iVar4 + 0x54) = 0;
|
|
|
|
// no spinDir anymore
|
|
*(undefined2 *)(param_2 + 0x582) = 0;
|
|
|
|
return;
|
|
}
|
|
|
|
// === spinning has stopped ===
|
|
|
|
// return driver to center steering
|
|
// animation frame
|
|
|
|
// VehFrameInst_GetStartFrame(midpoint, numFrames)
|
|
iVar3 = FUN_8005b0c4(0,iVar3);
|
|
|
|
// Interpolate rotation by speed
|
|
sVar2 = FUN_80058f54((int)*(short *)(iVar4 + 0x54),2,iVar3);
|
|
|
|
// set animation frame
|
|
*(short *)(iVar4 + 0x54) = sVar2;
|
|
|
|
// if you are not facing forward
|
|
if ((int)sVar2 != iVar3)
|
|
{
|
|
// keep spinning till you face forward
|
|
return;
|
|
}
|
|
}
|
|
|
|
// if you are facing forward
|
|
|
|
// VehPhysProc_Driving_Init
|
|
*(undefined4 *)(param_2 + 0x54) = 0x80062b74;
|
|
return;
|
|
}
|
|
|
|
// param1 = thread, param2 = driver
|
|
// VehPhysProc_SpinStop_Init
|
|
void FUN_800644d0(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
// Transition from
|
|
// LastSpin to Driving
|
|
|
|
// VehPhysProc_SpinStop_Update,
|
|
// "updating" happens in OnAnimate
|
|
*(undefined4 *)(param_2 + 0x58) = 0x800642ec;
|
|
|
|
// VehPhysProc_SpinStop_PhysLinear
|
|
*(undefined4 *)(param_2 + 0x5c) = 0x800642f4;
|
|
|
|
*(undefined4 *)(param_2 + 0x60) = 0x80062a2c; // OnAudio
|
|
*(undefined4 *)(param_2 + 100) = 0x80064320; // OnPhysAngular
|
|
*(undefined4 *)(param_2 + 0x68) = 0x8005ea60; // VehPhysForce_OnApplyForces
|
|
*(undefined4 *)(param_2 + 0x6c) = 0x80020410; // COLL_StartSearch_NearPlayer
|
|
*(undefined4 *)(param_2 + 0x70) = 0x8005ebac; // VehPhysForce_CollideDrivers
|
|
*(undefined4 *)(param_2 + 0x74) = 0x8001d944; // COLL_StartSearch_Player
|
|
*(undefined4 *)(param_2 + 0x78) = 0x80060630; // JumpAndFriction
|
|
*(undefined4 *)(param_2 + 0x7c) = 0x8005ee34; // VehPhysForce_TranslateMatrix -- move position to instance matrix
|
|
|
|
// VehPhysProc_SpinStop_Animate, calls VehPhysProc_Driving_Init
|
|
*(undefined4 *)(param_2 + 0x80) = 0x800643d4;
|
|
|
|
*(undefined4 *)(param_2 + 0x54) = 0;
|
|
|
|
// VehEmitter_DriverMain
|
|
*(undefined4 *)(param_2 + 0x84) = 0x80059a18;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
// VehPickState_NewState
|
|
// param1 - driverVictim
|
|
// param2 - damageType
|
|
// param3 - driverAttacker
|
|
// param4 - reason
|
|
undefined4 FUN_80064568(int param_1,int param_2,int param_3,undefined4 param_4)
|
|
|
|
{
|
|
char cVar1;
|
|
byte bVar2;
|
|
undefined4 uVar3;
|
|
undefined *puVar4;
|
|
undefined4 in_zero;
|
|
undefined4 in_at;
|
|
undefined *puVar5;
|
|
int iVar6;
|
|
int iVar7;
|
|
undefined4 local_30;
|
|
uint local_2c;
|
|
short local_28;
|
|
short sStack38;
|
|
|
|
// get kart state
|
|
cVar1 = *(char *)(param_1 + 0x376);
|
|
*(undefined *)(param_1 + 0x4ff) = 0;
|
|
|
|
// if kart is being mask-grabbed
|
|
if (cVar1 == '\x05') {
|
|
return 0;
|
|
}
|
|
|
|
if (
|
|
// If player is using mask weapon
|
|
((*(uint *)(param_1 + 0x2c8) & 0x800000) != 0) ||
|
|
|
|
// If player invincibility timer is active
|
|
(*(int *)(param_1 + 0x24) != 0)
|
|
)
|
|
{
|
|
// Player / AI structure + 0x4a shows driver index (0-7)
|
|
|
|
// which driver this is (0-7)
|
|
bVar2 = *(byte *)(param_1 + 0x4a);
|
|
|
|
LAB_8006462c:
|
|
|
|
// Theory
|
|
// Play sound of character laughing because they
|
|
// were hit by weapon while invincible, and therefore
|
|
// they take no damage
|
|
|
|
// Voiceline_RequestPlay
|
|
FUN_8002cbe8(2,(int)(short)(&DAT_80086e84)[bVar2],0x10);
|
|
return 0;
|
|
}
|
|
|
|
// if you have a shield weapon
|
|
if (*(int *)(param_1 + 0x14) != 0)
|
|
{
|
|
// driver -> shield -> thread -> object
|
|
iVar6 = *(int *)(*(int *)(*(int *)(param_1 + 0x14) + 0x6c) + 0x30);
|
|
|
|
*(ushort *)(iVar6 + 6) = *(ushort *)(iVar6 + 6) | 1;
|
|
|
|
// give invincibility
|
|
*(undefined4 *)(param_1 + 0x24) = 0x2a0;
|
|
|
|
bVar2 = *(byte *)(param_1 + 0x4a);
|
|
|
|
// you no-longer have a shield
|
|
*(undefined4 *)(param_1 + 0x14) = 0;
|
|
|
|
goto LAB_8006462c;
|
|
}
|
|
|
|
// driving
|
|
if (param_2 == 0) {
|
|
return 1;
|
|
}
|
|
|
|
// driver -> instance -> thread
|
|
iVar6 = *(int *)(*(int *)(param_1 + 0x1c) + 0x6c);
|
|
|
|
// Squish
|
|
if (param_2 == 3) {
|
|
if (cVar1 != '\x03')
|
|
{
|
|
// OtherFX_Play_Echo
|
|
// squish sound
|
|
FUN_80028494(0x5a,1,*(uint *)(param_1 + 0x2c8) >> 0x10 & 1);
|
|
|
|
// Voiceline_RequestPlay
|
|
FUN_8002cbe8(4,(int)(short)(&DAT_80086e84)[*(byte *)(param_1 + 0x4a)],0x10);
|
|
}
|
|
|
|
// squish the character, put them into squished
|
|
// animation for 0xF00 amount of time (frames?)
|
|
*(undefined2 *)(param_1 + 0x404) = 0xf00;
|
|
|
|
// NoInput = 0.25s
|
|
*(undefined2 *)(param_1 + 0x400) = 0xf0;
|
|
}
|
|
else {
|
|
if (param_2 < 4) {
|
|
|
|
// Blast
|
|
if (param_2 == 2) {
|
|
|
|
// if kart is already being "blasted"
|
|
if (cVar1 == '\x06') {
|
|
return 0;
|
|
}
|
|
|
|
// if function pointer is already set to make the kart "blasted"
|
|
if (*(code **)(param_1 + 0x54) == FUN_800682a4) {
|
|
return 0;
|
|
}
|
|
|
|
// You are only here if the player is not being
|
|
// blasted, but needs to be blasted after being hit
|
|
|
|
// NoInput = 2.4 seconds
|
|
*(undefined2 *)(param_1 + 0x400) = 0x960;
|
|
|
|
// Player / AI structure + 0x4a shows driver index (0-7)
|
|
|
|
|
|
// which driver this is (0-7)
|
|
bVar2 = *(byte *)(param_1 + 0x4a);
|
|
|
|
// Undo the "Squish" effect
|
|
*(undefined2 *)(param_1 + 0x404) = 0;
|
|
|
|
// VehStuckProc_Tumble_Init
|
|
*(undefined4 *)(param_1 + 0x54) = 0x800682a4;
|
|
|
|
LAB_800646f0:
|
|
|
|
// Voiceline_RequestPlay
|
|
FUN_8002cbe8(1,(int)(short)(&DAT_80086e84)[bVar2],0x10);
|
|
goto LAB_800647d8;
|
|
}
|
|
}
|
|
else {
|
|
|
|
// Burn
|
|
if (param_2 == 4) {
|
|
|
|
// If player is not currently burned
|
|
if (*(short *)(param_1 + 0x402) == 0)
|
|
{
|
|
// OtherFX_Play "Just got Burned" sound
|
|
FUN_80028468(0x69,1);
|
|
|
|
// Make driver talk
|
|
FUN_8002cbe8(1,(int)(short)(&DAT_80086e84)[*(byte *)(param_1 + 0x4a)],0x10);
|
|
}
|
|
|
|
// Add to player's Burned timer
|
|
*(undefined2 *)(param_1 + 0x402) = 0xf00;
|
|
|
|
// NoInput set to 2.0 seconds
|
|
*(undefined2 *)(param_1 + 0x400) = 0x780;
|
|
|
|
goto LAB_800647c8;
|
|
}
|
|
|
|
// mask grab
|
|
if (param_2 == 5)
|
|
{
|
|
// NoInput set to 3.36 seconds
|
|
*(undefined2 *)(param_1 + 0x400) = 0xd20;
|
|
|
|
// VehStuckProc_PlantEaten_Init
|
|
*(undefined4 *)(param_1 + 0x54) = 0x800677d0;
|
|
|
|
bVar2 = *(byte *)(param_1 + 0x4a);
|
|
goto LAB_800646f0;
|
|
}
|
|
}
|
|
|
|
// NoInput set to 1.0 seconds
|
|
*(undefined2 *)(param_1 + 0x400) = 0x3c0;
|
|
|
|
// If you're spinning: if you hit a glass or spun out from drifting
|
|
if (*(char *)(param_1 + 0x376) == '\x03') goto LAB_800647d8;
|
|
}
|
|
LAB_800647c8:
|
|
|
|
// VehPhysProc_SpinFirst_Init
|
|
*(undefined4 *)(param_1 + 0x54) = 0x80063ec0;
|
|
|
|
LAB_800647d8:
|
|
switch(param_4) {
|
|
case 1:
|
|
|
|
// number of times bomb hit you
|
|
*(char *)(param_1 + 0x55e) = *(char *)(param_1 + 0x55e) + '\x01';
|
|
|
|
if ((param_3 != 0) && (param_3 != param_1))
|
|
{
|
|
// number of times your bomb hit someone
|
|
*(char *)(param_3 + 0x55a) = *(char *)(param_3 + 0x55a) + '\x01';
|
|
*(ushort *)(param_3 + 0x4f6) = *(ushort *)(param_3 + 0x4f6) | 1;
|
|
}
|
|
break;
|
|
|
|
// hit by motionless potion
|
|
case 2:
|
|
// number of times motionless potion hit you
|
|
*(char *)(param_1 + 0x55f) = *(char *)(param_1 + 0x55f) + '\x01';
|
|
break;
|
|
|
|
case 3:
|
|
|
|
// number of times missile hit you
|
|
*(char *)(param_1 + 0x55d) = *(char *)(param_1 + 0x55d) + '\x01';
|
|
|
|
if ((param_3 != 0) && (param_3 != param_1)) {
|
|
|
|
// number of times you hit someone with missile
|
|
*(char *)(param_3 + 0x557) = *(char *)(param_3 + 0x557) + '\x01';
|
|
*(ushort *)(param_3 + 0x4f6) = *(ushort *)(param_3 + 0x4f6) | 2;
|
|
}
|
|
break;
|
|
|
|
// hit by moving potion
|
|
case 4:
|
|
if ((param_3 != 0) && (param_3 != param_1))
|
|
{
|
|
// number of times you hit someone with potion moving potion
|
|
*(char *)(param_3 + 0x556) = *(char *)(param_3 + 0x556) + '\x01';
|
|
*(ushort *)(param_3 + 0x4f6) = *(ushort *)(param_3 + 0x4f6) | 4;
|
|
}
|
|
break;
|
|
|
|
// squished by other driver's turbo
|
|
case 5:
|
|
if ((param_3 != 0) && (param_3 != param_1))
|
|
{
|
|
// number of times you squished someone
|
|
*(char *)(param_3 + 0x55b) = *(char *)(param_3 + 0x55b) + '\x01';
|
|
}
|
|
break;
|
|
|
|
// hit by a mask weapon
|
|
case 6:
|
|
if ((param_3 != 0) && (param_3 != param_1))
|
|
{
|
|
// set flag to the driver that did the attacking with mask weapon
|
|
*(ushort *)(param_3 + 0x4f6) = *(ushort *)(param_3 + 0x4f6) | 8;
|
|
}
|
|
}
|
|
*(undefined *)(param_1 + 0x376) = 0;
|
|
*(undefined2 *)(param_1 + 0x3e2) = 0;
|
|
*(undefined2 *)(param_1 + 0x3de) = 0;
|
|
*(undefined *)(param_1 + 0x4c) = 0;
|
|
*(undefined *)(param_1 + 0x4d) = 0;
|
|
|
|
// GAMEPAD_ShockFreq and GAMEPAD_ShockForce1
|
|
FUN_80026440(param_1,8,0);
|
|
FUN_800264c0(param_1,8,0x7f);
|
|
|
|
puVar4 = PTR_DAT_8008d2ac;
|
|
|
|
// If you're not in End-Of-Race menu
|
|
if ((param_3 != 0) && ((*(uint *)PTR_DAT_8008d2ac & 0x200000) == 0))
|
|
{
|
|
local_30 = CONCAT22(*(undefined2 *)(*(int *)(param_3 + 0x1c) + 0x48),
|
|
*(undefined2 *)(*(int *)(param_3 + 0x1c) + 0x44));
|
|
|
|
local_2c = local_2c & 0xffff0000 | (uint)*(ushort *)(*(int *)(param_3 + 0x1c) + 0x4c);
|
|
|
|
// camera index depending on player
|
|
puVar5 = PTR_DAT_8008d2ac + (uint)*(byte *)(param_3 + 0x4a) * 0x110;
|
|
|
|
// pushBuffer ViewProj
|
|
gte_SetRotMatrix(puVar5 + 0x168 + 0x28);
|
|
gte_SetTransMatrix(puVar5 + 0x168 + 0x28);
|
|
|
|
// instance position on GTE
|
|
gte_ldv0(&local_30);
|
|
|
|
// RTPS - Perspective Transformation (single)
|
|
gte_rtps();
|
|
|
|
// get screenspace pos of driver
|
|
gte_stsxy(&uVar3);
|
|
|
|
// X
|
|
local_28 = (short)uVar3;
|
|
|
|
// set position of HUD element to position of driver (on screen)
|
|
*(short *)(param_3 + 0x4d4) =
|
|
local_28 + *(short *)(PTR_DAT_8008d2ac + (uint)*(byte *)(param_3 + 0x4a) * 0x110 + 0x184);
|
|
|
|
// Y
|
|
sStack38 = (short)((uint)uVar3 >> 0x10);
|
|
*(short *)(param_3 + 0x4d6) =
|
|
sStack38 + *(short *)(puVar4 + (uint)*(byte *)(param_3 + 0x4a) * 0x110 + 0x186) + -0x14;
|
|
|
|
// loop counter
|
|
iVar7 = 0;
|
|
|
|
// for iVar7 = 0; iVar7 < 1; iVar7++
|
|
do
|
|
{
|
|
// this only happens once
|
|
|
|
// RB_Player_KillPlayer
|
|
FUN_800abbb4(param_3,param_1);
|
|
|
|
// === Naughty Dog Bug ===
|
|
// If you're in End-Of-Race menu (impossible)
|
|
if ((*(uint *)PTR_DAT_8008d2ac & 0x200000) != 0)
|
|
{
|
|
// save something in the player that got the kill,
|
|
// and the player that got killed
|
|
*(undefined2 *)(param_3 + 0x4f0) = (short)param_4;
|
|
*(undefined2 *)(param_1 + 0x4f4) = (short)param_4;
|
|
}
|
|
|
|
// increment loop counter
|
|
iVar7 = iVar7 + 1;
|
|
} while (iVar7 < 1);
|
|
|
|
if (
|
|
// if attacked yourself
|
|
(param_3 == param_1) &&
|
|
|
|
// If you have a point limit (battle)
|
|
((*(uint *)PTR_DAT_8008d2ac & 0x4000) != 0)
|
|
)
|
|
{
|
|
if (*(int *)(param_1 + 0x4d0) == 5)
|
|
{
|
|
// scoreDelta
|
|
*(int *)(param_1 + 0x4dc) = *(int *)(param_1 + 0x4dc) + -1;
|
|
}
|
|
else
|
|
{
|
|
// scoreDelta
|
|
*(undefined4 *)(param_1 + 0x4dc) = 0xffffffff;
|
|
}
|
|
}
|
|
|
|
// did not attack self
|
|
else
|
|
{
|
|
if (*(int *)(param_3 + 0x4d0) == 5)
|
|
{
|
|
// scoreDelta
|
|
*(int *)(param_3 + 0x4dc) = *(int *)(param_3 + 0x4dc) + 1;
|
|
}
|
|
|
|
else
|
|
{
|
|
// scoreDelta
|
|
*(undefined4 *)(param_3 + 0x4dc) = 1;
|
|
}
|
|
}
|
|
|
|
// cooldown
|
|
*(undefined4 *)(param_3 + 0x4d0) = 5;
|
|
|
|
// param_3 is attacker,
|
|
// param_1 is attacked
|
|
|
|
// count number of times attacked by this player
|
|
// param_1->0x560[param_3->driverID]++
|
|
iVar7 = param_1 + (uint)*(byte *)(param_3 + 0x4a);
|
|
*(char *)(iVar7 + 0x560) = *(char *)(iVar7 + 0x560) + '\x01';
|
|
|
|
// count number of times attacking this player
|
|
// param_1->0x50c[param_3->driverID]++
|
|
iVar7 = param_3 + (uint)*(byte *)(param_1 + 0x4a);
|
|
*(char *)(iVar7 + 0x50c) = *(char *)(iVar7 + 0x50c) + '\x01';
|
|
|
|
// if did not attack yourself
|
|
if (param_3 != param_1)
|
|
{
|
|
// count number of times attacking
|
|
*(char *)(param_3 + 0x559) = *(char *)(param_3 + 0x559) + '\x01';
|
|
}
|
|
}
|
|
|
|
// enable collision for this thread
|
|
*(uint *)(iVar6 + 0x1c) = *(uint *)(iVar6 + 0x1c) & 0xffffefff;
|
|
|
|
// make visible
|
|
*(uint *)(*(int *)(param_1 + 0x1c) + 0x28) =
|
|
*(uint *)(*(int *)(param_1 + 0x1c) + 0x28) & 0xffffff7f;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
// VehPickupItem_MaskBoolGoodGuy
|
|
undefined4 FUN_80064be4(int param_1)
|
|
|
|
{
|
|
// character ID (0 for crash, 1 for cortex, 2 for tiny, etc)
|
|
short sVar1;
|
|
|
|
// return (0 for uka, 1 for aku)
|
|
undefined4 uVar2;
|
|
|
|
// Player / AI structure + 0x4a shows driver index (0-7)
|
|
|
|
|
|
// get character ID of current player (p1, p2, p3, etc)
|
|
sVar1 = (&DAT_80086e84)[*(byte *)(param_1 + 0x4a)];
|
|
|
|
// by default, player is bad guy and uses uka uka
|
|
uVar2 = 0;
|
|
|
|
// if you are crash, coco polar pura or penta
|
|
if ((((sVar1 == 0) || (sVar1 == 3)) || (sVar1 == 6)) || ((sVar1 == 7 || (sVar1 == 0xd))))
|
|
{
|
|
// you are a good guy, use aku aku
|
|
uVar2 = 1;
|
|
}
|
|
|
|
// return whether you use aku or uka
|
|
return uVar2;
|
|
}
|
|
|
|
|
|
// VehPickupItem_MaskUseWeapon
|
|
// param1 is driver
|
|
// param2 (0 for mask grab, 1 for weapon)
|
|
undefined2 * FUN_80064c38(int param_1,int param_2)
|
|
|
|
{
|
|
undefined2 uVar1;
|
|
int iVar2;
|
|
undefined2 *puVar3;
|
|
uint uVar4;
|
|
undefined4 uVar5;
|
|
int iVar6;
|
|
|
|
// Check if 231 dll is loaded
|
|
iVar2 = FUN_800348e8();
|
|
|
|
if (
|
|
// if it is not loaded
|
|
(iVar2 == 0) ||
|
|
|
|
// If you're in Adventure Arena
|
|
((*(uint *)PTR_DAT_8008d2ac & 0x100000) != 0)
|
|
)
|
|
{
|
|
// return nullptr
|
|
// no mask object in adv arena
|
|
puVar3 = (undefined2 *)0x0;
|
|
}
|
|
else
|
|
{
|
|
// driver -> instance -> thread
|
|
iVar6 = *(int *)(*(int *)(param_1 + 0x1c) + 0x6c);
|
|
|
|
// thread -> childThread,
|
|
// which gets mask thread from driver
|
|
iVar2 = *(int *)(iVar6 + 0x14);
|
|
|
|
// while pointer is not nullptr
|
|
while (iVar2 != 0)
|
|
{
|
|
// if thread->modelIndex is Aku or Uka
|
|
if ((uint)*(ushort *)(iVar2 + 0x44) - 0x39 < 2)
|
|
{
|
|
// RB_MaskWeapon_ThTick
|
|
*(undefined4 *)(iVar2 + 0x2c) = 0x800afdbc;
|
|
|
|
// short duration
|
|
uVar1 = 0x1e00;
|
|
|
|
// if wumpa is less than 10
|
|
if (*(char *)(param_1 + 0x30) < '\n') {
|
|
iVar6 = *(int *)(iVar2 + 0x30);
|
|
}
|
|
|
|
// if wumpa is 10
|
|
else {
|
|
iVar6 = *(int *)(iVar2 + 0x30);
|
|
|
|
// long duration
|
|
uVar1 = 0x2d00;
|
|
}
|
|
|
|
// duration
|
|
*(undefined2 *)(iVar6 + 6) = uVar1;
|
|
|
|
if (
|
|
// If this is human and not AI
|
|
((*(uint *)(param_1 + 0x2c8) & 0x100000) == 0) &&
|
|
|
|
// if this is not a mask grab
|
|
(param_2 != 0)
|
|
)
|
|
{
|
|
// if thread->modelIndex == Uka
|
|
if (*(short *)(iVar2 + 0x44) == 0x3a) {
|
|
uVar5 = 0x54;
|
|
}
|
|
|
|
// if it is not aku
|
|
else
|
|
{
|
|
// if thread->modelIndex == Aku
|
|
if (*(short *)(iVar2 + 0x44) != 0x39) goto LAB_80064d4c;
|
|
uVar5 = 0x53;
|
|
}
|
|
|
|
// OtherFX_Play_Echo
|
|
// activate mask weapon
|
|
FUN_80028494(uVar5,1,*(uint *)(param_1 + 0x2c8) >> 0x10 & 1);
|
|
}
|
|
LAB_80064d4c:
|
|
|
|
// thread -> flags
|
|
*(uint *)(iVar2 + 0x1c) = *(uint *)(iVar2 + 0x1c) & 0xfffff7ff;
|
|
|
|
// return object attached to thread
|
|
return (undefined2 *)*(undefined4 *)(iVar2 + 0x30);
|
|
}
|
|
|
|
// go to next pointer
|
|
iVar2 = *(int *)(iVar2 + 0x10);
|
|
}
|
|
|
|
// VehPickupItem_MaskBoolGoodGuy
|
|
uVar4 = FUN_80064be4(param_1);
|
|
|
|
// If player uses Uka weapon
|
|
if ((uVar4 & 0xffff) == 0)
|
|
{
|
|
// s_doctor1_8008d62c
|
|
// "doctor1"
|
|
|
|
// 0x3a is index of model pointer array
|
|
// for uka head model
|
|
|
|
// 0x300 flag = SmallStackPool
|
|
// 0xd = "other" thread bucket
|
|
iVar2 = FUN_800309a4(0x3a,s_doctor1_8008d62c,0x300,0xd,&DAT_800afdbc,0x14,iVar6);
|
|
|
|
// If this is human and not AI
|
|
if (((*(uint *)(param_1 + 0x2c8) & 0x100000) == 0) &&
|
|
|
|
// OtherFX_Play_Echo
|
|
// uka activate
|
|
(FUN_80028494(0x54,1,*(uint *)(param_1 + 0x2c8) >> 0x10 & 1),
|
|
|
|
1 < (uint)*(byte *)(param_1 + 0x376) - 4))
|
|
{
|
|
// Start playing uka uka mask song
|
|
*(uint *)PTR_DAT_8008d2ac = *(uint *)PTR_DAT_8008d2ac & 0xfeffffff | 0x2000000;
|
|
}
|
|
|
|
// get thread
|
|
iVar6 = *(int *)(iVar2 + 0x6c);
|
|
|
|
// model pointer to uka beam
|
|
uVar5 = *(undefined4 *)(PTR_DAT_8008d2ac + 0x2260);
|
|
}
|
|
|
|
// If player uses Aku weapon
|
|
else
|
|
{
|
|
// s_doctor1_8008d62c
|
|
// "doctor1"
|
|
|
|
// 0x3a is index of model pointer array
|
|
// for aku head model
|
|
|
|
// 0x300 flag = SmallStackPool
|
|
// 0xd = "other" thread bucket
|
|
iVar2 = FUN_800309a4(0x39,s_doctor1_8008d62c,0x300,0xd,&DAT_800afdbc,0x14,iVar6);
|
|
|
|
// If this is human and not AI
|
|
if (((*(uint *)(param_1 + 0x2c8) & 0x100000) == 0) &&
|
|
|
|
// OtherFX_Play_Echo
|
|
// aku mask grab
|
|
(FUN_80028494(0x53,1,*(uint *)(param_1 + 0x2c8) >> 0x10 & 1),
|
|
1 < (uint)*(byte *)(param_1 + 0x376) - 4))
|
|
{
|
|
// Start playing aku aku mask song
|
|
*(uint *)PTR_DAT_8008d2ac = *(uint *)PTR_DAT_8008d2ac & 0xfdffffff | 0x1000000;
|
|
}
|
|
|
|
// get thread from instance
|
|
iVar6 = *(int *)(iVar2 + 0x6c);
|
|
|
|
// model pointer for aku beam
|
|
uVar5 = *(undefined4 *)(PTR_DAT_8008d2ac + 0x2258);
|
|
}
|
|
|
|
// get mask head object from thread
|
|
puVar3 = *(undefined2 **)(iVar6 + 0x30);
|
|
|
|
// INSTANCE_Birth3D -- ptrModel, name, thread
|
|
uVar5 = FUN_8003086c(uVar5,"akubeam1",iVar6);
|
|
|
|
// give beam instance to mask head object
|
|
*(undefined4 *)(puVar3 + 4) = uVar5;
|
|
|
|
// set funcThDestroy to remove instance from instance pool
|
|
*(undefined4 *)(iVar6 + 0x24) = 0x80041dfc;
|
|
|
|
// allow this thread to ignore all collisions
|
|
*(uint *)(iVar6 + 0x1c) = *(uint *)(iVar6 + 0x1c) | 0x1000;
|
|
|
|
// make mask head invisible
|
|
*(uint *)(iVar2 + 0x28) = *(uint *)(iVar2 + 0x28) | 0x80;
|
|
|
|
// make mask beam invisible
|
|
*(uint *)(*(int *)(puVar3 + 4) + 0x28) = *(uint *)(*(int *)(puVar3 + 4) + 0x28) | 0x80;
|
|
|
|
// mask duration without 10 wumpa
|
|
uVar1 = 0x1e00;
|
|
|
|
// if 9 < number of wumpa
|
|
// if wumpa is 10
|
|
if ('\t' < *(char *)(param_1 + 0x30))
|
|
{
|
|
// increased mask duration
|
|
uVar1 = 0x2d00;
|
|
}
|
|
|
|
// duration
|
|
puVar3[3] = uVar1;
|
|
|
|
// rotX
|
|
*puVar3 = 0x40;
|
|
|
|
// rotY
|
|
puVar3[1] = 0;
|
|
|
|
// scale
|
|
puVar3[9] = 0x1000;
|
|
|
|
// rotZ
|
|
puVar3[2] = 0;
|
|
}
|
|
|
|
// return mask object
|
|
return puVar3;
|
|
}
|
|
|
|
|
|
// VehPickupItem_MissileGetTargetDriver
|
|
// param_1 driver who shot weapon
|
|
// return driver who will be chased
|
|
int FUN_80064f94(int param_1)
|
|
|
|
{
|
|
int iVar1;
|
|
int iVar2;
|
|
MATRIX *pMVar3;
|
|
int iVar4;
|
|
int iVar5;
|
|
long *r0;
|
|
int iVar6;
|
|
int iVar7;
|
|
undefined *puVar8;
|
|
undefined *puVar9;
|
|
undefined auStack128 [16];
|
|
undefined2 local_70;
|
|
undefined2 local_6e;
|
|
undefined2 local_6c;
|
|
MATRIX MStack104;
|
|
undefined auStack72 [48];
|
|
|
|
puVar9 = auStack128;
|
|
puVar8 = auStack128;
|
|
|
|
// the ID of the player that the missile will chase
|
|
iVar7 = 0;
|
|
|
|
// set minimum distance from P1 to max possible distance
|
|
iVar6 = 0x7fffffff;
|
|
|
|
// if player shot missile
|
|
// driver -> instance -> thread -> modelIndex == "player" of any kind
|
|
if (*(short *)(*(int *)(*(int *)(param_1 + 0x1c) + 0x6c) + 0x44) == 0x18)
|
|
{
|
|
// pushBuffer ViewProj
|
|
pMVar3 = (MATRIX *)(PTR_DAT_8008d2ac + (uint)*(byte *)(param_1 + 0x4a) * 0x110 + 0x168 + 0x28);
|
|
gte_SetRotMatrix(pMVar3);
|
|
gte_SetTransMatrix(pMVar3);
|
|
puVar9 = puVar8;
|
|
}
|
|
|
|
// if robotcar shot missile
|
|
else
|
|
{
|
|
// get rotation of AI
|
|
local_70 = *(undefined2 *)(param_1 + 0x2ec);
|
|
pMVar3 = &MStack104;
|
|
local_6e = *(undefined2 *)(param_1 + 0x2ee);
|
|
local_6c = *(undefined2 *)(param_1 + 0x2f0);
|
|
|
|
// convert 3 rotation shorts into rotation matrix
|
|
FUN_8006c2a4(pMVar3,&local_70);
|
|
|
|
// get position of AI
|
|
MStack104.t[0] = *(int *)(param_1 + 0x2d4) >> 8;
|
|
MStack104.t[1] = *(int *)(param_1 + 0x2d8) >> 8;
|
|
MStack104.t[2] = *(int *)(param_1 + 0x2dc) >> 8;
|
|
|
|
// output: matrix ???
|
|
// input: missile matrix
|
|
// MATH_HitboxMatrix
|
|
FUN_8003d264(auStack72,pMVar3);
|
|
|
|
gte_SetRotMatrix(pMVar3);
|
|
gte_SetTransMatrix(pMVar3);
|
|
}
|
|
|
|
// loop counter
|
|
iVar5 = 0;
|
|
|
|
r0 = (long *)(puVar9 + 0x60);
|
|
|
|
// for iVar6 = 0; iVar6 < 8; iVar6++
|
|
do
|
|
{
|
|
// get pointer to current player's structure
|
|
iVar4 = *(int *)(PTR_DAT_8008d2ac + iVar5 * 4 + 0x24ec);
|
|
|
|
if (
|
|
(
|
|
// if you hit a player with a weapon that is not yourself
|
|
(
|
|
// if pointer is not nullptr
|
|
(iVar4 != 0) &&
|
|
|
|
// if pointer is not the same as param1
|
|
(iVar4 != param_1)
|
|
) &&
|
|
|
|
// if player hit, is not being picked up by mask
|
|
(*(char *)(iVar4 + 0x376) != '\x05')
|
|
) &&
|
|
|
|
(
|
|
(
|
|
(
|
|
// If you're not in Battle Mode
|
|
(*(uint *)PTR_DAT_8008d2ac & 0x20) == 0 ||
|
|
|
|
// if you are in battle mode,
|
|
// if one player hit another that is on a different team
|
|
(*(int *)(iVar4 + 0x4e8) != *(int *)(param_1 + 0x4e8))
|
|
) &&
|
|
|
|
// if player is not invisible
|
|
(*(int *)(iVar4 + 0x28) == 0)
|
|
)
|
|
)
|
|
)
|
|
|
|
// If you hard-code iVar5 + 0x376 to be 5,
|
|
// player can't be hit, weapons go right through them
|
|
|
|
// however, if player hits another player on the same team,
|
|
// and if this block still does not execute, the player hit still
|
|
// gets animated like any other player getting hit
|
|
|
|
{
|
|
// set position to driver -> instSelf -> position
|
|
*(undefined2 *)(puVar9 + 0x58) = *(undefined2 *)(*(int *)(iVar4 + 0x1c) + 0x44);
|
|
*(undefined2 *)(puVar9 + 0x5a) = *(undefined2 *)(*(int *)(iVar4 + 0x1c) + 0x48);
|
|
*(undefined2 *)(puVar9 + 0x5c) = *(undefined2 *)(*(int *)(iVar4 + 0x1c) + 0x4c);
|
|
gte_ldv0((SVECTOR *)(puVar9 + 0x58));
|
|
|
|
// RTPS - Perspective Transformation (single)
|
|
gte_rtps();
|
|
|
|
gte_stsxy(r0);
|
|
gte_stflg((long *)(puVar9 + 0x64));
|
|
|
|
if (
|
|
(
|
|
// if driver is in front of camera view?
|
|
((*(uint *)(puVar9 + 0x64) & 0x40000) == 0) &&
|
|
|
|
// pixW > 30
|
|
(0x1e < *(short *)(puVar9 + 0x60))
|
|
) &&
|
|
(
|
|
(
|
|
// pixW < pushBuffer[driverID]->rect.w - 30
|
|
(int)*(short *)(puVar9 + 0x60) <
|
|
*(short *)(PTR_DAT_8008d2ac + (uint)*(byte *)(param_1 + 0x4a) * 0x110 + 0x188) + -0x1e &&
|
|
|
|
(
|
|
(
|
|
(
|
|
// pixH > 20
|
|
0x14 < *(short *)((int)r0 + 2) &&
|
|
|
|
(
|
|
// pixH < pushBuffer[driverID]->rect.h - 20
|
|
(int)*(short *)((int)r0 + 2) <
|
|
*(short *)(PTR_DAT_8008d2ac + (uint)*(byte *)(param_1 + 0x4a) * 0x110 + 0x18a) + -0x14
|
|
)
|
|
) &&
|
|
|
|
(
|
|
// get X distance between two players
|
|
iVar1 = *(int *)(iVar4 + 0x2d4) - *(int *)(param_1 + 0x2d4) >> 8,
|
|
|
|
// get Z distance between two players
|
|
iVar2 = *(int *)(iVar4 + 0x2dc) - *(int *)(param_1 + 0x2dc) >> 8,
|
|
|
|
// if player is closer to missile than previous closest player
|
|
iVar1 = iVar1 * iVar1 + iVar2 * iVar2, iVar1 < iVar6
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
{
|
|
// set smallest distance to current distance
|
|
iVar6 = iVar1;
|
|
|
|
// set closest player to this player
|
|
iVar7 = iVar4;
|
|
}
|
|
}
|
|
|
|
// increment loop counter
|
|
iVar5 = iVar5 + 1;
|
|
|
|
} while (iVar5 < 8);
|
|
|
|
// return address of player that missile will chase
|
|
return iVar7;
|
|
}
|
|
|
|
|
|
// VehPickupItem_PotionThrow
|
|
// param1 is object
|
|
// param2 is instance
|
|
// param3 is flags (like throw forward potion)
|
|
undefined4 FUN_800652c8(int param_1,int param_2,uint param_3)
|
|
|
|
{
|
|
short sVar1;
|
|
uint uVar2;
|
|
int iVar3;
|
|
undefined2 uVar4;
|
|
|
|
// For TNTs param3 != 0 shoots tnt up into air,
|
|
// direction does not change (komodo joe)
|
|
|
|
// For Potions
|
|
// param3 & 1 shoots back a short distance
|
|
// param3 & 2 shoots back a long distance
|
|
// param3 & 4 shoots forward (hold up on d-pad)
|
|
|
|
// if you dont want to throw forward
|
|
if ((param_3 & 4) == 0)
|
|
{
|
|
// if you dont want to throw back long
|
|
if ((param_3 & 2) == 0)
|
|
{
|
|
// if you dont want to throw back short
|
|
if ((param_3 & 1) == 0)
|
|
{
|
|
// just quit and drop weapon as-is
|
|
return 0;
|
|
}
|
|
|
|
// if you want to throw back short
|
|
|
|
uVar2 = FUN_8006c684(&DAT_8008d668);
|
|
iVar3 = (uVar2 & 0x1f) - 0x10;
|
|
*(undefined2 *)(param_1 + 0xc) = (short)(*(short *)(param_2 + 0x34) * iVar3 >> 0xc);
|
|
sVar1 = *(short *)(param_2 + 0x40);
|
|
*(undefined2 *)(param_1 + 0xe) = 0x30;
|
|
*(undefined4 *)(param_1 + 8) = 0;
|
|
*(ushort *)(param_1 + 0x28) = *(ushort *)(param_1 + 0x28) | 2;
|
|
uVar4 = (undefined2)(sVar1 * iVar3 >> 0xc);
|
|
}
|
|
|
|
// if you want to throw back long
|
|
else {
|
|
*(undefined2 *)(param_1 + 0xc) = (short)((int)*(short *)(param_2 + 0x34) * -0x78 >> 0xc);
|
|
sVar1 = *(short *)(param_2 + 0x40);
|
|
*(undefined2 *)(param_1 + 0xe) = 0x30;
|
|
*(undefined4 *)(param_1 + 8) = 0;
|
|
*(ushort *)(param_1 + 0x28) = *(ushort *)(param_1 + 0x28) | 2;
|
|
uVar4 = (undefined2)((int)sVar1 * -0x78 >> 0xc);
|
|
}
|
|
}
|
|
|
|
// if you want to throw forward
|
|
else {
|
|
*(undefined2 *)(param_1 + 0xc) = (short)((int)*(short *)(param_2 + 0x34) * 0xf >> 9);
|
|
sVar1 = *(short *)(param_2 + 0x40);
|
|
*(undefined2 *)(param_1 + 0xe) = 0x30;
|
|
*(undefined4 *)(param_1 + 8) = 0;
|
|
*(ushort *)(param_1 + 0x28) = *(ushort *)(param_1 + 0x28) | 2;
|
|
uVar4 = (undefined2)((int)sVar1 * 0xf >> 9);
|
|
}
|
|
*(undefined2 *)(param_1 + 0x10) = uVar4;
|
|
return 1;
|
|
}
|
|
|
|
|
|
// VehPickupItem_ShootNow
|
|
void FUN_8006540c(int param_1,undefined4 param_2,uint param_3)
|
|
// param1 is the address of the player/AI structure that fired the weapon
|
|
// param2 is weaponID
|
|
// param3 is "special" like throwing potions backward, or TNTs airborne
|
|
{
|
|
undefined2 uVar1;
|
|
short sVar2;
|
|
int iVar3;
|
|
int iVar4;
|
|
int iVar5;
|
|
uint uVar6;
|
|
undefined4 uVar7;
|
|
int iVar8;
|
|
int iVar9;
|
|
char *pcVar10;
|
|
undefined2 *puVar11;
|
|
undefined *puVar12;
|
|
undefined4 local_48;
|
|
undefined4 uVar13;
|
|
int iVar14;
|
|
int *piVar15;
|
|
undefined4 *puVar16;
|
|
undefined2 local_40;
|
|
short local_3e;
|
|
undefined2 local_3c;
|
|
undefined2 local_38;
|
|
short local_36;
|
|
undefined2 local_34;
|
|
undefined2 local_30;
|
|
short local_2e;
|
|
undefined2 local_2c;
|
|
undefined2 local_28;
|
|
short local_26;
|
|
undefined2 local_24;
|
|
|
|
// param1 is weapon ID
|
|
switch(param_2)
|
|
{
|
|
|
|
// If your weapon is Turbo
|
|
case 0:
|
|
|
|
// small boost
|
|
uVar7 = 0x80;
|
|
|
|
// if 9 < number of wumpa
|
|
// basically if wumpa < 10
|
|
if ('\t' < *(char *)(param_1 + 0x30))
|
|
{
|
|
// bigger boost
|
|
uVar7 = 0x100;
|
|
}
|
|
|
|
// VehFire_Increment
|
|
// 2.4 seconds reserve
|
|
FUN_8005abfc(param_1,0x960,9,uVar7);
|
|
|
|
break;
|
|
|
|
// Shared code for Bomb and Missile
|
|
case 2:
|
|
|
|
// If there are more than 11 missiles on screen
|
|
if (0xb < *(int *)(PTR_DAT_8008d2ac + 0x1ec0))
|
|
{
|
|
// Quit, dont shoot more missiles
|
|
return;
|
|
}
|
|
|
|
// set closest distance from missile-shooter to player, to max value,
|
|
// so that we can loop through other players to find smaller distance
|
|
iVar5 = 0x7fffffff;
|
|
|
|
// number of missiles launched by player
|
|
*(char *)(param_1 + 0x55c) = *(char *)(param_1 + 0x55c) + '\x01';
|
|
|
|
// increment number of missiles that are on screen
|
|
*(int *)(PTR_DAT_8008d2ac + 0x1ec0) = *(int *)(PTR_DAT_8008d2ac + 0x1ec0) + 1;
|
|
|
|
// GAMEPAD_ShockFreq and GAMEPAD_ShockForce1
|
|
FUN_80026440(param_1,8,0);
|
|
FUN_800264c0(param_1,8,0x7f);
|
|
|
|
// VehPickupItem_MissileGetTargetDriver
|
|
iVar8 = FUN_80064f94(param_1);
|
|
|
|
// if a player was not found to chase
|
|
if (iVar8 == 0)
|
|
{
|
|
iVar14 = 0;
|
|
puVar12 = PTR_DAT_8008d2ac;
|
|
|
|
// If you're not in Battle Mode
|
|
if ((*(uint *)PTR_DAT_8008d2ac & 0x20) == 0)
|
|
{
|
|
if (
|
|
(
|
|
// driver -> instance -> thread -> modelIndex
|
|
(*(short *)(*(int *)(*(int *)(param_1 + 0x1c) + 0x6c) + 0x44) != 0x18) &&
|
|
|
|
// if racer is not in first place
|
|
((int)*(short *)(param_1 + 0x482) != 0)
|
|
) &&
|
|
|
|
// if time on clock is an odd number
|
|
((*(uint *)(PTR_DAT_8008d2ac + 0x1d10) & 1) != 0)
|
|
)
|
|
{
|
|
// the missile chases the driver, one place ahead of the driver that fired the weapon
|
|
iVar8 = *(int *)(PTR_DAT_8008d2ac + ((int)*(short *)(param_1 + 0x482) + -1) * 4 + 0x250c);
|
|
}
|
|
}
|
|
|
|
// if you are in battle
|
|
else
|
|
{
|
|
// loop through all players to find
|
|
// the closest player that the missile can seek
|
|
|
|
// for iVar14 = 0; iVar14 < 8; iVar14++
|
|
do
|
|
{
|
|
// get address of player structure
|
|
iVar9 = *(int *)(puVar12 + 0x24ec);
|
|
|
|
if (
|
|
(
|
|
(
|
|
// if pointer is not nullptr
|
|
(iVar9 != 0) &&
|
|
|
|
// if player is not the missile shooter
|
|
(iVar9 != param_1)
|
|
) &&
|
|
|
|
(
|
|
(
|
|
// if enemy player is being picked up by mask
|
|
*(char *)(iVar9 + 0x376) != '\x05' &&
|
|
|
|
(
|
|
(
|
|
// if two players are not on same team in battle mode
|
|
*(int *)(iVar9 + 0x4e8) != *(int *)(param_1 + 0x4e8) &&
|
|
|
|
// if player is not invisible
|
|
(*(int *)(iVar9 + 0x28) == 0)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
) &&
|
|
(
|
|
// Get the X distance between two players
|
|
iVar3 = *(int *)(iVar9 + 0x2d4) - *(int *)(param_1 + 0x2d4) >> 8,
|
|
|
|
// Get the Z distance between two players
|
|
iVar4 = *(int *)(iVar9 + 0x2dc) - *(int *)(param_1 + 0x2dc) >> 8,
|
|
|
|
// Get the distance between two players
|
|
iVar3 = iVar3 * iVar3 + iVar4 * iVar4,
|
|
|
|
// if player is closer to missile shooter than previous closest player
|
|
iVar3 < iVar5
|
|
)
|
|
)
|
|
{
|
|
// set smallest distance to current distance
|
|
iVar5 = iVar3;
|
|
|
|
// set closest player to this player
|
|
iVar8 = iVar9;
|
|
}
|
|
|
|
// increment loop iteration counter
|
|
iVar14 = iVar14 + 1;
|
|
|
|
// increment pointer
|
|
puVar12 = puVar12 + 4;
|
|
} while (iVar14 < 8);
|
|
|
|
// when this loop ends, iVar8 is the player that the missile is tracking
|
|
|
|
}
|
|
}
|
|
|
|
if (
|
|
// if weapon is 1 missile
|
|
(*(char *)(param_1 + 0x36) == 2) ||
|
|
(
|
|
// not missile, use bomb model
|
|
uVar7 = 0x3b,
|
|
|
|
// if weapon is three missiles
|
|
*(char *)(param_1 + 0x36) == 11
|
|
)
|
|
)
|
|
{
|
|
// missile model
|
|
uVar7 = 0x29;
|
|
|
|
pcVar10 = "bombtracker1";
|
|
|
|
// 6 = "tracking" thread bucket
|
|
uVar13 = 6;
|
|
|
|
local_48 = 0;
|
|
}
|
|
else
|
|
{
|
|
// s_bomb1_8008d634
|
|
// "bomb1"
|
|
pcVar10 = s_bomb1_8008d634;
|
|
|
|
// driver -> instance -> thread
|
|
local_48 = *(undefined4 *)(*(int *)(param_1 + 0x1c) + 0x6c);
|
|
|
|
// 0xd = "other" thread bucket
|
|
uVar13 = 0xd;
|
|
}
|
|
|
|
// make thread for bomb or missile
|
|
// 0x200 flag = MediumStackPool
|
|
iVar5 = FUN_800309a4(uVar7,pcVar10,0x200,uVar13,FUN_800adb50,0x58,local_48);
|
|
|
|
// driver instance
|
|
iVar14 = *(int *)(param_1 + 0x1c);
|
|
|
|
// copy driver position, rotation, and scale
|
|
// into missile position, rotation, and scale
|
|
uVar7 = *(undefined4 *)(iVar14 + 0x34);
|
|
local_48 = *(undefined4 *)(iVar14 + 0x38);
|
|
uVar13 = *(undefined4 *)(iVar14 + 0x3c);
|
|
*(undefined4 *)(iVar5 + 0x30) = *(undefined4 *)(iVar14 + 0x30);
|
|
*(undefined4 *)(iVar5 + 0x34) = uVar7;
|
|
*(undefined4 *)(iVar5 + 0x38) = local_48;
|
|
*(undefined4 *)(iVar5 + 0x3c) = uVar13;
|
|
uVar7 = *(undefined4 *)(iVar14 + 0x44);
|
|
local_48 = *(undefined4 *)(iVar14 + 0x48);
|
|
uVar13 = *(undefined4 *)(iVar14 + 0x4c);
|
|
*(undefined4 *)(iVar5 + 0x40) = *(undefined4 *)(iVar14 + 0x40);
|
|
*(undefined4 *)(iVar5 + 0x44) = uVar7;
|
|
*(undefined4 *)(iVar5 + 0x48) = local_48;
|
|
*(undefined4 *)(iVar5 + 0x4c) = uVar13;
|
|
|
|
// VehPhysForce_RotAxisAngle
|
|
// rotation matrix of weapon,
|
|
// face direction of driver facing, even with drift applied
|
|
FUN_8005f89c(iVar5 + 0x30,param_1 + 0x360,(int)*(short *)(param_1 + 0x2ee));
|
|
|
|
// PROC_DestroyTracker
|
|
// when missile needs to be destroyed,
|
|
// decrease number of missiles,
|
|
*(undefined4 *)(*(int *)(iVar5 + 0x6c) + 0x24) = 0x80041dc0;
|
|
|
|
// RB_Hazard_ThCollide_Missile, remove 2D target being drawn on them
|
|
*(undefined4 *)(*(int *)(iVar5 + 0x6c) + 0x28) = 0x800ac42c;
|
|
|
|
// instance -> thread -> object
|
|
piVar15 = *(int **)(*(int *)(iVar5 + 0x6c) + 0x30);
|
|
|
|
*(undefined2 *)((int)piVar15 + 0x16) = 0;
|
|
|
|
// record pointer that shot the missile
|
|
piVar15[1] = param_1;
|
|
|
|
piVar15[0x12] = 0;
|
|
piVar15[0x15] = 0;
|
|
piVar15[9] = 0;
|
|
|
|
// if weapon is one bowling bomb or three bowling bombs
|
|
if ((*(char *)(param_1 + 0x36) == 1) || (*(char *)(param_1 + 0x36) == 10))
|
|
{
|
|
// CTR_MatrixToRot
|
|
// iVar5+0x30 is weapon inst->matrix
|
|
FUN_80021edc(&local_40,iVar5 + 0x30,0x11);
|
|
|
|
// 6*4 = 0x18, missile->dir[x]
|
|
*(short *)(piVar15 + 6) = local_3e;
|
|
|
|
// missile->dir[y]
|
|
*(undefined2 *)((int)piVar15 + 0x1a) = local_40;
|
|
|
|
// tw->driverTarget
|
|
*piVar15 = iVar8;
|
|
|
|
// 7*4 = 0x1C, missile->dir[z]
|
|
*(undefined2 *)(piVar15 + 7) = local_3c;
|
|
|
|
// d->instBombThrow
|
|
*(int *)(param_1 + 0x10) = iVar5;
|
|
|
|
// PlaySound3D
|
|
FUN_8002f0dc(0x47,iVar5);
|
|
|
|
// get flags of driver that shot bombs
|
|
uVar6 = *(uint *)(param_1 + 0x2c8);
|
|
|
|
uVar7 = 10;
|
|
}
|
|
|
|
// if weapon is missile
|
|
else
|
|
{
|
|
// RB_Hazard_ThCollide_Missile
|
|
*(undefined4 *)(*(int *)(iVar5 + 0x6c) + 0x28) = 0x800ac42c;
|
|
|
|
// if missile does not have a target
|
|
if (iVar8 == 0)
|
|
{
|
|
// set target to nullptr,
|
|
*piVar15 = 0;
|
|
}
|
|
|
|
// if missile has a target
|
|
else
|
|
{
|
|
// save address of player structure of target
|
|
*piVar15 = iVar8;
|
|
|
|
// if player is not aware a missile is chasing them
|
|
if (*(int *)(iVar8 + 0x4a4) == 0)
|
|
{
|
|
// RB_GetThread_ClosestTracker (missile or warpball)
|
|
uVar7 = FUN_800b28c0(iVar8);
|
|
|
|
// Give the player a pointer to the missile chasing them
|
|
*(undefined4 *)(iVar8 + 0x4a4) = uVar7;
|
|
}
|
|
}
|
|
|
|
// PlaySound3D
|
|
FUN_8002f0dc(0x4a,iVar5);
|
|
|
|
// get flags of the driver who shot the missile
|
|
uVar6 = *(uint *)(param_1 + 0x2c8);
|
|
|
|
uVar7 = 0xb;
|
|
}
|
|
|
|
// If driver shooting is human and not AI
|
|
if ((uVar6 & 0x100000) == 0)
|
|
{
|
|
// Make driver talk
|
|
FUN_8002cbe8(uVar7,(int)(short)(&DAT_80086e84)[*(byte *)(param_1 + 0x4a)],0x10);
|
|
}
|
|
|
|
uVar1 = *(undefined2 *)(param_1 + 0x2ee);
|
|
*(undefined2 *)((int)piVar15 + 0x12) = 0;
|
|
*(undefined2 *)((int)piVar15 + 0x1e) = uVar1;
|
|
|
|
// if weapon is one bowling bomb, or three bowling bombs
|
|
if ((*(char *)(param_1 + 0x36) == '\x01') || (*(char *)(param_1 + 0x36) == '\n'))
|
|
{
|
|
*(short *)(piVar15 + 4) = (short)((int)*(short *)(iVar5 + 0x34) * 3 >> 7);
|
|
*(short *)(piVar15 + 5) = (short)((int)*(short *)(iVar5 + 0x40) * 3 >> 7);
|
|
|
|
// if 9 < number of wumpa
|
|
// if wumpa is 10
|
|
if ('\t' < *(char *)(param_1 + 0x30))
|
|
{
|
|
*(ushort *)((int)piVar15 + 0x16) = *(ushort *)((int)piVar15 + 0x16) | 1;
|
|
}
|
|
|
|
// If you press Down on D-Pad
|
|
if (((*(uint *)(PTR_DAT_8008d2b0 + (uint)*(byte *)(param_1 + 0x4a) * 0x50 + 0x10) & 2) != 0)
|
|
|
|
// or if you are pinstripe boss, I assume???
|
|
|| ((param_3 & 2) != 0))
|
|
{
|
|
// roll bomb backwards
|
|
*(ushort *)((int)piVar15 + 0x16) = *(ushort *)((int)piVar15 + 0x16) | 0x20;
|
|
|
|
*(short *)(piVar15 + 4) =
|
|
-(short)((((int)((uint)*(ushort *)(piVar15 + 4) << 0x10) >> 0x11) * 3) / 5);
|
|
sVar2 = -(short)((((int)((uint)*(ushort *)(piVar15 + 5) << 0x10) >> 0x11) * 3) / 5);
|
|
goto LAB_800659ec;
|
|
}
|
|
}
|
|
|
|
// if weapon is not bowling bomb
|
|
else
|
|
{
|
|
// if wumpa < 10
|
|
if (*(char *)(param_1 + 0x30) < '\n') {
|
|
*(short *)(piVar15 + 4) = (short)((uint)((int)*(short *)(iVar5 + 0x34) * 5) >> 8);
|
|
sVar2 = (short)((uint)((int)*(short *)(iVar5 + 0x40) * 5) >> 8);
|
|
}
|
|
|
|
// if wumpa is 10
|
|
else
|
|
{
|
|
*(short *)(piVar15 + 4) = (short)((int)*(short *)(iVar5 + 0x34) * 3 >> 7);
|
|
sVar2 = *(short *)(iVar5 + 0x40);
|
|
*(ushort *)((int)piVar15 + 0x16) = *(ushort *)((int)piVar15 + 0x16) | 1;
|
|
sVar2 = (short)((int)sVar2 * 3 >> 7);
|
|
}
|
|
LAB_800659ec:
|
|
*(short *)(piVar15 + 5) = sVar2;
|
|
}
|
|
*(undefined2 *)(piVar15 + 8) = 0x3c;
|
|
*(undefined2 *)((int)piVar15 + 0x22) = 0;
|
|
|
|
// record the driver who shot the tracker
|
|
piVar15[2] = *(int *)(param_1 + 0x1c);
|
|
|
|
break;
|
|
|
|
// if weapon ID is TNT / Nitro
|
|
case 3:
|
|
|
|
// If number of wumpa fruit is less than 10
|
|
if (*(char *)(param_1 + 0x30) < '\n')
|
|
{
|
|
uVar7 = 0x27;
|
|
|
|
// DAT_8008d64c
|
|
// "tnt1"
|
|
pcVar10 = &DAT_8008d64c;
|
|
}
|
|
|
|
// if you have 10 wumpa fruit
|
|
else
|
|
{
|
|
uVar7 = 6;
|
|
|
|
// s_nitro1_8008d644
|
|
// "nitro1"
|
|
pcVar10 = s_nitro1_8008d644;
|
|
}
|
|
|
|
// make TNT or Nitro thread
|
|
// 0x300 flag = SmallStackPool
|
|
// 4 = "mine" thread bucket
|
|
iVar5 = FUN_800309a4(uVar7,pcVar10,0x300,4,&DAT_800acb60,0x2c,0);
|
|
|
|
// get instance from driver
|
|
iVar8 = *(int *)(param_1 + 0x1c);
|
|
|
|
// copy rotation from driver, into weapon
|
|
uVar7 = *(undefined4 *)(iVar8 + 0x34);
|
|
local_48 = *(undefined4 *)(iVar8 + 0x38);
|
|
uVar13 = *(undefined4 *)(iVar8 + 0x3c);
|
|
*(undefined4 *)(iVar5 + 0x30) = *(undefined4 *)(iVar8 + 0x30);
|
|
*(undefined4 *)(iVar5 + 0x34) = uVar7;
|
|
*(undefined4 *)(iVar5 + 0x38) = local_48;
|
|
*(undefined4 *)(iVar5 + 0x3c) = uVar13;
|
|
|
|
// get position from player
|
|
uVar7 = *(undefined4 *)(iVar8 + 0x44);
|
|
local_48 = *(undefined4 *)(iVar8 + 0x48);
|
|
uVar13 = *(undefined4 *)(iVar8 + 0x4c);
|
|
|
|
// one more rotation variable
|
|
*(undefined4 *)(iVar5 + 0x40) = *(undefined4 *)(iVar8 + 0x40);
|
|
|
|
// set position of weapon
|
|
*(undefined4 *)(iVar5 + 0x44) = uVar7;
|
|
*(undefined4 *)(iVar5 + 0x48) = local_48;
|
|
*(undefined4 *)(iVar5 + 0x4c) = uVar13;
|
|
|
|
// set scale (x, y, z)
|
|
*(undefined2 *)(iVar5 + 0x1c) = 0;
|
|
*(undefined2 *)(iVar5 + 0x1e) = 0;
|
|
*(undefined2 *)(iVar5 + 0x20) = 0;
|
|
|
|
// set funcThDestroy to remove instance from instance pool
|
|
*(undefined4 *)(*(int *)(iVar5 + 0x6c) + 0x24) = 0x80041dfc;
|
|
|
|
// set funcThCollide function
|
|
*(undefined4 *)(*(int *)(iVar5 + 0x6c) + 0x28) = 0x800ac4b8;
|
|
|
|
// PlaySound3D
|
|
FUN_8002f0dc(0x52,iVar5);
|
|
|
|
// If this is human and not AI
|
|
if ((*(uint *)(param_1 + 0x2c8) & 0x100000) == 0)
|
|
{
|
|
// Make driver talk
|
|
FUN_8002cbe8(0xf,(int)(short)(&DAT_80086e84)[*(byte *)(param_1 + 0x4a)],0x10);
|
|
}
|
|
|
|
// instance -> thread -> object (mw)
|
|
puVar16 = *(undefined4 **)(*(int *)(iVar5 + 0x6c) + 0x30);
|
|
|
|
// mw->instParent
|
|
puVar16[1] = *(undefined4 *)(param_1 + 0x1c);
|
|
|
|
// mw->velocity (x,y,z)
|
|
*(undefined2 *)(puVar16 + 3) = 0;
|
|
*(undefined2 *)((int)puVar16 + 0xe) = 0;
|
|
*(undefined2 *)(puVar16 + 4) = 0;
|
|
|
|
// mw->frameCount_DontHurtParent
|
|
*(undefined2 *)(puVar16 + 9) = 10;
|
|
|
|
*(undefined2 *)(puVar16 + 5) = 0;
|
|
*(undefined2 *)((int)puVar16 + 0x26) = 0;
|
|
*puVar16 = 0;
|
|
puVar16[2] = 0;
|
|
*(undefined2 *)(puVar16 + 10) = 0;
|
|
|
|
// RB_MinePool_Add
|
|
FUN_800ac13c(puVar16);
|
|
|
|
// VehPickupItem_PotionThrow
|
|
FUN_800652c8(puVar16,iVar5,param_3);
|
|
|
|
// instancePos - Y
|
|
local_40 = *(undefined2 *)(iVar5 + 0x44);
|
|
local_3e = *(short *)(iVar5 + 0x48) + -400;
|
|
local_3c = *(undefined2 *)(iVar5 + 0x4c);
|
|
|
|
// instancePos + Y
|
|
local_38 = *(undefined2 *)(iVar5 + 0x44);
|
|
local_36 = *(short *)(iVar5 + 0x48) + 0x40;
|
|
local_34 = *(undefined2 *)(iVar5 + 0x4c);
|
|
|
|
// ground quadblock flags
|
|
DAT_1f80012c = 0x1000;
|
|
|
|
DAT_1f800130 = 0;
|
|
|
|
// low-LOD collision (2 triangles)
|
|
DAT_1f80012a = 1;
|
|
|
|
// if numPlyrCurrGame is less than 3
|
|
if ((byte)PTR_DAT_8008d2ac[0x1ca8] < 3)
|
|
{
|
|
// high-LOD collision (8 triangles)
|
|
DAT_1f80012a = 3;
|
|
}
|
|
|
|
DAT_1f800134 = **(undefined4 **)(PTR_DAT_8008d2ac + 0x160);
|
|
|
|
// COLL_SearchTree_FindQuadblock_Touching
|
|
FUN_8001eb0c(&local_40,&local_38,&DAT_1f800108,0x40);
|
|
|
|
if (DAT_1f80014a == 0) {
|
|
puVar16[2] = 0;
|
|
}
|
|
else {
|
|
DAT_1f800114 = *(ushort *)(*(int *)(iVar5 + 0x18) + 0x10) | 0x8000;
|
|
|
|
// RB_Hazard_CollLevInst
|
|
FUN_800ad9ac(&DAT_1f800108,*(undefined4 *)(iVar5 + 0x6c));
|
|
|
|
// InstDef -> modelID
|
|
sVar2 = *(short *)(*(int *)(DAT_1f800150 + 0x1c) + 0x3c);
|
|
|
|
// fruit crate or weapon crate
|
|
if ((sVar2 == 7) || (sVar2 == 8))
|
|
{
|
|
// save mineWeapon->crateInst as...
|
|
// InstDef -> ptrInstance
|
|
puVar16[2] = *(undefined4 *)(*(int *)(DAT_1f800150 + 0x1c) + 0x2c);
|
|
}
|
|
else
|
|
{
|
|
// RB_GenericMine_ThDestroy
|
|
FUN_800ad250(*(undefined4 *)(iVar5 + 0x6c),iVar5,puVar16);
|
|
}
|
|
|
|
// low-LOD collision (2 triangles)
|
|
DAT_1f80012a = 0;
|
|
|
|
// COLL_SearchTree_FindQuadblock_Touching
|
|
FUN_8001eb0c(&local_40,&local_38,&DAT_1f800108,0);
|
|
}
|
|
|
|
// RB_MakeInstanceReflective
|
|
FUN_800abab0(&DAT_1f800108,iVar5);
|
|
|
|
// if quadblock was not found
|
|
if (DAT_1f800146 == 0)
|
|
{
|
|
*(undefined2 *)((int)puVar16 + 0x12) = *(undefined2 *)(iVar5 + 0x48);
|
|
|
|
local_40 = 0;
|
|
local_3e = 0x1000;
|
|
local_3c = 0;
|
|
|
|
sVar2 = *(short *)(param_1 + 0x39a);
|
|
puVar11 = &local_40;
|
|
}
|
|
|
|
// if quadblock was found
|
|
else {
|
|
*(undefined2 *)((int)puVar16 + 0x12) = DAT_1f800124._2_2_;
|
|
sVar2 = *(short *)(param_1 + 0x39a);
|
|
puVar11 = &DAT_1f800178;
|
|
}
|
|
|
|
// VehPhysForce_RotAxisAngle
|
|
// generate TNT/Nitro rotation matrix,
|
|
// with driver rotation, and quadblock rotation
|
|
FUN_8005f89c(iVar5 + 0x30,puVar11,(int)sVar2);
|
|
|
|
// instTntSend
|
|
*(int *)(param_1 + 0x20) = iVar5;
|
|
|
|
*(uint *)(param_1 + 0x2c8) = *(uint *)(param_1 + 0x2c8) | 0x80000000;
|
|
|
|
if (param_3 == 0)
|
|
{
|
|
// RB_Follower_Init
|
|
FUN_800b6f00(param_1,*(undefined4 *)(iVar5 + 0x6c));
|
|
}
|
|
|
|
break;
|
|
|
|
// if Weapon ID is beaker
|
|
case 4:
|
|
|
|
// if you have less than 10 wumpa fruit
|
|
if (*(char *)(param_1 + 0x30) < '\n')
|
|
{
|
|
// "beaker1"
|
|
// 0x47 = green beaker
|
|
|
|
// 0x300 flag = SmallStackPool
|
|
// 4 = "mine" thread bucket
|
|
iVar5 = FUN_800309a4(0x47,s_beaker1_8008d654,0x300,4,&FUN_800acb60,0x2c,0);
|
|
|
|
// if thread failed, then quit
|
|
if (iVar5 == 0) {
|
|
return;
|
|
}
|
|
|
|
// instance -> thread -> object
|
|
iVar8 = *(int *)(*(int *)(iVar5 + 0x6c) + 0x30);
|
|
|
|
// green beaker, not red
|
|
*(undefined2 *)(iVar8 + 0x28) = 0;
|
|
}
|
|
|
|
// if you have 10 wumpa fruit
|
|
else
|
|
{
|
|
// "beaker1"
|
|
// 0x46 = red beaker
|
|
|
|
// 0x300 flag = SmallStackPool
|
|
// 4 = "mine" thread bucket
|
|
iVar5 = FUN_800309a4(0x46,s_beaker1_8008d654,0x300,4,&FUN_800acb60,0x2c,0);
|
|
|
|
// instance->thread->object
|
|
iVar8 = *(int *)(*(int *)(iVar5 + 0x6c) + 0x30);
|
|
|
|
// red beaker
|
|
*(undefined2 *)(iVar8 + 0x28) = 1;
|
|
}
|
|
|
|
// get instance from player
|
|
iVar14 = *(int *)(param_1 + 0x1c);
|
|
|
|
// get player rotation
|
|
uVar7 = *(undefined4 *)(iVar14 + 0x34);
|
|
local_48 = *(undefined4 *)(iVar14 + 0x38);
|
|
uVar13 = *(undefined4 *)(iVar14 + 0x3c);
|
|
|
|
// set potion rotation to player rotation (4 of 5)
|
|
*(undefined4 *)(iVar5 + 0x30) = *(undefined4 *)(iVar14 + 0x30);
|
|
*(undefined4 *)(iVar5 + 0x34) = uVar7;
|
|
*(undefined4 *)(iVar5 + 0x38) = local_48;
|
|
*(undefined4 *)(iVar5 + 0x3c) = uVar13;
|
|
|
|
// get player position
|
|
uVar7 = *(undefined4 *)(iVar14 + 0x44);
|
|
local_48 = *(undefined4 *)(iVar14 + 0x48);
|
|
uVar13 = *(undefined4 *)(iVar14 + 0x4c);
|
|
|
|
// rotation (last of 5)
|
|
*(undefined4 *)(iVar5 + 0x40) = *(undefined4 *)(iVar14 + 0x40);
|
|
|
|
// set potion position to player position
|
|
*(undefined4 *)(iVar5 + 0x44) = uVar7;
|
|
*(undefined4 *)(iVar5 + 0x48) = local_48;
|
|
*(undefined4 *)(iVar5 + 0x4c) = uVar13;
|
|
|
|
// beakerInst -> model -> header
|
|
iVar14 = *(int *)(*(int *)(iVar5 + 0x18) + 0x14);
|
|
|
|
// header -> flag: always face camera
|
|
*(ushort *)(iVar14 + 0x16) = *(ushort *)(iVar14 + 0x16) | 2;
|
|
|
|
// set funcThDestroy to remove instance from instance pool
|
|
*(undefined4 *)(*(int *)(iVar5 + 0x6c) + 0x24) = 0x80041dfc;
|
|
|
|
// set funcThCollide
|
|
*(undefined4 *)(*(int *)(iVar5 + 0x6c) + 0x28) = 0x800ac4b8;
|
|
|
|
// get instance of driver
|
|
uVar7 = *(undefined4 *)(param_1 + 0x1c);
|
|
|
|
*(undefined2 *)(iVar8 + 0x24) = 10;
|
|
*(undefined2 *)(iVar8 + 0x14) = 0;
|
|
*(undefined4 *)(iVar8 + 8) = 0;
|
|
|
|
// save the driver who placed the weapon
|
|
*(undefined4 *)(iVar8 + 4) = uVar7;
|
|
|
|
// PlaySound3D
|
|
FUN_8002f0dc(0x52,iVar5);
|
|
|
|
// If this is human and not AI
|
|
if ((*(uint *)(param_1 + 0x2c8) & 0x100000) == 0)
|
|
{
|
|
// Make driver talk
|
|
FUN_8002cbe8(0xf,(int)(short)(&DAT_80086e84)[*(byte *)(param_1 + 0x4a)],0x10);
|
|
}
|
|
|
|
// RB_MinePool_Add
|
|
FUN_800ac13c(iVar8);
|
|
|
|
// If you hold Up on D-Pad
|
|
if ((*(uint *)(PTR_DAT_8008d2b0 + (uint)*(byte *)(param_1 + 0x4a) * 0x50 + 0x10) & 1) != 0)
|
|
{
|
|
// Shoot potion forward
|
|
param_3 = param_3 | 4;
|
|
}
|
|
|
|
// VehPickupItem_PotionThrow
|
|
uVar6 = FUN_800652c8(iVar8,iVar5,param_3);
|
|
|
|
// if mine is not "thrown", just "dropped"
|
|
if ((uVar6 & 0xffff) == 0)
|
|
{
|
|
// set scale to zero, thread will make it grow
|
|
*(undefined2 *)(iVar5 + 0x1c) = 0;
|
|
*(undefined2 *)(iVar5 + 0x1e) = 0;
|
|
*(undefined2 *)(iVar5 + 0x20) = 0;
|
|
|
|
*(undefined2 *)(iVar8 + 0xc) = 0;
|
|
*(undefined2 *)(iVar8 + 0xe) = 0;
|
|
*(undefined2 *)(iVar8 + 0x10) = 0;
|
|
|
|
// hit top
|
|
local_30 = *(undefined2 *)(iVar5 + 0x44);
|
|
local_2e = *(short *)(iVar5 + 0x48) + -400;
|
|
local_2c = *(undefined2 *)(iVar5 + 0x4c);
|
|
|
|
// hit bottom
|
|
local_28 = *(undefined2 *)(iVar5 + 0x44);
|
|
local_26 = *(short *)(iVar5 + 0x48) + 0x40;
|
|
local_24 = *(undefined2 *)(iVar5 + 0x4c);
|
|
|
|
// ground quadblock flags
|
|
DAT_1f80012c = 0x1000;
|
|
|
|
DAT_1f800130 = 0;
|
|
|
|
// low-LOD collision (2 triangles)
|
|
DAT_1f80012a = 1;
|
|
|
|
// if numPlyrCurrGame is less than 3
|
|
if ((byte)PTR_DAT_8008d2ac[0x1ca8] < 3)
|
|
{
|
|
// high-LOD collision (8 triangles)
|
|
DAT_1f80012a = 3;
|
|
}
|
|
|
|
DAT_1f800134 = **(undefined4 **)(PTR_DAT_8008d2ac + 0x160);
|
|
|
|
// COLL_SearchTree_FindQuadblock_Touching
|
|
FUN_8001eb0c(&local_30,&local_28,&DAT_1f800108,0x40);
|
|
|
|
if (DAT_1f80014a == 0) {
|
|
*(undefined4 *)(iVar8 + 8) = 0;
|
|
}
|
|
else {
|
|
DAT_1f800114 = *(ushort *)(*(int *)(iVar5 + 0x18) + 0x10);
|
|
|
|
// RB_Hazard_CollLevInst
|
|
FUN_800ad9ac(&DAT_1f800108,*(undefined4 *)(iVar5 + 0x6c));
|
|
|
|
sVar2 = *(short *)(*(int *)(DAT_1f800150 + 0x1c) + 0x3c);
|
|
if ((sVar2 == 7) || (sVar2 == 8)) {
|
|
*(undefined4 *)(iVar8 + 8) = *(undefined4 *)(*(int *)(DAT_1f800150 + 0x1c) + 0x2c);
|
|
}
|
|
else
|
|
{
|
|
// RB_GenericMine_ThDestroy
|
|
FUN_800ad250(*(undefined4 *)(iVar5 + 0x6c),iVar5,iVar8);
|
|
}
|
|
|
|
// low-LOD collision (2 triangles)
|
|
DAT_1f80012a = 0;
|
|
|
|
// COLL_SearchTree_FindQuadblock_Touching
|
|
FUN_8001eb0c(&local_30,&local_28,&DAT_1f800108,0);
|
|
}
|
|
|
|
// RB_MakeInstanceReflective
|
|
FUN_800abab0(&DAT_1f800108,iVar5);
|
|
|
|
// if no collision,
|
|
if (DAT_1f800146 == 0)
|
|
{
|
|
*(undefined2 *)(iVar8 + 0x12) = *(undefined2 *)(iVar5 + 0x48);
|
|
|
|
// rotate on Y axis
|
|
local_30 = 0;
|
|
local_2e = 0x1000;
|
|
local_2c = 0;
|
|
|
|
// driver rotation
|
|
sVar2 = *(short *)(param_1 + 0x39a);
|
|
|
|
puVar11 = &local_30;
|
|
}
|
|
|
|
else
|
|
{
|
|
*(undefined2 *)(iVar8 + 0x12) = DAT_1f800124._2_2_;
|
|
|
|
// driver rotation
|
|
sVar2 = *(short *)(param_1 + 0x39a);
|
|
|
|
// rotate on slanted axis from quadblock
|
|
puVar11 = &DAT_1f800178;
|
|
}
|
|
|
|
// VehPhysForce_RotAxisAngle
|
|
// rotation matrix of beaker, given driver rotation and quadblock
|
|
FUN_8005f89c(iVar5 + 0x30,puVar11,(int)sVar2);
|
|
|
|
// RB_Follower_Init
|
|
FUN_800b6f00(param_1,*(undefined4 *)(iVar5 + 0x6c));
|
|
|
|
*(uint *)(param_1 + 0x2c8) = *(uint *)(param_1 + 0x2c8) | 0x80000000;
|
|
}
|
|
break;
|
|
|
|
// if weapon ID is Shield Bubble
|
|
case 6:
|
|
|
|
// 0x200 flag = MediumStackPool
|
|
// 0xd = "other" thread bucket
|
|
// 0x5a = shieldDark (darkens edges of 2nd shield instance)
|
|
// 0x18 = sizeof(struct Shield)
|
|
// 800b0454 - RB_ShieldDark_ThTick_Grow
|
|
iVar5 = FUN_800309a4(0x5a,"shielddark",0x200,0xd,&DAT_800b0454,0x18,
|
|
|
|
// driver -> instance -> thread
|
|
*(undefined4 *)(*(int *)(param_1 + 0x1c) + 0x6c));
|
|
|
|
// set scale (x, y, z)
|
|
*(undefined2 *)(iVar5 + 0x1c) = 0x700;
|
|
*(undefined2 *)(iVar5 + 0x1e) = 0x700;
|
|
*(undefined2 *)(iVar5 + 0x20) = 0x700;
|
|
|
|
// set funcThDestroy to remove instance from instance pool
|
|
*(undefined4 *)(*(int *)(iVar5 + 0x6c) + 0x24) = 0x80041dfc;
|
|
|
|
// OtherFX_Play Activate Shield sound
|
|
FUN_80028468(0x57,1);
|
|
|
|
// get object created with thread
|
|
puVar16 = *(undefined4 **)(*(int *)(iVar5 + 0x6c) + 0x30);
|
|
|
|
// if number of wumpa is less than 10
|
|
if (*(char *)(param_1 + 0x30) < '\n')
|
|
{
|
|
// Green (0x5e) shield model pointer (in instance)
|
|
uVar7 = *(undefined4 *)(PTR_DAT_8008d2ac + 0x22d8);
|
|
}
|
|
|
|
// if number of wumpa is 10
|
|
else
|
|
{
|
|
// Blue (0x56) shield model pointer (in instance)
|
|
uVar7 = *(undefined4 *)(PTR_DAT_8008d2ac + 0x22b8);
|
|
}
|
|
|
|
// s_shield_8008d63c
|
|
// "shield"
|
|
|
|
// INSTANCE_Birth3D -- ptrModel, name, thread
|
|
uVar7 = FUN_8003086c(uVar7,s_shield_8008d63c);
|
|
|
|
// give instance to object
|
|
puVar16[2] = uVar7;
|
|
|
|
puVar12 = PTR_DAT_8008d2ac;
|
|
|
|
// scale (x, y, z)
|
|
*(undefined2 *)(puVar16[2] + 0x1c) = 0x700;
|
|
*(undefined2 *)(puVar16[2] + 0x1e) = 0x700;
|
|
*(undefined2 *)(puVar16[2] + 0x20) = 0x700;
|
|
|
|
// INSTANCE_Birth3D -- ptrModel, name, thread
|
|
iVar8 = FUN_8003086c(*(undefined4 *)(puVar12 + 0x22d4),"highlight",*(undefined4 *)(iVar5 + 0x6c));
|
|
|
|
// give instance to object
|
|
puVar16[3] = iVar8;
|
|
|
|
// scale (x, y, z)
|
|
*(undefined2 *)(iVar8 + 0x1c) = 0x700;
|
|
*(undefined2 *)(puVar16[3] + 0x1e) = 0x700;
|
|
*(undefined2 *)(puVar16[3] + 0x20) = 0x700;
|
|
|
|
*(undefined2 *)((int)puVar16 + 6) = 0;
|
|
*(undefined2 *)(puVar16 + 4) = 0;
|
|
*(undefined2 *)((int)puVar16 + 0x12) = 0xc00;
|
|
*(undefined2 *)(puVar16 + 5) = 0;
|
|
*(undefined2 *)((int)puVar16 + 0x16) = 0;
|
|
|
|
// if wumpa < 10
|
|
if (*(char *)(param_1 + 0x30) < '\n')
|
|
{
|
|
// 12 seconds,
|
|
// 12 * 30 * 32
|
|
*(undefined2 *)(puVar16 + 1) = 0x2d00;
|
|
}
|
|
|
|
// if weapon is 10
|
|
else
|
|
{
|
|
// use a flag to disable the countdown timer (in 231)
|
|
*(ushort *)((int)puVar16 + 6) = *(ushort *)((int)puVar16 + 6) | 4;
|
|
}
|
|
|
|
*(undefined2 *)(iVar5 + 0x22) = 0x400;
|
|
*puVar16 = 0;
|
|
*(int *)(param_1 + 0x14) = iVar5;
|
|
break;
|
|
|
|
// if weapon ID is mask
|
|
case 7:
|
|
// VehPickupItem_MaskUseWeapon
|
|
FUN_80064c38(param_1,1);
|
|
break;
|
|
|
|
// if weapon ID is clock
|
|
case 8:
|
|
*(char *)(param_1 + 0x558) = *(char *)(param_1 + 0x558) + '\x01';
|
|
|
|
// OtherFX_Play
|
|
FUN_80028468(0x44);
|
|
|
|
// loop iteration counter
|
|
iVar5 = 0;
|
|
|
|
// If this is human and not AI
|
|
if ((*(uint *)(param_1 + 0x2c8) & 0x100000) == 0)
|
|
{
|
|
// Make driver talk
|
|
FUN_8002cbe8(0xe,(int)(short)(&DAT_80086e84)[*(byte *)(param_1 + 0x4a)],0x10);
|
|
iVar5 = 0;
|
|
}
|
|
|
|
// for iVar5 = 0; iVar5 < 8; iVar5++
|
|
do
|
|
{
|
|
// pointer incrementer, for each player structure
|
|
iVar14 = iVar5 * 4;
|
|
|
|
// driver->clockFlash
|
|
*(undefined *)(*(int *)(PTR_DAT_8008d2ac + iVar14 + 0x24ec) + 0x367) = 4;
|
|
|
|
// get pointer to each player structure
|
|
iVar8 = *(int *)(PTR_DAT_8008d2ac + iVar14 + 0x24ec);
|
|
|
|
// if pointer is not nullptr
|
|
if (iVar8 != 0)
|
|
{
|
|
// do not put weapon effect on the player that used it
|
|
if (iVar8 == param_1) {
|
|
*(undefined *)(param_1 + 0x45) = 0x1e;
|
|
}
|
|
else
|
|
{
|
|
// RB_Hazard_HurtDriver (spinout)
|
|
iVar8 = FUN_800ac1b0(iVar8,1,0,0);
|
|
|
|
if (iVar8 != 0)
|
|
{
|
|
// if wumpa < 10
|
|
if (*(char *)(param_1 + 0x30) < '\n')
|
|
{
|
|
// little time
|
|
*(undefined2 *)(*(int *)(PTR_DAT_8008d2ac + iVar14 + 0x24ec) + 0xc) = 0x1e00;
|
|
}
|
|
|
|
// if wumpa is 10
|
|
else
|
|
{
|
|
// long time
|
|
*(undefined2 *)(*(int *)(PTR_DAT_8008d2ac + iVar14 + 0x24ec) + 0xc) = 0x2d00;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// increment loop counter
|
|
iVar5 = iVar5 + 1;
|
|
} while (iVar5 < 8);
|
|
break;
|
|
|
|
// if weapon ID is warp ball
|
|
case 9:
|
|
|
|
// GAMEPAD_ShockFreq and GAMEPAD_ShockForce1
|
|
FUN_80026440(param_1,8,0);
|
|
FUN_800264c0(param_1,8,0x7f);
|
|
|
|
// 0x200 flag = MediumStackPool
|
|
// 6 = "tracking" thread bucket
|
|
iVar5 = FUN_800309a4(0x36,"warpball",0x200,6,&DAT_800aef9c,0x58,0);
|
|
|
|
// copy position from player to warpball
|
|
*(int *)(iVar5 + 0x44) = *(int *)(param_1 + 0x2d4) >> 8;
|
|
*(int *)(iVar5 + 0x48) = *(int *)(param_1 + 0x2d8) >> 8;
|
|
iVar8 = *(int *)(param_1 + 0x2dc);
|
|
|
|
// set scale
|
|
*(undefined4 *)(iVar5 + 0x30) = 0x1000;
|
|
*(undefined4 *)(iVar5 + 0x38) = 0x1000;
|
|
*(undefined2 *)(iVar5 + 0x40) = 0x1000;
|
|
|
|
// one more position variable
|
|
*(int *)(iVar5 + 0x4c) = iVar8 >> 8;
|
|
|
|
// rotation variables
|
|
*(undefined4 *)(iVar5 + 0x34) = 0;
|
|
*(undefined4 *)(iVar5 + 0x3c) = 0;
|
|
|
|
// set funcThDestroy to remove instance from instance pool
|
|
*(undefined4 *)(*(int *)(iVar5 + 0x6c) + 0x24) = 0x80041dfc;
|
|
|
|
// PlaySound3D
|
|
FUN_8002f0dc(0x4d,iVar5);
|
|
|
|
// If this is human and not AI
|
|
if ((*(uint *)(param_1 + 0x2c8) & 0x100000) == 0)
|
|
{
|
|
// Make driver talk
|
|
FUN_8002cbe8(0xc,(int)(short)(&DAT_80086e84)[*(byte *)(param_1 + 0x4a)],0x10);
|
|
}
|
|
|
|
// warpball instance -> thread -> object
|
|
piVar15 = *(int **)(*(int *)(iVar5 + 0x6c) + 0x30);
|
|
|
|
piVar15[1] = param_1;
|
|
|
|
// set animation to zero
|
|
*(undefined2 *)((int)piVar15 + 0x52) = 0;
|
|
|
|
piVar15[0x10] = 0;
|
|
|
|
// by default, chase nobody
|
|
iVar8 = 0;
|
|
|
|
// If player is not in first place
|
|
if ((int)*(short *)(param_1 + 0x482) != 0)
|
|
{
|
|
// start chasing the player in front of you
|
|
iVar8 = *(int *)(PTR_DAT_8008d2ac + ((int)*(short *)(param_1 + 0x482) + -1) * 4 + 0x250c);
|
|
}
|
|
|
|
// store target driver in warpball object
|
|
*piVar15 = iVar8;
|
|
|
|
// RB_Warpball_SeekDriver
|
|
FUN_800aece0(piVar15,(uint)*(byte *)(param_1 + 0x495),param_1);
|
|
|
|
iVar8 = *(int *)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0x14c);
|
|
*(byte *)((int)piVar15 + 0x45) = *(byte *)(piVar15 + 0x11);
|
|
|
|
// if wumpa < 10
|
|
*(undefined2 *)((int)piVar15 + 0x16) = 0;
|
|
|
|
// respawnPointIndex
|
|
piVar15[0xb] = 0;
|
|
|
|
// ptrNodeCurr = lev->respawnPoint[pathIndexStart]
|
|
piVar15[0xf] = iVar8 + (uint)*(byte *)(piVar15 + 0x11) * 0xc;
|
|
|
|
// if 9 < wumpa
|
|
// if wumpa is 10
|
|
if ('\t' < *(char *)(param_1 + 0x30))
|
|
{
|
|
// use flag to remember that 10 wumpa were used
|
|
*(ushort *)((int)piVar15 + 0x16) = *(ushort *)((int)piVar15 + 0x16) | 1;
|
|
}
|
|
|
|
*(ushort *)((int)piVar15 + 0x16) = *(ushort *)((int)piVar15 + 0x16) | 8;
|
|
|
|
// one flag for each driver
|
|
piVar15[0xd] = 1 << ((uint)*(byte *)(param_1 + 0x4a) & 0x1f);
|
|
|
|
// if driver is in first
|
|
if (*(short *)(param_1 + 0x482) == 0)
|
|
{
|
|
// warp ball will not chase any driver
|
|
*piVar15 = 0;
|
|
}
|
|
|
|
// if driver is not in first
|
|
else
|
|
{
|
|
// Find a target driver to chase
|
|
|
|
// piVar15 is WarpBall object,
|
|
// iVar5 is WarpBall instance
|
|
|
|
// RB_Warpball_GetDriverTarget
|
|
iVar5 = FUN_800ae7dc(piVar15,iVar5);
|
|
|
|
// store pointer to driver that will be chased
|
|
*piVar15 = iVar5;
|
|
}
|
|
|
|
// if driver is in first (again?)
|
|
if (*(short *)(param_1 + 0x482) == 0)
|
|
{
|
|
// warp ball will not chase any driver
|
|
*piVar15 = 0;
|
|
}
|
|
|
|
// if driver is being chased
|
|
if (*piVar15 != 0)
|
|
{
|
|
// RB_Warpball_SetTargetDriver
|
|
FUN_800aeaac(piVar15);
|
|
}
|
|
|
|
if ((*(ushort *)((int)piVar15 + 0x16) & 4) == 0)
|
|
{
|
|
// RB_Warpball_Start
|
|
FUN_800ae778(piVar15);
|
|
}
|
|
else {
|
|
*(ushort *)((int)piVar15 + 0x16) = *(ushort *)((int)piVar15 + 0x16) & 0xfff7;
|
|
}
|
|
|
|
// RB_Warpball_NewPathNode
|
|
iVar5 = FUN_800ae668(piVar15[0xf],*piVar15);
|
|
piVar15[0x10] = iVar5;
|
|
|
|
// clear audio pointer
|
|
piVar15[9] = 0;
|
|
|
|
// get rotation of driver inst
|
|
sVar2 = *(short *)(*(int *)(param_1 + 0x1c) + 0x34);
|
|
|
|
// velY
|
|
*(undefined2 *)((int)piVar15 + 0x12) = 0;
|
|
|
|
// velX
|
|
*(short *)(piVar15 + 4) = (short)((uint)((int)sVar2 * 7) >> 8);
|
|
|
|
// get rotation of driver inst
|
|
sVar2 = *(short *)(*(int *)(param_1 + 0x1c) + 0x40);
|
|
|
|
// frameCount_DontHurtParent (useless)
|
|
*(undefined2 *)(piVar15 + 8) = 10;
|
|
|
|
// velZ
|
|
*(short *)(piVar15 + 5) = (short)((uint)((int)sVar2 * 7) >> 8);
|
|
|
|
// gGT
|
|
puVar12 = PTR_DAT_8008d2ac;
|
|
|
|
// rotation
|
|
*(undefined2 *)((int)piVar15 + 0x1a) = *(undefined2 *)(param_1 + 0x39a);
|
|
|
|
// instance who shot the warpball
|
|
piVar15[2] = *(int *)(param_1 + 0x1c);
|
|
|
|
// Create instance in particle pool
|
|
iVar5 = FUN_80040308(0,*(undefined4 *)(puVar12 + 0x2114),&DAT_80089c04);
|
|
|
|
// offset 0xC
|
|
piVar15[3] = iVar5;
|
|
|
|
if (iVar5 != 0) {
|
|
*(undefined *)(iVar5 + 0x18) = 0xfa;
|
|
}
|
|
break;
|
|
|
|
// if weapon ID is Invisibility
|
|
case 0xc:
|
|
|
|
// if not already invisible
|
|
if (*(int *)(param_1 + 0x28) == 0)
|
|
{
|
|
// backup instance flags before invisible
|
|
*(undefined4 *)(param_1 + 0x2c) = *(undefined4 *)(*(int *)(param_1 + 0x1c) + 0x28);
|
|
|
|
// instance flags
|
|
*(uint *)(*(int *)(param_1 + 0x1c) + 0x28) =
|
|
*(uint *)(*(int *)(param_1 + 0x1c) + 0x28) & 0xfff8ffff;
|
|
|
|
// instance flags
|
|
*(uint *)(*(int *)(param_1 + 0x1c) + 0x28) =
|
|
*(uint *)(*(int *)(param_1 + 0x1c) + 0x28) | 0x60000;
|
|
|
|
// OtherFX_Play
|
|
FUN_80028468(0x61,1);
|
|
}
|
|
|
|
// if wumpa is 10
|
|
uVar7 = 0x1e00;
|
|
|
|
// if 9 < wumpa
|
|
// if wumpa is 10
|
|
if ('\t' < *(char *)(param_1 + 0x30)) {
|
|
uVar7 = 0x2d00;
|
|
}
|
|
|
|
// set invisible timer
|
|
*(undefined4 *)(param_1 + 0x28) = uVar7;
|
|
|
|
break;
|
|
|
|
// if weapn ID is Super Engine
|
|
case 0xd:
|
|
|
|
// if wumpa is less than 10
|
|
if (*(char *)(param_1 + 0x30) < '\n')
|
|
{
|
|
// Set super engine powerup timer
|
|
*(undefined2 *)(param_1 + 0x38) = 0x1e00;
|
|
}
|
|
|
|
// if wumpa is 10
|
|
else
|
|
{
|
|
// Set super engine powerup timer
|
|
*(undefined2 *)(param_1 + 0x38) = 0x2d00;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// VehPickupItem_ShootOnCirclePress
|
|
void FUN_800666e4(int param_1)
|
|
|
|
{
|
|
uint uVar1;
|
|
|
|
if (*(byte *)(param_1 + 0x4ff) != 0)
|
|
{
|
|
// VehPickState_NewState
|
|
FUN_80064568(param_1,(uint)*(byte *)(param_1 + 0x4ff),*(undefined4 *)(param_1 + 0x500),
|
|
(uint)*(byte *)(param_1 + 0x504));
|
|
}
|
|
|
|
// If you want to fire a weapon
|
|
if ((*(uint *)(param_1 + 0x2c8) & 0x8000) != 0)
|
|
{
|
|
// Remove the request to fire a weapon, since we will fire it now
|
|
*(uint *)(param_1 + 0x2c8) = *(uint *)(param_1 + 0x2c8) & 0xffff7fff;
|
|
|
|
// Set weapon to one bomb
|
|
uVar1 = 1;
|
|
|
|
if (
|
|
// If this weapon is not 3 bombs
|
|
(*(char *)(param_1 + 0x36) != '\n') &&
|
|
|
|
(
|
|
// Set weapon to missile
|
|
uVar1 = 2,
|
|
|
|
// if this weapon is not 3 missiles
|
|
*(char *)(param_1 + 0x36) != '\v'
|
|
)
|
|
)
|
|
{
|
|
// Set to the original weapon the player has
|
|
uVar1 = (uint)*(byte *)(param_1 + 0x36);
|
|
}
|
|
|
|
// If weapon is bomb, change to missile,
|
|
// this is because bomb and missile share code
|
|
if (uVar1 == 1) {
|
|
uVar1 = 2;
|
|
}
|
|
|
|
// VehPickupItem_ShootNow (player)
|
|
FUN_8006540c(param_1,uVar1,0);
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
// WARNING: Removing unreachable block (ram,0x80066894)
|
|
// WARNING: Globals starting with '_' overlap smaller symbols at the same address
|
|
|
|
// VehStuckProc_MaskGrab_FindDestPos (destination position)
|
|
void FUN_8006677c(int param_1,short *param_2)
|
|
|
|
{
|
|
byte bVar1;
|
|
short sVar2;
|
|
undefined *puVar3;
|
|
long lVar4;
|
|
int iVar5;
|
|
int iVar6;
|
|
int iVar7;
|
|
short *psVar8;
|
|
short *psVar9;
|
|
|
|
puVar3 = PTR_DAT_8008d2ac;
|
|
|
|
if (
|
|
(
|
|
// if no respawn positions are found in the LEV file
|
|
(*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0x148) < 1) ||
|
|
(*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0x14c) == 0)
|
|
) ||
|
|
|
|
// quadblock checkpointIndex (0x3e)
|
|
(*(char *)(param_2 + 0x1f) == -1))
|
|
{
|
|
// respawn driver on the last "valid" quadblock they touched
|
|
|
|
// posX =
|
|
*(int *)(param_1 + 0x2d4) =
|
|
|
|
// lev->mesh_info->ptrVertexArray[(Quadblock*)param_2->index[0]].pos[0]
|
|
((int)*(short *)((int)*param_2 * 0x10 +
|
|
*(int *)(**(int **)(PTR_DAT_8008d2ac + 0x160) + 0x10)) +
|
|
|
|
// lev->mesh_info->ptrVertexArray[(Quadblock*)param_2->index[3]].pos[0]
|
|
(int)*(short *)((int)param_2[3] * 0x10 +
|
|
*(int *)(**(int **)(PTR_DAT_8008d2ac + 0x160) + 0x10)))
|
|
|
|
// midpoint between
|
|
* 0x80;
|
|
|
|
// lev->mesh_info->ptrVertexArray
|
|
iVar6 = *(int *)(**(int **)(puVar3 + 0x160) + 0x10);
|
|
|
|
// posY =
|
|
*(int *)(param_1 + 0x2d8) =
|
|
|
|
// ptrVertexArray[(Quadblock*)param_2->index[0]].pos[1]
|
|
((int)*(short *)((int)*param_2 * 0x10 + iVar6 + 2) +
|
|
|
|
// ptrVertexArray[(Quadblock*)param_2->index[3]].pos[1]
|
|
(int)*(short *)((int)param_2[3] * 0x10 + iVar6 + 2) + 0x80)
|
|
|
|
// midpoint between
|
|
* 0x80;
|
|
|
|
iVar6 = *(int *)(**(int **)(puVar3 + 0x160) + 0x10);
|
|
|
|
// posZ
|
|
*(int *)(param_1 + 0x2dc) =
|
|
|
|
|
|
// ptrVertexArray[(Quadblock*)param_2->index[0]].pos[2]
|
|
((int)*(short *)((int)*param_2 * 0x10 + iVar6 + 4) +
|
|
|
|
// ptrVertexArray[(Quadblock*)param_2->index[3]].pos[2]
|
|
(int)*(short *)((int)param_2[3] * 0x10 + iVar6 + 4))
|
|
|
|
// midpiont between
|
|
* 0x80;
|
|
}
|
|
|
|
// if checkpointIndex is not -1,
|
|
// and respawn points exist on LEV
|
|
else
|
|
{
|
|
// search BSP for valid quadblock near the point, and spawn there
|
|
|
|
// thread offset 0x42?
|
|
|
|
// a bunch of driver -> instance -> thread -> xxx
|
|
DAT_1f80010e = *(undefined2 *)(*(int *)(*(int *)(param_1 + 0x1c) + 0x6c) + 0x42);
|
|
_DAT_1f800110 = *(undefined4 *)(*(int *)(*(int *)(param_1 + 0x1c) + 0x6c) + 0x38);
|
|
DAT_1f80011c._2_2_ = *(undefined2 *)(*(int *)(*(int *)(param_1 + 0x1c) + 0x6c) + 0x42);
|
|
DAT_1f800120 = *(undefined4 *)(*(int *)(*(int *)(param_1 + 0x1c) + 0x6c) + 0x38);
|
|
|
|
DAT_1f800134 = **(int **)(PTR_DAT_8008d2ac + 0x160);
|
|
DAT_1f800130 = 0x4010;
|
|
|
|
// ground quadblock flags
|
|
DAT_1f80012c = 0x1000;
|
|
|
|
// quadblock checkpointIndex (0x3e)
|
|
bVar1 = *(byte *)(param_2 + 0x1f);
|
|
|
|
// lev -> respawn_points
|
|
iVar6 = *(int *)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0x14c);
|
|
|
|
*(undefined4 *)(param_1 + 0x490) = 0;
|
|
|
|
// respawn data
|
|
psVar8 = (short *)(iVar6 + (uint)bVar1 * 0xc);
|
|
|
|
do {
|
|
do {
|
|
|
|
// next respawn data after the one being spawned on
|
|
psVar9 = (short *)(*(int *)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0x14c) +
|
|
(uint)*(byte *)(psVar8 + 4) * 0xc);
|
|
|
|
// posX
|
|
*(int *)(param_1 + 0x2d4) = (int)*psVar8 << 8;
|
|
|
|
// posY (+ offset for mask in air)
|
|
*(int *)(param_1 + 0x2d8) = ((int)psVar8[1] + 0x80) * 0x100;
|
|
|
|
// posZ
|
|
sVar2 = psVar8[2];
|
|
|
|
// rotX = 0 (not on slant)
|
|
*(undefined2 *)(param_1 + 0x2ec) = 0;
|
|
|
|
// posZ
|
|
*(int *)(param_1 + 0x2dc) = (int)sVar2 << 8;
|
|
|
|
// get rotY by comparing positions of cur respawn and next respawn
|
|
lVar4 = ratan2((int)*psVar9 - (int)*psVar8,(int)psVar9[2] - (int)psVar8[2]);
|
|
*(undefined2 *)(param_1 + 0x2ee) = (short)lVar4;
|
|
|
|
// rotZ = 0 (not on slant)
|
|
*(undefined2 *)(param_1 + 0x2f0) = 0;
|
|
|
|
// build hitbox for driver
|
|
DAT_1f800118._0_2_ = (short)((uint)*(undefined4 *)(param_1 + 0x2d4) >> 8);
|
|
DAT_1f800118._2_2_ = (ushort)((uint)*(undefined4 *)(param_1 + 0x2d8) >> 8);
|
|
DAT_1f80011c._0_2_ = (ushort)((uint)*(undefined4 *)(param_1 + 0x2dc) >> 8);
|
|
DAT_1f800108 = (short)((uint)*(undefined4 *)(param_1 + 0x2d4) >> 8);
|
|
DAT_1f80010a = (short)((uint)*(undefined4 *)(param_1 + 0x2d8) >> 8) - 0x100;
|
|
|
|
// low-LOD collision (2 triangles)
|
|
DAT_1f80012a = 0;
|
|
|
|
DAT_1f80010c = (ushort)((uint)*(undefined4 *)(param_1 + 0x2dc) >> 8);
|
|
|
|
// if numPlyrCurrGame is less than 3
|
|
if ((byte)PTR_DAT_8008d2ac[0x1ca8] < 3)
|
|
{
|
|
// high-LOD collision (8 triangles)
|
|
DAT_1f80012a = 2;
|
|
}
|
|
|
|
DAT_1f800146 = 0;
|
|
DAT_1f800144 = 0;
|
|
DAT_1f80018c = 0x1000;
|
|
DAT_1f8002ac = 0;
|
|
DAT_1f800138 = (short)DAT_1f800118;
|
|
if (DAT_1f800108 < (short)DAT_1f800118) {
|
|
DAT_1f800138 = DAT_1f800108;
|
|
}
|
|
DAT_1f80013a = DAT_1f800118._2_2_;
|
|
if ((int)((uint)DAT_1f80010a << 0x10) < (int)((uint)DAT_1f800118._2_2_ << 0x10)) {
|
|
DAT_1f80013a = DAT_1f80010a;
|
|
}
|
|
DAT_1f80013c = (ushort)DAT_1f80011c;
|
|
if ((int)((uint)DAT_1f80010c << 0x10) < (int)((uint)(ushort)DAT_1f80011c << 0x10)) {
|
|
DAT_1f80013c = DAT_1f80010c;
|
|
}
|
|
DAT_1f80013e = (short)DAT_1f800118;
|
|
if ((short)DAT_1f800118 < DAT_1f800108) {
|
|
DAT_1f80013e = DAT_1f800108;
|
|
}
|
|
DAT_1f800140 = DAT_1f800118._2_2_;
|
|
if ((int)((uint)DAT_1f800118._2_2_ << 0x10) < (int)((uint)DAT_1f80010a << 0x10)) {
|
|
DAT_1f800140 = DAT_1f80010a;
|
|
}
|
|
DAT_1f800142 = (ushort)DAT_1f80011c;
|
|
if ((int)((uint)(ushort)DAT_1f80011c << 0x10) < (int)((uint)DAT_1f80010c << 0x10)) {
|
|
DAT_1f800142 = DAT_1f80010c;
|
|
}
|
|
DAT_1f800124._0_2_ = DAT_1f800108;
|
|
DAT_1f800124._2_2_ = DAT_1f80010a;
|
|
DAT_1f800128 = DAT_1f80010c;
|
|
|
|
// COLL_SearchTree_FindX, callback for touching quadblocks,
|
|
// COLL_PerBspLeaf_CheckQuadblocks_Touching
|
|
FUN_8001ebec(*(undefined4 *)(DAT_1f800134 + 0x18),&DAT_1f800138,FUN_8001f5f0,&DAT_1f800108);
|
|
|
|
// cur respawn = next respawn
|
|
psVar8 = psVar9;
|
|
|
|
// loop again if no quadblock is found under the driver
|
|
} while ((DAT_1f800146 == 0) || ((DAT_1f8002ac & 0x4000) != 0));
|
|
|
|
// pointer to first Player thread
|
|
iVar6 = *(int *)(PTR_DAT_8008d2ac + 0x1b2c);
|
|
|
|
// if player does not exist, quit
|
|
if (iVar6 == 0) break;
|
|
|
|
// loop through all players
|
|
do
|
|
{
|
|
// player object
|
|
iVar7 = *(int *)(iVar6 + 0x30);
|
|
|
|
// dont check for collision against yourself
|
|
if (iVar7 != param_1)
|
|
{
|
|
// compare X
|
|
iVar5 = *(int *)(param_1 + 0x2d4) - *(int *)(iVar7 + 0x2d4);
|
|
|
|
// absolute value
|
|
if (iVar5 < 0) {
|
|
iVar5 = -iVar5;
|
|
}
|
|
|
|
// if distance too close, go to next respawn point
|
|
if (iVar5 < 0x2000) break;
|
|
|
|
// compare Z
|
|
iVar7 = *(int *)(param_1 + 0x2dc) - *(int *)(iVar7 + 0x2dc);
|
|
|
|
// absolute value
|
|
if (iVar7 < 0) {
|
|
iVar7 = -iVar7;
|
|
}
|
|
|
|
// if distance too close, go to next respawn point
|
|
if (iVar7 < 0x2000) break;
|
|
}
|
|
|
|
// next player
|
|
iVar6 = *(int *)(iVar6 + 0x10);
|
|
|
|
// if == 0, player does not spawn on top of another,
|
|
// else, check next driver
|
|
} while (iVar6 != 0);
|
|
|
|
// if == 0, player does not spawn on top of another,
|
|
// else, spawn player on the next respawn point
|
|
} while (iVar6 != 0);
|
|
}
|
|
|
|
// CameraDC flag
|
|
*(uint *)(PTR_DAT_8008d2ac + (uint)*(byte *)(param_1 + 0x4a) * 0xdc + 0x1508) =
|
|
*(uint *)(PTR_DAT_8008d2ac + (uint)*(byte *)(param_1 + 0x4a) * 0xdc + 0x1508) | 1;
|
|
return;
|
|
}
|
|
|
|
|
|
// VehStuckProc_MaskGrab_Particles
|
|
void FUN_80066cb0(int param_1)
|
|
|
|
{
|
|
int iVar1;
|
|
int iVar2;
|
|
|
|
iVar2 = 10;
|
|
do
|
|
{
|
|
// Create instance in particle pool
|
|
iVar1 = FUN_80040308(0,*(undefined4 *)(PTR_DAT_8008d2ac + 0x2114),&DAT_80089d90);
|
|
|
|
iVar2 = iVar2 + -1;
|
|
if (iVar1 == 0) {
|
|
return;
|
|
}
|
|
|
|
// position variables
|
|
*(int *)(iVar1 + 0x24) = *(int *)(iVar1 + 0x24) + *(int *)(param_1 + 0x2d4);
|
|
*(int *)(iVar1 + 0x2c) = *(int *)(iVar1 + 0x2c) + *(int *)(param_1 + 0x2d8);
|
|
*(int *)(iVar1 + 0x34) = *(int *)(iVar1 + 0x34) + *(int *)(param_1 + 0x2dc);
|
|
|
|
} while (iVar2 != 0);
|
|
return;
|
|
}
|
|
|
|
|
|
// VehStuckProc_MaskGrab_Update
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80066d4c(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
int iVar1;
|
|
|
|
// NoInput timer = NoInput timer - elapsed milliseconds per frame, ~32
|
|
iVar1 = (uint)*(ushort *)(param_2 + 0x400) - (uint)*(ushort *)(PTR_DAT_8008d2ac + 0x1d04);
|
|
*(undefined2 *)(param_2 + 0x400) = (short)iVar1;
|
|
|
|
// if negative
|
|
if (iVar1 * 0x10000 < 0)
|
|
{
|
|
// set to zero
|
|
*(undefined2 *)(param_2 + 0x400) = 0;
|
|
}
|
|
|
|
// when input is allowed,
|
|
// which is when driver is spawned back over track
|
|
if (*(short *)(param_2 + 0x400) == 0)
|
|
{
|
|
// maskObj
|
|
iVar1 = *(int *)(param_2 + 0x580);
|
|
|
|
if (iVar1 != 0)
|
|
{
|
|
// mask rotY
|
|
*(ushort *)(iVar1 + 4) = *(ushort *)(iVar1 + 4) & 0xfffe;
|
|
|
|
// scale = 100%
|
|
*(undefined2 *)(*(int *)(param_2 + 0x580) + 0x12) = 0x1000;
|
|
}
|
|
|
|
// CameraDC flag
|
|
*(uint *)(PTR_DAT_8008d2ac + (uint)*(byte *)(param_2 + 0x4a) * 0xdc + 0x1508) =
|
|
*(uint *)(PTR_DAT_8008d2ac + (uint)*(byte *)(param_2 + 0x4a) * 0xdc + 0x1508) | 8;
|
|
|
|
// VehStuckProc_MaskGrab_FindDestPos
|
|
// driver, and quadblock (last valid)
|
|
FUN_8006677c(param_2,*(undefined4 *)(param_2 + 0x354));
|
|
|
|
// VehBirth_TeleportSelf (back onto track)
|
|
FUN_80057c8c(param_2,0,0x80);
|
|
|
|
// VehStuckProc_RevEngine_Init
|
|
FUN_80067f4c(param_1,param_2);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// VehStuckProc_MaskGrab_PhysLinear
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80066e3c(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
// VehPhysProc_Driving_PhysLinear
|
|
FUN_8006181c(param_1, param_2);
|
|
|
|
// reset base speed
|
|
*(undefined2 *)(param_2 + 0x39e) = 0;
|
|
|
|
//reset Jump buffer Timer
|
|
*(undefined2 *)(param_2 + 0x3f0) = 0;
|
|
|
|
// reset base speed (again?)
|
|
*(undefined2 *)(param_2 + 0x39e) = 0;
|
|
|
|
// reset "basic" speed
|
|
*(undefined2 *)(param_2 + 0x39c) = 0;
|
|
|
|
// reset turning state
|
|
*(undefined *)(param_2 + 0x4b) = 0;
|
|
|
|
*(uint *)(param_2 + 0x2c8) = *(uint *)(param_2 + 0x2c8) & 0xfffdffdb | 8;
|
|
return;
|
|
}
|
|
|
|
// VehStuckProc_MaskGrab_Animate
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80066e8c(int param_1,int param_2)
|
|
{
|
|
char cVar1;
|
|
short sVar2;
|
|
ushort uVar3;
|
|
undefined2 uVar4;
|
|
undefined4 uVar5;
|
|
int iVar6;
|
|
|
|
// get instance from thread
|
|
iVar6 = *(int *)(param_1 + 0x34);
|
|
|
|
// if driver touched ground before mask grab
|
|
if (*(char *)(param_2 + 0x58d) == '\0') {
|
|
|
|
// MatrixArr and MatrixIndex
|
|
*(undefined *)(param_2 + 0x4c) = 0;
|
|
*(undefined *)(param_2 + 0x4d) = 0;
|
|
|
|
// set animation
|
|
*(undefined *)(iVar6 + 0x52) = 0;
|
|
|
|
// Instance_GetNumAnimFrames(instance, anim#0)
|
|
uVar5 = FUN_8005b0f4(iVar6,0);
|
|
|
|
// VehFrameInst_GetStartFrame(midpoint, numFrames)
|
|
uVar4 = FUN_8005b0c4(0,uVar5);
|
|
|
|
*(undefined2 *)(iVar6 + 0x54) = uVar4;
|
|
*(undefined2 *)(param_2 + 0x368) = *(undefined2 *)(param_2 + 0x584);
|
|
*(undefined2 *)(param_2 + 0x36a) = *(undefined2 *)(param_2 + 0x586);
|
|
*(undefined2 *)(param_2 + 0x36c) = *(undefined2 *)(param_2 + 0x588);
|
|
}
|
|
|
|
// if driver did not touch ground (and is falling)
|
|
else
|
|
{
|
|
if (
|
|
// if whistle sound has not played
|
|
(*(char *)(param_2 + 0x58f) == '\0') &&
|
|
|
|
(*(short *)(param_2 + 0x400) < 0x3c0)
|
|
)
|
|
{
|
|
// OtherFX_Play "falling" sound, like a whistle
|
|
FUN_80028468(0x55,1);
|
|
|
|
// whistle sound has played
|
|
*(undefined *)(param_2 + 0x58f) = 1;
|
|
}
|
|
|
|
// MatrixArr = Crashing
|
|
*(undefined *)(param_2 + 0x4c) = 4;
|
|
|
|
if (*(short *)(param_2 + 0x58a) < 3)
|
|
{
|
|
cVar1 = '\a';
|
|
}
|
|
|
|
else {
|
|
cVar1 = *(char *)(param_2 + 0x58a) + '\x05';
|
|
}
|
|
//Crashing frame = cVar1
|
|
*(char *)(param_2 + 0x4d) = cVar1;
|
|
|
|
// change animation
|
|
*(undefined *)(iVar6 + 0x52) = 2;
|
|
|
|
sVar2 = 7;
|
|
if (2 < *(short *)(param_2 + 0x58a)) {
|
|
sVar2 = *(short *)(param_2 + 0x58a) + 5;
|
|
}
|
|
*(short *)(iVar6 + 0x54) = sVar2;
|
|
sVar2 = *(short *)(param_2 + 0x58a) + 1;
|
|
*(short *)(param_2 + 0x58a) = sVar2;
|
|
if (7 < sVar2) {
|
|
*(undefined2 *)(param_2 + 0x58a) = 7;
|
|
}
|
|
if (*(short *)(param_2 + 0x400) < 0x510)
|
|
{
|
|
// MatrixArr Crashing
|
|
*(undefined *)(param_2 + 0x4c) = 4;
|
|
|
|
// MatrixIndex = 12
|
|
*(undefined *)(param_2 + 0x4d) = 0xc;
|
|
|
|
// set animation
|
|
*(undefined *)(iVar6 + 0x52) = 2;
|
|
|
|
// set animation frame
|
|
*(undefined2 *)(iVar6 + 0x54) = 0xc;
|
|
|
|
if (*(short *)(param_2 + 0x400) < 0x3c1) {
|
|
uVar3 = *(short *)(param_2 + 0x40c) - 800;
|
|
*(ushort *)(param_2 + 0x40c) = uVar3;
|
|
if ((int)((uint)uVar3 << 0x10) < 0) {
|
|
*(undefined2 *)(param_2 + 0x40c) = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// if particles are not spawned
|
|
if (*(char *)(param_2 + 0x58c) == '\0')
|
|
{
|
|
// VehStuckProc_MaskGrab_Particles
|
|
FUN_80066cb0(param_2);
|
|
|
|
// now they are spawned
|
|
*(undefined *)(param_2 + 0x58c) = 1;
|
|
}
|
|
sVar2 = *(short *)(param_2 + 0x40c) + 0x2d0;
|
|
*(short *)(param_2 + 0x40c) = sVar2;
|
|
if (8000 < sVar2) {
|
|
*(undefined2 *)(param_2 + 0x40c) = 8000;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
//reset Speed and Speed Approximate
|
|
*(undefined2 *)(param_2 + 0x38c) = 0;
|
|
*(undefined2 *)(param_2 + 0x38e) = 0;
|
|
|
|
//position backups
|
|
*(undefined4 *)(param_2 + 0x2d4) = *(undefined4 *)(param_2 + 0x2e0);
|
|
*(undefined4 *)(param_2 + 0x2d8) = *(undefined4 *)(param_2 + 0x2e4);
|
|
*(undefined4 *)(param_2 + 0x2dc) = *(undefined4 *)(param_2 + 0x2e8);
|
|
}
|
|
}
|
|
|
|
// if maskObj
|
|
if (*(int *)(param_2 + 0x580) != 0)
|
|
{
|
|
// set mask duration
|
|
*(undefined2 *)(*(int *)(param_2 + 0x580) + 6) = 0x1e00;
|
|
|
|
// if more than 0.5s after player fell
|
|
if (*(short *)(param_2 + 0x400) < 0x3c1) {
|
|
|
|
// if not lifting player
|
|
if (*(char *)(param_2 + 0x58e) == '\0')
|
|
{
|
|
// decrease mask posY by elapsed time
|
|
*(short *)(*(int *)(param_2 + 0x580) + 0xe) =
|
|
*(short *)(*(int *)(param_2 + 0x580) + 0xe) - *(short *)(PTR_DAT_8008d2ac + 0x1d04);
|
|
}
|
|
|
|
// if lifting player (if driver isn't falling infinitely)
|
|
else
|
|
{
|
|
// elapsed milliseconds per frame, ~32
|
|
iVar6 = *(int *)(PTR_DAT_8008d2ac + 0x1d04);
|
|
|
|
// speed = 0
|
|
*(undefined2 *)(param_2 + 0x38c) = 0;
|
|
|
|
// increase driver height, both posCurr and posPrev
|
|
iVar6 = *(int *)(param_2 + 0x2d8) + iVar6 * 0x80;
|
|
*(int *)(param_2 + 0x2d8) = iVar6;
|
|
*(int *)(param_2 + 0x2e4) = iVar6;
|
|
}
|
|
|
|
// set mask posZ
|
|
*(undefined2 *)(*(int *)(param_2 + 0x580) + 0x10) =
|
|
(short)((uint)*(undefined4 *)(param_2 + 0x2dc) >> 8);
|
|
|
|
// if mask posY < driver posY
|
|
if ((int)*(short *)(*(int *)(param_2 + 0x580) + 0xe) < *(int *)(param_2 + 0x2d8) >> 8)
|
|
{
|
|
// mask posY = driver posY
|
|
*(undefined2 *)(*(int *)(param_2 + 0x580) + 0xe) =
|
|
(short)((uint)*(int *)(param_2 + 0x2d8) >> 8);
|
|
|
|
// boolLiftingPlayer = 1
|
|
*(undefined *)(param_2 + 0x58e) = 1;
|
|
}
|
|
|
|
// maskPosX = driverPosX
|
|
*(undefined2 *)(*(int *)(param_2 + 0x580) + 0xc) =
|
|
(short)((uint)*(undefined4 *)(param_2 + 0x2d4) >> 8);
|
|
|
|
// if more than halfway through mask pickup
|
|
if ((int)*(short *)(param_2 + 0x400) < 0x2d1)
|
|
{
|
|
// scale = 100%
|
|
*(undefined2 *)(*(int *)(param_2 + 0x580) + 0x12) = 0x1000;
|
|
}
|
|
|
|
// if less than half
|
|
else
|
|
{
|
|
// interpolate scale
|
|
*(undefined2 *)(*(int *)(param_2 + 0x580) + 0x12) =
|
|
(short)(((0x3c0 - (int)*(short *)(param_2 + 0x400)) * 0x1000) / 0xf0);
|
|
}
|
|
}
|
|
|
|
// less than 0.5s after player fell
|
|
else
|
|
{
|
|
// scale = 0%
|
|
*(undefined2 *)(*(int *)(param_2 + 0x580) + 0x12) = 0;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// VehStuckProc_MaskGrab_Init
|
|
// when falling off track
|
|
// param1 = thread, param2 = driver
|
|
void FUN_800671b0(int param_1,int param_2)
|
|
{
|
|
// When this function executes,
|
|
// mask comes down to catch you
|
|
|
|
undefined4 uVar1;
|
|
int iVar2;
|
|
int iVar3;
|
|
int iVar4;
|
|
|
|
// get instance from thread
|
|
iVar4 = *(int *)(param_1 + 0x34);
|
|
|
|
// now being mask grabbed
|
|
*(undefined *)(param_2 + 0x376) = 5;
|
|
|
|
*(undefined *)(param_2 + 0x58c) = 0;
|
|
*(undefined2 *)(param_2 + 0x58a) = 0;
|
|
*(undefined *)(param_2 + 0x58e) = 0;
|
|
|
|
// reset whistle bool
|
|
*(undefined *)(param_2 + 0x58f) = 0;
|
|
|
|
// reset stillFalling bool
|
|
*(undefined *)(param_2 + 0x58d) = 0;
|
|
|
|
// VehPickupItem_MaskUseWeapon
|
|
uVar1 = FUN_80064c38(param_2,1);
|
|
|
|
// Mask Object
|
|
*(undefined4 *)(param_2 + 0x580) = uVar1;
|
|
|
|
*(undefined2 *)(param_2 + 0x3dc) = 0;
|
|
*(undefined2 *)(param_2 + 0x3e2) = 0;
|
|
*(undefined2 *)(param_2 + 0x3de) = 0;
|
|
*(undefined *)(param_2 + 0x4c) = 0;
|
|
*(undefined *)(param_2 + 0x4d) = 0;
|
|
|
|
// 1.44s until spawned back over track
|
|
*(undefined2 *)(param_2 + 0x400) = 0x5a0;
|
|
|
|
*(uint *)(param_2 + 0x2c8) = *(uint *)(param_2 + 0x2c8) & 0xfff7ffbf;
|
|
|
|
// Check if 231 dll is loaded
|
|
iVar2 = FUN_800348e8();
|
|
|
|
if (
|
|
// If it is loaded
|
|
(iVar2 != 0) &&
|
|
|
|
// If you're not in Adventure Arena
|
|
((*(uint *)PTR_DAT_8008d2ac & 0x100000) == 0)
|
|
)
|
|
{
|
|
// RB_Player_ModifyWumpa, -2
|
|
FUN_800abefc(param_2,0xfffffffe);
|
|
}
|
|
// if stored quadblock height + 0x8000 < posCurr.y
|
|
if (*(int *)(param_2 + 0x2d0) + 0x8000 < *(int *)(param_2 + 0x2d8))
|
|
{
|
|
// mask grab count (for end of race comments)
|
|
*(char *)(param_2 + 0x56a) = *(char *)(param_2 + 0x56a) + '\x01';
|
|
|
|
// if driver touched surface before mask grab
|
|
if (
|
|
// if height is low
|
|
// like splashing water on coco park happens on low height,
|
|
// not high height when you're on the grass
|
|
(*(int *)(param_2 + 0x2d8) < -0x8000) &&
|
|
(
|
|
// 10 particles
|
|
iVar2 = 10,
|
|
|
|
// if mask should grab you when underwater
|
|
(*(uint *)(*(int *)(PTR_DAT_8008d2ac + 0x160) + 0xdc) & 2) != 0
|
|
)
|
|
)
|
|
{
|
|
// AngleAxis normalVec
|
|
*(undefined2 *)(param_2 + 0x584) = *(undefined2 *)(param_2 + 0x368);
|
|
*(undefined2 *)(param_2 + 0x586) = *(undefined2 *)(param_2 + 0x36a);
|
|
*(undefined2 *)(param_2 + 0x588) = *(undefined2 *)(param_2 + 0x36c);
|
|
|
|
// spawn particles
|
|
do
|
|
{
|
|
// 0x2138 = "falling",
|
|
// like splashing in water on coco park
|
|
|
|
// Create instance in particle pool
|
|
iVar3 = FUN_80040308(0,*(undefined4 *)(PTR_DAT_8008d2ac + 0x2138),&DAT_80089a94);
|
|
|
|
// if particle exists
|
|
if (iVar3 != 0) {
|
|
*(undefined *)(iVar3 + 0x18) = *(undefined *)(*(int *)(param_2 + 0x1c) + 0x50);
|
|
|
|
// driver -> instSelf
|
|
*(undefined4 *)(iVar3 + 0x20) = *(undefined4 *)(param_2 + 0x1c);
|
|
|
|
// driverID
|
|
*(undefined *)(iVar3 + 0x19) = *(undefined *)(param_2 + 0x4a);
|
|
}
|
|
|
|
// loop counter
|
|
iVar2 = iVar2 + -1;
|
|
|
|
} while (iVar2 != 0);
|
|
}
|
|
|
|
// if driver did not touch surface (and is still falling)
|
|
else
|
|
{
|
|
// save result in a bool
|
|
*(undefined *)(param_2 + 0x58d) = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// AngleAxis normalVec
|
|
*(undefined2 *)(param_2 + 0x584) = *(undefined2 *)(param_2 + 0x368);
|
|
*(undefined2 *)(param_2 + 0x586) = *(undefined2 *)(param_2 + 0x36a);
|
|
*(undefined2 *)(param_2 + 0x588) = *(undefined2 *)(param_2 + 0x36c);
|
|
}
|
|
|
|
// edits position
|
|
*(int *)(param_2 + 0x2d4) = *(int *)(iVar4 + 0x44) << 8;
|
|
iVar2 = *(int *)(param_2 + 0x580);
|
|
*(int *)(param_2 + 0x2d8) = *(int *)(iVar4 + 0x48) << 8;
|
|
*(int *)(param_2 + 0x2dc) = *(int *)(iVar4 + 0x4c) << 8;
|
|
|
|
//set previous frame velocity to the same as current frame velocity
|
|
*(undefined4 *)(param_2 + 0x2e4) = *(undefined4 *)(param_2 + 0x2d8);
|
|
*(undefined4 *)(param_2 + 0x2e0) = *(undefined4 *)(param_2 + 0x2d4);
|
|
*(undefined4 *)(param_2 + 0x2e8) = *(undefined4 *)(param_2 + 0x2dc);
|
|
|
|
// if maskObj
|
|
if (iVar2 != 0)
|
|
{
|
|
*(ushort *)(iVar2 + 4) = *(ushort *)(iVar2 + 4) | 1;
|
|
|
|
// maskX = driverX
|
|
*(undefined2 *)(*(int *)(param_2 + 0x580) + 0xc) =
|
|
(short)((uint)*(undefined4 *)(param_2 + 0x2d4) >> 8);
|
|
|
|
// maskY = driverY
|
|
*(short *)(*(int *)(param_2 + 0x580) + 0xe) =
|
|
(short)((uint)*(undefined4 *)(param_2 + 0x2d8) >> 8) + 0x140;
|
|
|
|
// maskZ = driverZ
|
|
*(undefined2 *)(*(int *)(param_2 + 0x580) + 0x10) =
|
|
(short)((uint)*(undefined4 *)(param_2 + 0x2dc) >> 8);
|
|
}
|
|
|
|
// VehStuckProc_MaskGrab_Update
|
|
*(undefined4 *)(param_2 + 0x58) = 0x80066d4c;
|
|
|
|
// VehStuckProc_MaskGrab_PhysLinear
|
|
*(undefined4 *)(param_2 + 0x5c) = 0x80066e3c;
|
|
|
|
*(undefined4 *)(param_2 + 0x60) = 0x80062a2c; // OnAudio
|
|
*(undefined4 *)(param_2 + 100) = 0x8005fc8c; // OnPhysAngular
|
|
*(undefined4 *)(param_2 + 0x68) = 0x8005ea60; // VehPhysForce_OnApplyForces
|
|
*(undefined4 *)(param_2 + 0x6c) = 0x80020410; // COLL_StartSearch_NearPlayer
|
|
*(undefined4 *)(param_2 + 0x70) = 0x8005ebac; // VehPhysForce_CollideDrivers
|
|
*(undefined4 *)(param_2 + 0x74) = 0x8001d944; // COLL_StartSearch_Player
|
|
*(undefined4 *)(param_2 + 0x78) = 0x80060630; // JumpAndFriction
|
|
*(undefined4 *)(param_2 + 0x7c) = 0x8005ee34; // VehPhysForce_TranslateMatrix -- move position to instance matrix
|
|
|
|
// VehStuckProc_MaskGrab_Animate
|
|
*(undefined4 *)(param_2 + 0x80) = 0x80066e8c;
|
|
|
|
*(undefined4 *)(param_2 + 0x54) = 0;
|
|
|
|
// VehEmitter_DriverMain
|
|
*(undefined4 *)(param_2 + 0x84) = 0x80059a18;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
// VehStuckProc_PlantEaten_Update
|
|
void FUN_8006749c(int param_1,int param_2)
|
|
|
|
{
|
|
int iVar1;
|
|
int iVar2;
|
|
|
|
// get instance from thread
|
|
iVar2 = *(int *)(param_1 + 0x34);
|
|
|
|
// NoInput timer = NoInput timer - elapsed milliseconds per frame, ~32
|
|
iVar1 = (uint)*(ushort *)(param_2 + 0x400) - (uint)*(ushort *)(PTR_DAT_8008d2ac + 0x1d04);
|
|
*(undefined2 *)(param_2 + 0x400) = (short)iVar1;
|
|
|
|
// if negative
|
|
if (iVar1 * 0x10000 < 0)
|
|
{
|
|
// set to zero
|
|
*(undefined2 *)(param_2 + 0x400) = 0;
|
|
}
|
|
|
|
// when input is now allowed
|
|
if (*(short *)(param_2 + 0x400) == 0)
|
|
{
|
|
// VehStuckProc_MaskGrab_FindDestPos
|
|
// driver, and quadblock previously touched by driver
|
|
FUN_8006677c(param_2,*(undefined4 *)(param_2 + 0x354));
|
|
|
|
// VehBirth_TeleportSelf (back onto track)
|
|
FUN_80057c8c(param_2,0,0x80);
|
|
|
|
// enable collision for this thread
|
|
*(uint *)(param_1 + 0x1c) = *(uint *)(param_1 + 0x1c) & 0xffffefff;
|
|
|
|
// make visible
|
|
*(uint *)(iVar2 + 0x28) = *(uint *)(iVar2 + 0x28) & 0xffffff7f;
|
|
|
|
// VehStuckProc_RevEngine_Init
|
|
// this lets you rev engine while falling
|
|
FUN_80067f4c(param_1,param_2);
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// VehStuckProc_PlantEaten_PhysLinear
|
|
void FUN_80067554(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
undefined *puVar1;
|
|
|
|
// VehPhysProc_Driving_PhysLinear
|
|
FUN_8006181c();
|
|
|
|
// reset speed
|
|
*(undefined2 *)(param_2 + 0x39e) = 0;
|
|
|
|
// reset jump variable
|
|
*(undefined2 *)(param_2 + 0x3f0) = 0;
|
|
|
|
// reset two speed variables
|
|
*(undefined2 *)(param_2 + 0x39e) = 0;
|
|
*(undefined2 *)(param_2 + 0x39c) = 0;
|
|
|
|
*(undefined *)(param_2 + 0x4b) = 0;
|
|
puVar1 = PTR_DAT_8008d2ac;
|
|
|
|
// acceleration prevention,
|
|
// drop bits for jump button, 0x20?, reversing engine
|
|
*(uint *)(param_2 + 0x2c8) = *(uint *)(param_2 + 0x2c8) & 0xfffdffdb | 8;
|
|
|
|
// increment time spent in mask grab
|
|
*(int *)(param_2 + 0x548) = *(int *)(param_2 + 0x548) + *(int *)(puVar1 + 0x1d04);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
// VehStuckProc_PlantEaten_Animate
|
|
// param1 = thread, param2 = driver
|
|
void FUN_800675c0(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
short sVar1;
|
|
undefined *puVar2;
|
|
long x;
|
|
int iVar3;
|
|
int iVar4;
|
|
SVECTOR local_38;
|
|
int local_30;
|
|
int local_28;
|
|
long alStack32 [2];
|
|
|
|
// plantEatingMe
|
|
iVar3 = *(int *)(param_2 + 0x4a8);
|
|
|
|
if (
|
|
(
|
|
// if plant is eating me
|
|
(iVar3 != 0) &&
|
|
|
|
// if not initialized
|
|
(*(char *)(param_2 + 0x580) == '\0')
|
|
) &&
|
|
|
|
// if more than 0.5s since player death
|
|
(*(short *)(param_2 + 0x400) < 0xb40))
|
|
{
|
|
// get instance from thread
|
|
iVar4 = *(int *)(iVar3 + 0x34);
|
|
|
|
// initialized, player eaten
|
|
*(undefined *)(param_2 + 0x580) = 1;
|
|
|
|
local_38.vx = -0xfa;
|
|
if (*(short *)(*(int *)(iVar3 + 0x30) + 4) == 0) {
|
|
local_38.vx = 0xfa;
|
|
}
|
|
local_38.vy = 0;
|
|
local_38.vz = 0x2ee;
|
|
|
|
// driver -> instance -> matrix
|
|
SetRotMatrix((MATRIX *)(iVar4 + 0x30));
|
|
|
|
// driver -> instance -> matrix
|
|
SetTransMatrix((MATRIX *)(iVar4 + 0x30));
|
|
|
|
RotTrans(&local_38,(VECTOR *)&local_30,alStack32);
|
|
puVar2 = PTR_DAT_8008d2ac;
|
|
|
|
// pushBuffer->posX
|
|
*(undefined2 *)(PTR_DAT_8008d2ac + (uint)*(byte *)(param_2 + 0x4a) * 0x110 + 0x168) =
|
|
(undefined2)local_30;
|
|
|
|
// pushBuffer->posY
|
|
*(short *)(puVar2 + (uint)*(byte *)(param_2 + 0x4a) * 0x110 + 0x16a) =
|
|
|
|
// driverY + 0xc0
|
|
*(short *)(iVar4 + 0x48) + 0xc0;
|
|
|
|
// pushBuffer->posZ
|
|
*(undefined2 *)(puVar2 + (uint)*(byte *)(param_2 + 0x4a) * 0x110 + 0x16c) =
|
|
(undefined2)local_28;
|
|
|
|
// cameraX = cameraX - driverX
|
|
local_30 = local_30 - *(int *)(iVar4 + 0x44);
|
|
|
|
// get pushBuffer->posY
|
|
sVar1 = *(short *)(puVar2 + (uint)*(byte *)(param_2 + 0x4a) * 0x110 + 0x16a);
|
|
|
|
// driverY
|
|
iVar3 = *(int *)(iVar4 + 0x48);
|
|
|
|
// cameraZ = cameraZ - driverZ
|
|
local_28 = local_28 - *(int *)(iVar4 + 0x4c);
|
|
|
|
// get direction from camera to driver
|
|
x = ratan2(local_30,local_28);
|
|
|
|
// pushBuffer-> ??? right after rotZ
|
|
*(short *)(PTR_DAT_8008d2ac + (uint)*(byte *)(param_2 + 0x4a) * 0x110 + 0x170) = (short)x;
|
|
|
|
// get distance between car and camera
|
|
x = SquareRoot0(local_30 * local_30 + local_28 * local_28);
|
|
|
|
// camPosY - driverY
|
|
x = ratan2(sVar1 - iVar3,x);
|
|
|
|
puVar2 = PTR_DAT_8008d2ac;
|
|
|
|
// camera->rotZ
|
|
*(short *)(PTR_DAT_8008d2ac + (uint)*(byte *)(param_2 + 0x4a) * 0x110 + 0x16e) =
|
|
0x800 - (short)x;
|
|
|
|
// camera-> ???
|
|
*(undefined2 *)(puVar2 + (uint)*(byte *)(param_2 + 0x4a) * 0x110 + 0x172) = 0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// VehStuckProc_PlantEaten_Init
|
|
// when eaten by plant on papu pyramid
|
|
// param1 = thread, param2 = driver
|
|
void FUN_800677d0(int param_1,int param_2)
|
|
{
|
|
// when this function executes, you are lifted
|
|
// above the track by the mask, where you respawn
|
|
|
|
int iVar1;
|
|
int iVar2;
|
|
|
|
iVar2 = *(int *)(param_1 + 0x34);
|
|
|
|
// set state to mask grab, so nobody hits you with weapon
|
|
*(undefined *)(param_2 + 0x376) = 5;
|
|
|
|
// boolInited = false
|
|
*(undefined *)(param_2 + 0x580) = 0;
|
|
|
|
*(undefined2 *)(param_2 + 0x3dc) = 0;
|
|
*(undefined2 *)(param_2 + 0x3e2) = 0;
|
|
*(undefined2 *)(param_2 + 0x3de) = 0;
|
|
|
|
// drop bits for airborne (and another?)
|
|
*(uint *)(param_2 + 0x2c8) = *(uint *)(param_2 + 0x2c8) & 0xfff7ffbf;
|
|
|
|
// "cloud" is the raincloud after hitting red potion
|
|
|
|
// if thread of "cloud" exists
|
|
if (*(int *)(param_2 + 0x4a0) != 0)
|
|
{
|
|
*(undefined2 *)(*(int *)(*(int *)(param_2 + 0x4a0) + 0x30) + 4) = 0;
|
|
|
|
// Set driver->cloudTh->funcThTick to destroy thread
|
|
*(undefined4 *)(*(int *)(param_2 + 0x4a0) + 0x2c) = 0x800b0f1c;
|
|
|
|
// erase pointer to "cloud" thread
|
|
*(undefined4 *)(param_2 + 0x4a0) = 0;
|
|
}
|
|
|
|
// Check if 231 dll is loaded
|
|
iVar1 = FUN_800348e8();
|
|
|
|
if (
|
|
// If it is loaded
|
|
(iVar1 != 0) &&
|
|
|
|
// If you're not in Adventure Arena
|
|
((*(uint *)PTR_DAT_8008d2ac & 0x100000) == 0)
|
|
)
|
|
{
|
|
// RB_Player_ModifyWumpa, -2
|
|
FUN_800abefc(param_2,0xfffffffe);
|
|
}
|
|
|
|
// allow this thread to ignore all collisions
|
|
*(uint *)(param_1 + 0x1c) = *(uint *)(param_1 + 0x1c) | 0x1000;
|
|
|
|
// make invisible
|
|
*(uint *)(iVar2 + 0x28) = *(uint *)(iVar2 + 0x28) | 0x80;
|
|
|
|
// OtherFX_Stop1 (three sounds)
|
|
FUN_80028808(*(undefined4 *)(param_2 + 0x304));
|
|
*(undefined4 *)(param_2 + 0x304) = 0;
|
|
FUN_80028808(*(undefined4 *)(param_2 + 0x308));
|
|
*(undefined4 *)(param_2 + 0x308) = 0;
|
|
FUN_80028808(*(undefined4 *)(param_2 + 0x300));
|
|
|
|
// VehStuckProc_PlantEaten_Update
|
|
*(undefined4 *)(param_2 + 0x58) = 0x8006749c;
|
|
|
|
// VehStuckProc_PlantEaten_PhysLinear
|
|
*(undefined4 *)(param_2 + 0x5c) = 0x80067554;
|
|
|
|
*(undefined4 *)(param_2 + 0x60) = 0x80062a2c; // OnAudio
|
|
*(undefined4 *)(param_2 + 0x300) = 0;
|
|
*(undefined4 *)(param_2 + 0x54) = 0;
|
|
*(undefined4 *)(param_2 + 100) = 0;
|
|
*(undefined4 *)(param_2 + 0x68) = 0;
|
|
*(undefined4 *)(param_2 + 0x6c) = 0; // COLL_StartSearch_NearPlayer
|
|
*(undefined4 *)(param_2 + 0x70) = 0; // VehPhysForce_CollideDrivers
|
|
*(undefined4 *)(param_2 + 0x74) = 0; // COLL_StartSearch_Player
|
|
*(undefined4 *)(param_2 + 0x78) = 0; // cant move anymore
|
|
*(undefined4 *)(param_2 + 0x7c) = 0;
|
|
|
|
// VehStuckProc_PlantEaten_Animate
|
|
*(undefined4 *)(param_2 + 0x80) = 0x800675c0;
|
|
|
|
// no particles
|
|
*(undefined4 *)(param_2 + 0x84) = 0;
|
|
return;
|
|
}
|
|
|
|
// VehStuckProc_RIP_Init
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80067930(undefined4 param_1,int param_2)
|
|
{
|
|
// VehStuckProc_PlantEaten_Init
|
|
FUN_800677d0(param_1, param_2);
|
|
|
|
// erase OnUpdate
|
|
*(undefined4 *)(param_2 + 0x58) = 0;
|
|
|
|
// erase OnAnimate
|
|
*(undefined4 *)(param_2 + 0x80) = 0;
|
|
|
|
// erase invisibleTimer
|
|
*(undefined4 *)(param_2 + 0x28) = 0;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
// VehStuckProc_RevEngine_Update
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80067960(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
undefined4 uVar1;
|
|
|
|
// If race has not started
|
|
if (*(char *)(param_2 + 0x594) == '\0')
|
|
{
|
|
// If Traffic Lights are not done counting down
|
|
if (0 < *(int *)(PTR_DAT_8008d2ac + 0x1d0c))
|
|
{
|
|
// Dont continue with the function,
|
|
// let your kart stay in a revving state
|
|
return;
|
|
}
|
|
}
|
|
|
|
// If race has started
|
|
else
|
|
{
|
|
|
|
// If mask grab has not lowered you close
|
|
// enough to the track to let you go
|
|
if (*(int *)(param_2 + 0x2d0) + 0x4000 <= *(int *)(param_2 + 0x2d8))
|
|
{
|
|
// Dont continue with the function,
|
|
// let your kart stay in a revving state
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Assume it's time to transition out of being
|
|
// frozen, and into driving, last iteration of
|
|
// this function
|
|
|
|
if (
|
|
// if reason for revving is mask grab
|
|
(*(char *)(param_2 + 0x594) != '\0') &&
|
|
|
|
// if maskObj exists
|
|
(*(int *)(param_2 + 0x580) != 0)
|
|
)
|
|
{
|
|
// end duration
|
|
*(undefined2 *)(*(int *)(param_2 + 0x580) + 6) = 0;
|
|
}
|
|
|
|
if (
|
|
// If sacred fire constant is less than ???
|
|
((int)*(short *)(param_2 + 0x42e) < *(int *)(param_2 + 0x588)) &&
|
|
((*(byte *)(param_2 + 0x593) & 3) == 0)
|
|
)
|
|
{
|
|
|
|
if (
|
|
// While not moving, if you rev'd your engine less than...
|
|
*(int *)(param_2 + 0x584) <
|
|
|
|
(int)*(short *)(param_2 + 0x42e) + (int)*(short *)(param_2 + 0x432))
|
|
{
|
|
// You get a small boost
|
|
uVar1 = 0x20;
|
|
}
|
|
|
|
// if you rev'd your engine high
|
|
else
|
|
{
|
|
// you get a big boost
|
|
uVar1 = 0x80;
|
|
}
|
|
|
|
// VehFire_Increment
|
|
// one full second of reserves
|
|
FUN_8005abfc(param_2,0x3c0,0,uVar1);
|
|
}
|
|
*(undefined2 *)(param_2 + 0x3dc) = 0;
|
|
*(undefined *)(param_2 + 0x4fe) = 0;
|
|
|
|
// VehPhysProc_Driving_Init
|
|
FUN_80062b74(param_1);
|
|
return;
|
|
}
|
|
|
|
|
|
// VehStuckProc_RevEngine_PhysLinear
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80067a74(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
undefined *puVar1;
|
|
int iVar2;
|
|
|
|
// elapsed milliseconds per frame, ~32
|
|
iVar2 = (uint)*(ushort *)(param_2 + 0x58e) - (uint)*(ushort *)(PTR_DAT_8008d2ac + 0x1d04);
|
|
|
|
*(undefined2 *)(param_2 + 0x58e) = (short)iVar2;
|
|
if (iVar2 * 0x10000 < 0) {
|
|
*(undefined2 *)(param_2 + 0x58e) = 0;
|
|
}
|
|
// elapsed milliseconds per frame, ~32
|
|
iVar2 = (uint)*(ushort *)(param_2 + 0x590) - (uint)*(ushort *)(PTR_DAT_8008d2ac + 0x1d04);
|
|
*(undefined2 *)(param_2 + 0x590) = (short)iVar2;
|
|
if (iVar2 * 0x10000 < 0) {
|
|
*(undefined2 *)(param_2 + 0x590) = 0;
|
|
}
|
|
|
|
// VehPhysProc_Driving_PhysLinear
|
|
FUN_8006181c(param_1,param_2);
|
|
|
|
puVar1 = PTR_DAT_8008d2ac;
|
|
|
|
// if race already started
|
|
if (*(char *)(param_2 + 0x594) != '\0')
|
|
{
|
|
// cameraDC flag
|
|
*(uint *)(PTR_DAT_8008d2ac + (uint)*(byte *)(param_2 + 0x4a) * 0xdc + 0x1508) =
|
|
*(uint *)(PTR_DAT_8008d2ac + (uint)*(byte *)(param_2 + 0x4a) * 0xdc + 0x1508) | 0x10;
|
|
|
|
*(undefined2 *)(puVar1 + (uint)*(byte *)(param_2 + 0x4a) * 0xdc + 0x1530) = 0x40;
|
|
|
|
// Y pos -= 0x200
|
|
*(int *)(param_2 + 0x2d8) = *(int *)(param_2 + 0x2d8) + -0x200;
|
|
|
|
// if maskObj exists
|
|
if (*(int *)(param_2 + 0x580) != 0)
|
|
{
|
|
// set mask duration
|
|
*(undefined2 *)(*(int *)(param_2 + 0x580) + 6) = 0x1e00;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// VehStuckProc_RevEngine_Animate
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80067b7c(int param_1,int param_2)
|
|
|
|
{
|
|
byte bVar1;
|
|
bool bVar2;
|
|
undefined2 uVar3;
|
|
int iVar4;
|
|
int local_18;
|
|
short sVar5;
|
|
undefined4 uVar6;
|
|
int iVar7;
|
|
uint uVar8;
|
|
int iVar9;
|
|
int iVar10;
|
|
|
|
// thread -> instance
|
|
iVar10 = *(int *)(param_1 + 0x34);
|
|
|
|
if (((0 < *(short *)(param_2 + 0x39e)) && (*(short *)(param_2 + 0x58e) == 0)) &&
|
|
((*(byte *)(param_2 + 0x593) & 3) == 0)) {
|
|
|
|
// Curr revving meter - Max revving meter
|
|
iVar4 = *(int *)(param_2 + 0x588) - *(int *)(param_2 + 0x584);
|
|
|
|
// absolute value
|
|
if (iVar4 < 0) {
|
|
iVar4 = -iVar4;
|
|
}
|
|
|
|
// NOPing will fill meter in
|
|
// slow motion, showing how it works
|
|
iVar4 = iVar4 >> 1;
|
|
|
|
iVar7 = iVar4;
|
|
|
|
// Speed of filling the meter changes
|
|
// depending on how full the meter is,
|
|
// there are two speeds
|
|
|
|
if (5000 < iVar4) {
|
|
iVar7 = 5000;
|
|
}
|
|
|
|
if (iVar4 < 0x100) {
|
|
iVar7 = 0x100;
|
|
}
|
|
|
|
// Interpolate turboMeter by speed
|
|
// parameters: curr revving meter and meter filling speed
|
|
iVar4 = FUN_80058f54(*(int *)(param_2 + 0x588),iVar7);
|
|
|
|
// Set new curr rev
|
|
*(int *)(param_2 + 0x588) = iVar4;
|
|
|
|
*(undefined *)(param_2 + 0x592) = 2;
|
|
|
|
// if max revv > filling speed
|
|
if (iVar4 < *(int *)(param_2 + 0x584)) {
|
|
*(undefined2 *)(param_2 + 0x58c) = 0;
|
|
}
|
|
|
|
else
|
|
{
|
|
// elapsed milliseconds per frame, ~32
|
|
sVar5 = *(short *)(param_2 + 0x58c) + *(short *)(PTR_DAT_8008d2ac + 0x1d04);
|
|
*(short *)(param_2 + 0x58c) = sVar5;
|
|
|
|
// if more than 0.192s
|
|
if (0xc0 < sVar5)
|
|
{
|
|
*(undefined *)(param_2 + 0x592) = 0;
|
|
*(byte *)(param_2 + 0x593) = *(byte *)(param_2 + 0x593) | 3;
|
|
|
|
// OtherFX_Play_Echo
|
|
FUN_80028494(0xf,1,(uint)*(ushort *)(param_2 + 0x2ca) & 1);
|
|
}
|
|
}
|
|
goto LAB_80067dec;
|
|
}
|
|
*(undefined2 *)(param_2 + 0x58c) = 0;
|
|
if (*(char *)(param_2 + 0x592) == '\x02') {
|
|
*(undefined2 *)(param_2 + 0x58e) = 0x100;
|
|
*(undefined *)(param_2 + 0x592) = 0;
|
|
|
|
// if curr rev > ???
|
|
if ((int)*(short *)(param_2 + 0x42e) < *(int *)(param_2 + 0x588)) {
|
|
*(undefined *)(param_2 + 0x592) = 1;
|
|
}
|
|
}
|
|
if ((*(char *)(param_2 + 0x592) != '\0') &&
|
|
|
|
// curr rev < ???
|
|
(*(int *)(param_2 + 0x588) < (int)*(short *)(param_2 + 0x42e))) {
|
|
*(undefined *)(param_2 + 0x592) = 0;
|
|
|
|
// Interpolate rotation by speed
|
|
// params: max revv, ???
|
|
uVar6 = FUN_80058f54(*(undefined4 *)(param_2 + 0x584),(int)*(short *)(param_2 + 0x432) / 3 + 3);
|
|
|
|
// max rev = ???
|
|
*(undefined4 *)(param_2 + 0x584) = uVar6;
|
|
}
|
|
|
|
// if curr rev < 1
|
|
if (*(int *)(param_2 + 0x588) < 1) {
|
|
*(byte *)(param_2 + 0x593) = *(byte *)(param_2 + 0x593) & 0xfd;
|
|
|
|
// max rev = ???
|
|
*(int *)(param_2 + 0x584) =
|
|
(int)*(short *)(param_2 + 0x42e) + (int)*(short *)(param_2 + 0x432) / 3;
|
|
}
|
|
|
|
// if curr rev >= 1
|
|
else {
|
|
|
|
// rev deacceleration rate = curr rev / 2
|
|
uVar8 = *(int *)(param_2 + 0x588) >> 1;
|
|
|
|
if ((*(byte *)(param_2 + 0x593) & 2) == 0) {
|
|
bVar2 = (int)uVar8 < 0x100;
|
|
|
|
// if rev deacceleration rate > 1000
|
|
if (1000 < (int)uVar8) {
|
|
|
|
// rev deacceleration rate = 1000
|
|
uVar8 = 1000;
|
|
goto LAB_80067d64;
|
|
}
|
|
}
|
|
|
|
else {
|
|
bVar2 = (int)uVar8 < 0x100;
|
|
|
|
// if rev deacceleration rate > 3000
|
|
if (3000 < (int)uVar8) {
|
|
|
|
// rev deacceleration rate = 3000
|
|
uVar8 = 3000;
|
|
LAB_80067d64:
|
|
bVar2 = uVar8 < 0x100;
|
|
}
|
|
}
|
|
if (bVar2) {
|
|
|
|
// rev deacceleration rate = 0x100
|
|
uVar8 = 0x100;
|
|
}
|
|
|
|
// new rev = curr rev - rev deacceleration rate
|
|
iVar4 = *(int *)(param_2 + 0x588) - uVar8;
|
|
|
|
// curr rev = new rev
|
|
*(int *)(param_2 + 0x588) = iVar4;
|
|
|
|
// if new rev < 1
|
|
if (iVar4 < 1) {
|
|
|
|
*(undefined2 *)(param_2 + 0x590) = 0xc0;
|
|
|
|
// curr rev = 0
|
|
*(undefined4 *)(param_2 + 0x588) = 0;
|
|
}
|
|
}
|
|
if (*(short *)(param_2 + 0x39e) < 1) {
|
|
*(byte *)(param_2 + 0x593) = *(byte *)(param_2 + 0x593) & 0xfe;
|
|
}
|
|
LAB_80067dec:
|
|
if ((*(uint *)(param_2 + 0x590) & 0x200ffff) == 0) {
|
|
|
|
// if curr rev < ???
|
|
if (*(int *)(param_2 + 0x588) < (int)*(short *)(param_2 + 0x42e)) {
|
|
*(undefined *)(param_2 + 0x4fe) = 0;
|
|
}
|
|
else {
|
|
*(undefined *)(param_2 + 0x4fe) = 1;
|
|
}
|
|
}
|
|
else {
|
|
*(undefined *)(param_2 + 0x4fe) = 2;
|
|
}
|
|
iVar4 = (int)*(short *)(param_2 + 0x42e);
|
|
|
|
// ??? = curr rev
|
|
*(undefined2 *)(param_2 + 0x36e) = *(undefined2 *)(param_2 + 0x588);
|
|
|
|
// if curr rev < ???
|
|
if (*(int *)(param_2 + 0x588) < iVar4)
|
|
{
|
|
|
|
// 476 and 447 can be absolutely any value,
|
|
// by default they are 15 and 30, but as long as
|
|
// they are proportional (1 and 2, 4 and 8), they
|
|
// behave the same as 15 and 30
|
|
|
|
bVar1 = *(byte *)(param_2 + 0x476);
|
|
|
|
// 477 changes when meter turns red
|
|
local_18 = (uint)*(byte *)(param_2 + 0x477) * 0x20 + 1;
|
|
|
|
// curr rev
|
|
uVar6 = *(undefined4 *)(param_2 + 0x588);
|
|
iVar7 = 0;
|
|
iVar9 = iVar4;
|
|
}
|
|
else
|
|
{
|
|
// 477 changes when meter turns red
|
|
bVar1 = *(byte *)(param_2 + 0x477);
|
|
|
|
local_18 = 1;
|
|
|
|
// curr rev
|
|
uVar6 = *(undefined4 *)(param_2 + 0x588);
|
|
iVar9 = iVar4 + *(short *)(param_2 + 0x432);
|
|
iVar7 = iVar4;
|
|
}
|
|
|
|
// Get percentage of uVar6 between iVar7 and iVar9,
|
|
// then return that same percentage between bVar1<<5 and local18
|
|
// Map value from [oldMin, oldMax] to [newMin, newMax]
|
|
// inverting newMin and newMax will give an inverse range mapping
|
|
uVar3 = FUN_80058f9c(uVar6,iVar7,iVar9,(uint)bVar1 << 5,local_18);
|
|
|
|
*(undefined2 *)(param_2 + 0x3dc) = uVar3;
|
|
*(undefined4 *)(param_2 + 0x490) = 0;
|
|
iVar4 = (int)((uint)*(ushort *)(param_2 + 0x36e) << 0x10) >> 0x16;
|
|
|
|
*(short *)(param_2 + 0x40c) = (short)*(ushort *)(param_2 + 0x36e) >> 6;
|
|
|
|
if (iVar4 < 0x401) {
|
|
if (iVar4 < 0) {
|
|
*(undefined2 *)(param_2 + 0x40c) = 0;
|
|
}
|
|
}
|
|
|
|
else {
|
|
*(undefined2 *)(param_2 + 0x40c) = 0x400;
|
|
}
|
|
|
|
// Set the scale of the car while revving the engine,
|
|
// this is a basic "squash and stretch" concept of animation, before motion
|
|
|
|
// Reduce height a little
|
|
*(short *)(iVar10 + 0x1e) = 0xccc - *(short *)(param_2 + 0x40c);
|
|
|
|
// Increase X and Z a little
|
|
*(short *)(iVar10 + 0x1c) = (short)(((int)*(short *)(param_2 + 0x40c) * 6) / 10) + 0xccc;
|
|
*(short *)(iVar10 + 0x20) = (short)(((int)*(short *)(param_2 + 0x40c) * 6) / 10) + 0xccc;
|
|
|
|
return;
|
|
}
|
|
|
|
// VehStuckProc_RevEngine_Init
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80067f4c(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
// spawn function that waits for traffic lights
|
|
|
|
undefined4 uVar1;
|
|
|
|
// kart state to rev
|
|
*(undefined *)(param_2 + 0x376) = 4;
|
|
|
|
*(undefined *)(param_2 + 0x4fe) = 0;
|
|
*(undefined4 *)(param_2 + 0x588) = 0;
|
|
|
|
// assume reason for revving is: start of race
|
|
*(undefined *)(param_2 + 0x594) = 0;
|
|
|
|
// clear maskObj
|
|
*(undefined4 *)(param_2 + 0x580) = 0;
|
|
|
|
// if this is a mask grab
|
|
if (*(int *)(param_2 + 0x2d0) + 0x1000 < *(int *)(param_2 + 0x2d8))
|
|
{
|
|
// assume reason for revving is: mask grab
|
|
*(undefined *)(param_2 + 0x594) = 1;
|
|
|
|
// VehPickupItem_MaskUseWeapon
|
|
uVar1 = FUN_80064c38(param_2,0);
|
|
|
|
// Mask Object
|
|
*(undefined4 *)(param_2 + 0x580) = uVar1;
|
|
|
|
// Driver flag
|
|
*(uint *)(param_2 + 0x2c8) = *(uint *)(param_2 + 0x2c8) & 0xfffffffe;
|
|
|
|
// CameraDC flag
|
|
*(uint *)(PTR_DAT_8008d2ac + (uint)*(byte *)(param_2 + 0x4a) * 0xdc + 0x1508) =
|
|
*(uint *)(PTR_DAT_8008d2ac + (uint)*(byte *)(param_2 + 0x4a) * 0xdc + 0x1508) | 8;
|
|
}
|
|
|
|
// firstFrameSinceRevEngine
|
|
*(undefined *)(param_2 + 0x449) = 1;
|
|
|
|
// VehStuckProc_RevEngine_Update
|
|
*(undefined4 *)(param_2 + 0x58) = 0x80067960;
|
|
|
|
// VehStuckProc_RevEngine_PhysLinear
|
|
*(undefined4 *)(param_2 + 0x5c) = 0x80067a74;
|
|
|
|
*(undefined4 *)(param_2 + 0x60) = 0x80062a2c; // OnAudio
|
|
*(undefined4 *)(param_2 + 0x7c) = 0x8005ee34; // VehPhysForce_TranslateMatrix -- move position to instance matrix
|
|
|
|
// VehStuckProc_RevEngine_Animate
|
|
*(undefined4 *)(param_2 + 0x80) = 0x80067b7c;
|
|
|
|
// VehEmitter_DriverMain
|
|
*(undefined4 *)(param_2 + 0x84) = 0x80059a18;
|
|
|
|
*(undefined2 *)(param_2 + 0x58c) = 0;
|
|
*(undefined2 *)(param_2 + 0x58e) = 0;
|
|
*(undefined *)(param_2 + 0x592) = 0;
|
|
*(undefined *)(param_2 + 0x593) = 0;
|
|
*(undefined2 *)(param_2 + 0x590) = 0;
|
|
*(undefined4 *)(param_2 + 0x54) = 0;
|
|
*(undefined4 *)(param_2 + 100) = 0;
|
|
*(undefined4 *)(param_2 + 0x68) = 0;
|
|
*(undefined4 *)(param_2 + 0x6c) = 0; // COLL_StartSearch_NearPlayer
|
|
*(undefined4 *)(param_2 + 0x70) = 0; // VehPhysForce_CollideDrivers
|
|
*(undefined4 *)(param_2 + 0x74) = 0; // COLL_StartSearch_Player
|
|
*(undefined4 *)(param_2 + 0x78) = 0; // cant move anymore
|
|
*(int *)(param_2 + 0x584) =
|
|
(int)*(short *)(param_2 + 0x42e) + (int)*(short *)(param_2 + 0x432) / 3;
|
|
return;
|
|
}
|
|
|
|
|
|
// VehStuckProc_Tumble_Update
|
|
// param1 = thread, param2 = driver
|
|
void FUN_8006809c(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
// if you are done being blasted, NoInput ended
|
|
if (*(short *)(param_2 + 0x400) == 0) {
|
|
*(undefined *)(param_2 + 0x4c) = 0;
|
|
*(undefined *)(param_2 + 0x4d) = 0;
|
|
|
|
// VehPhysProc_Driving_Init
|
|
FUN_80062b74();
|
|
}
|
|
return;
|
|
}
|
|
|
|
// VehStuckProc_Tumble_PhysLinear
|
|
// param1 = thread, param2 = driver
|
|
void FUN_800680d0(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
int iVar1;
|
|
|
|
// NoInput timer = NoInput timer - elapsed milliseconds per frame, ~32
|
|
iVar1 = (uint)*(ushort *)(param_2 + 0x400) - (uint)*(ushort *)(PTR_DAT_8008d2ac + 0x1d04);
|
|
*(undefined2 *)(param_2 + 0x400) = (short)iVar1;
|
|
|
|
// if negative
|
|
if (iVar1 * 0x10000 < 0)
|
|
{
|
|
// set to zero
|
|
*(undefined2 *)(param_2 + 0x400) = 0;
|
|
}
|
|
|
|
// VehPhysProc_Driving_PhysLinear
|
|
FUN_8006181c(param_1,param_2);
|
|
|
|
// force to jump when hit the ground,
|
|
// lock to 96ms (0.1s) until blasted state is over
|
|
*(undefined2 *)(param_2 + 0x3f6) = 0x60;
|
|
|
|
// reset two speed variables
|
|
*(undefined2 *)(param_2 + 0x39c) = 0;
|
|
*(undefined2 *)(param_2 + 0x39e) = 0;
|
|
|
|
// wheels skidding, blasted, accel prevention
|
|
*(uint *)(param_2 + 0x2c8) = *(uint *)(param_2 + 0x2c8) | 0x5808;
|
|
|
|
// jump_InitialVelY to throw driver in air
|
|
*(short *)(param_2 + 0x3f8) = *(short *)(param_2 + 0x400) * 2 + 6000;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
// VehStuckProc_Tumble_PhysAngular
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80068150(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
undefined *puVar1;
|
|
ushort uVar2;
|
|
undefined2 uVar3;
|
|
short sVar4;
|
|
|
|
puVar1 = PTR_DAT_8008d2ac;
|
|
*(undefined2 *)(param_2 + 0x3e6) = 10000;
|
|
|
|
// decrease turn rate by 1/8 of itself
|
|
*(short *)(param_2 + 0x3b4) = *(short *)(param_2 + 0x3b4) - (*(short *)(param_2 + 0x3b4) >> 3);
|
|
|
|
sVar4 = *(short *)(param_2 + 0x3d2) - (*(short *)(param_2 + 0x3d2) >> 3);
|
|
*(short *)(param_2 + 0x3d2) = sVar4;
|
|
|
|
*(short *)(param_2 + 0xc0) = *(short *)(param_2 + 0x3b4);
|
|
*(short *)(param_2 + 0x3c6) = (*(short *)(param_2 + 0x3c6) + sVar4 + 0x800U & 0xfff) - 0x800;
|
|
*(short *)(param_2 + 0x3d4) = *(short *)(param_2 + 0x3d4) - (*(short *)(param_2 + 0x3d4) >> 3);
|
|
|
|
// angle change = angle + (spinRate * time lapsed between frames) & 0xFFF
|
|
uVar2 = *(short *)(param_2 + 0x39a) +
|
|
(short)((int)*(short *)(param_2 + 0x3b4) * *(int *)(puVar1 + 0x1d04) >> 0xd) & 0xfff;
|
|
|
|
// angle = angle change
|
|
*(ushort *)(param_2 + 0x39a) = uVar2;
|
|
|
|
// cameraRotY = ??? + kart angle + drift angle
|
|
*(short *)(param_2 + 0x2ee) = *(short *)(param_2 + 0x3d4) + uVar2 + *(short *)(param_2 + 0x3c6);
|
|
|
|
// Interpolate rotation by speed
|
|
uVar3 = FUN_80058f54((int)*(short *)(param_2 + 0x2f2),(*(int *)(puVar1 + 0x1d04) << 5) >> 5,0);
|
|
|
|
// set new camera rotation
|
|
*(undefined2 *)(param_2 + 0x2f2) = uVar3;
|
|
|
|
// VehPhysForce_RotAxisAngle
|
|
FUN_8005f89c(param_2 + 0x310,param_2 + 0x360,(int)*(short *)(param_2 + 0x39a));
|
|
return;
|
|
}
|
|
|
|
// VehStuckProc_Tumble_Animate
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80068244(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
char cVar1;
|
|
int iVar2;
|
|
|
|
// set animation index
|
|
*(undefined *)(param_2 + 0x4c) = 6;
|
|
|
|
// get amount of time remaining before you can move (while blasted),
|
|
// use that to determine animation frame of bouncing around
|
|
iVar2 = (int)((uint)*(ushort *)(param_2 + 0x400) << 0x10) >> 0x15;
|
|
|
|
// DAT_80087f28 is a constant for how many frames are in "blasted" anim
|
|
|
|
// Just a stupid fail-safe to alert the debugger
|
|
if (DAT_80087f28 == 0) trap(0x1c00);
|
|
if ((DAT_80087f28 == -1) && (iVar2 == -0x80000000)) trap(0x1800);
|
|
|
|
// get animation frame of blasted
|
|
cVar1 = (char)(iVar2 % DAT_80087f28);
|
|
|
|
if (*(char *)(param_2 + 0x580) != '\0')
|
|
{
|
|
// play animation backwards???
|
|
cVar1 = (char)DAT_80087f28 - (cVar1 + '\x01');
|
|
}
|
|
|
|
// set animation frame
|
|
*(char *)(param_2 + 0x4d) = cVar1;
|
|
|
|
return;
|
|
}
|
|
|
|
// VehStuckProc_Tumble_Init
|
|
// param1 = thread, param2 = driver
|
|
void FUN_800682a4(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
byte bVar1;
|
|
undefined2 uVar2;
|
|
int iVar3;
|
|
undefined4 uVar4;
|
|
|
|
// put player in flipping animation after being hit
|
|
*(undefined *)(param_2 + 0x376) = 6;
|
|
|
|
*(undefined2 *)(param_2 + 0x3dc) = 0;
|
|
|
|
// Check if 231 dll is loaded
|
|
iVar3 = FUN_800348e8();
|
|
if (
|
|
// if it is loaded
|
|
(iVar3 != 0) &&
|
|
|
|
// If you're not in Adventure Arena
|
|
((*(uint *)PTR_DAT_8008d2ac & 0x100000) == 0)
|
|
)
|
|
{
|
|
// RB_Player_ModifyWumpa, -3
|
|
FUN_800abefc(param_2,0xfffffffd);
|
|
}
|
|
|
|
// set animation to zero
|
|
*(undefined *)(*(int *)(param_2 + 0x1c) + 0x52) = 0;
|
|
|
|
// Instance_GetNumAnimFrames(instance, anim#0)
|
|
uVar4 = FUN_8005b0f4(*(undefined4 *)(param_2 + 0x1c),0);
|
|
|
|
// VehFrameInst_GetStartFrame(midpoint, numFrames)
|
|
uVar2 = FUN_8005b0c4(0,uVar4);
|
|
|
|
// set animation frame
|
|
*(undefined2 *)(*(int *)(param_2 + 0x1c) + 0x54) = uVar2;
|
|
|
|
// Get random number
|
|
bVar1 = FUN_8003ea28();
|
|
|
|
// randomly play blasted backwards
|
|
*(byte *)(param_2 + 0x580) = bVar1 & 4;
|
|
|
|
// VehStuckProc_Tumble_Update
|
|
*(undefined4 *)(param_2 + 0x58) = 0x8006809c;
|
|
|
|
// VehStuckProc_Tumble_PhysLinear
|
|
*(undefined4 *)(param_2 + 0x5c) = 0x800680d0;
|
|
|
|
*(undefined4 *)(param_2 + 0x60) = 0x80062a2c; // OnAudio
|
|
*(undefined4 *)(param_2 + 100) = 0x80068150; // OnPhysAngular
|
|
*(undefined4 *)(param_2 + 0x68) = 0x8005ea60; // VehPhysForce_OnApplyForces
|
|
*(undefined4 *)(param_2 + 0x6c) = 0x80020410; // COLL_StartSearch_NearPlayer
|
|
*(undefined4 *)(param_2 + 0x70) = 0x8005ebac; // VehPhysForce_CollideDrivers
|
|
*(undefined4 *)(param_2 + 0x74) = 0x8001d944; // COLL_StartSearch_Player
|
|
*(undefined4 *)(param_2 + 0x78) = 0x80060630; // JumpAndFriction
|
|
*(undefined4 *)(param_2 + 0x7c) = 0x8005ee34; // VehPhysForce_TranslateMatrix -- move position to instance matrix
|
|
|
|
// VehStuckProc_Tumble_Animate
|
|
*(undefined4 *)(param_2 + 0x80) = 0x80068244;
|
|
|
|
// Erase OnInit, now that it has executed
|
|
*(undefined4 *)(param_2 + 0x54) = 0;
|
|
|
|
// VehEmitter_DriverMain
|
|
*(undefined4 *)(param_2 + 0x84) = 0x80059a18;
|
|
|
|
if (*(char *)(param_2 + 0x4b) < '\x01') {
|
|
uVar4 = 0x19;
|
|
}
|
|
else {
|
|
uVar4 = 0x29;
|
|
}
|
|
|
|
// GAMEPAD_JogCon1
|
|
FUN_800263a0(param_2,uVar4,0x60);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
// VehStuckProc_Warp_MoveDustPuff
|
|
// "dustpuff" is really lightning under the player,
|
|
// without this, lightning is half-stuck under the player
|
|
void FUN_800683f4(short *param_1,int param_2,int param_3,short *param_4)
|
|
|
|
{
|
|
uint uVar1;
|
|
short *psVar2;
|
|
int iVar3;
|
|
int iVar4;
|
|
int iVar5;
|
|
short *psVar6;
|
|
int iVar7;
|
|
|
|
// Get random number
|
|
uVar1 = FUN_8003ea28();
|
|
|
|
iVar4 = param_3 >> 1;
|
|
iVar5 = (int)((uVar1 & 0xfff) * param_3) >> 0xc;
|
|
if (iVar5 < iVar4) {
|
|
iVar5 = iVar5 - param_3;
|
|
}
|
|
|
|
// Get random number
|
|
uVar1 = FUN_8003ea28();
|
|
|
|
iVar7 = (int)((uVar1 & 0xfff) * param_3) >> 0xc;
|
|
if (iVar7 < iVar4) {
|
|
iVar7 = iVar7 - param_3;
|
|
}
|
|
|
|
// Get random number
|
|
uVar1 = FUN_8003ea28();
|
|
|
|
iVar3 = (int)((uVar1 & 0xfff) * param_3) >> 0xc;
|
|
if (iVar3 < iVar4) {
|
|
iVar3 = iVar3 - param_3;
|
|
}
|
|
psVar2 = param_1 + param_2 * 4;
|
|
iVar4 = param_2 >> 1;
|
|
psVar6 = param_1 + iVar4 * 4;
|
|
*psVar6 = (short)((int)*param_1 + (int)*psVar2 >> 1) + (short)(*param_4 * iVar5 >> 0xc);
|
|
psVar6[1] = (short)((int)param_1[1] + (int)psVar2[1] >> 1) + (short)(param_4[1] * iVar7 >> 0xc);
|
|
psVar6[2] = (short)((int)param_1[2] + (int)psVar2[2] >> 1) + (short)(param_4[2] * iVar3 >> 0xc);
|
|
if (2 < param_2) {
|
|
iVar5 = param_3 * 0xc00 >> 0xc;
|
|
|
|
// VehStuckProc_Warp_MoveDustPuff
|
|
FUN_800683f4(param_1,iVar4,iVar5,param_4);
|
|
|
|
// VehStuckProc_Warp_MoveDustPuff
|
|
FUN_800683f4(psVar6,iVar4,iVar5,param_4);
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// VehStuckProc_Warp_AddDustPuff1
|
|
void FUN_800685b0(short *param_1)
|
|
|
|
{
|
|
int iVar1;
|
|
|
|
if (((*(uint *)(PTR_DAT_8008d2ac + 0x1cec) & 1) == 0) &&
|
|
(
|
|
// Create instance in particle pool
|
|
iVar1 = FUN_80040308(0,*(undefined4 *)(PTR_DAT_8008d2ac + 0x2118),&DAT_8008a180),
|
|
iVar1 != 0
|
|
))
|
|
{
|
|
// position variables
|
|
*(int *)(iVar1 + 0x24) = *(int *)(iVar1 + 0x24) + (int)*param_1 * 0x100;
|
|
*(int *)(iVar1 + 0x2c) = *(int *)(iVar1 + 0x2c) + (int)param_1[1] * 0x100;
|
|
*(int *)(iVar1 + 0x34) = *(int *)(iVar1 + 0x34) + (int)param_1[2] * 0x100;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// VehStuckProc_Warp_AddDustPuff2
|
|
void FUN_80068644(int param_1,int param_2)
|
|
|
|
{
|
|
short sVar1;
|
|
short sVar2;
|
|
ushort uVar3;
|
|
short sVar4;
|
|
short sVar5;
|
|
short sVar6;
|
|
uint *puVar7;
|
|
undefined4 in_zero;
|
|
undefined4 in_at;
|
|
short extraout_var;
|
|
short extraout_var_00;
|
|
int iVar8;
|
|
uint uVar9;
|
|
uint *puVar10;
|
|
undefined4 uVar11;
|
|
uint *puVar12;
|
|
uint *puVar13;
|
|
short *psVar14;
|
|
short *psVar15;
|
|
uint *puVar16;
|
|
undefined4 *puVar17;
|
|
int iVar18;
|
|
uint *puVar19;
|
|
undefined *puVar20;
|
|
int local_30;
|
|
|
|
// pointer to each player's pushBuffer buffer
|
|
puVar20 = PTR_DAT_8008d2ac + (uint)*(byte *)(param_1 + 0x4a) * 0x110 + 0x168;
|
|
|
|
// set several pushBuffer buffer variables to coprocessor
|
|
gte_SetRotMatrix(puVar20 + 0x28);
|
|
gte_SetTransMatrix(puVar20 + 0x28);
|
|
|
|
// handle some pushBuffer buffer variables in RAM
|
|
sVar1 = *(short *)(puVar20 + 0x48);
|
|
sVar2 = *(short *)(puVar20 + 0x4e);
|
|
uVar3 = *(ushort *)(puVar20 + 0x54);
|
|
|
|
// handle some pushBuffer buffer variables in scratchpad
|
|
DAT_1f8001c0 = (undefined2)((int)sVar1 + (int)*(short *)(puVar20 + 0x4a) >> 5);
|
|
DAT_1f8001c2 = (undefined2)
|
|
((int)*(short *)(puVar20 + 0x4e) + (int)*(short *)(puVar20 + 0x50) >> 5);
|
|
DAT_1f8001c4 = (undefined2)
|
|
((int)*(short *)(puVar20 + 0x54) + (int)*(short *)(puVar20 + 0x56) >> 5);
|
|
|
|
// backBuffer->primMem.curr
|
|
puVar19 = *(uint **)(*(int *)(PTR_DAT_8008d2ac + 0x10) + 0x80);
|
|
|
|
// if driver -> instance -> flags & INVISIBLE is true
|
|
if ((*(uint *)(*(int *)(param_1 + 0x1c) + 0x28) & 0x80) != 0)
|
|
{
|
|
DAT_1f800188._0_2_ = (short)((uint)*(undefined4 *)(param_1 + 0x2d4) >> 8);
|
|
DAT_1f800188._2_2_ = (undefined2)((uint)*(undefined4 *)(param_2 + 0x10) >> 8);
|
|
DAT_1f80018c._0_2_ = (short)((uint)*(undefined4 *)(param_1 + 0x2dc) >> 8);
|
|
|
|
// add dust puff
|
|
FUN_800685b0(&DAT_1f800188);
|
|
}
|
|
|
|
local_30 = 0;
|
|
do {
|
|
iVar18 = (local_30 << 0xc) / 6;
|
|
|
|
// Sine(angle)
|
|
iVar8 = FUN_8003d184(iVar18 + *(int *)(param_2 + 0xc));
|
|
|
|
_DAT_1f800108 =
|
|
CONCAT22((short)((uint)*(undefined4 *)(param_2 + 8) >> 8),
|
|
(short)((uint)*(undefined4 *)(param_1 + 0x2d4) >> 8) - (short)(iVar8 >> 5));
|
|
|
|
// Cosine(angle)
|
|
iVar8 = FUN_8003d1c0(iVar18 + *(int *)(param_2 + 0xc));
|
|
|
|
_DAT_1f80010c =
|
|
_DAT_1f80010c & 0xffff0000 |
|
|
(uint)(ushort)((short)((uint)*(undefined4 *)(param_1 + 0x2dc) >> 8) - (short)(iVar8 >> 5));
|
|
DAT_1f800188._0_2_ = (short)((uint)*(undefined4 *)(param_1 + 0x2d4) >> 8);
|
|
DAT_1f800188._2_2_ = (undefined2)((uint)*(undefined4 *)(param_2 + 0x10) >> 8);
|
|
DAT_1f80018c._0_2_ = (short)((uint)*(undefined4 *)(param_1 + 0x2dc) >> 8);
|
|
|
|
// driver -> instSelf -> flags -> INVISIBLE is false
|
|
if ((*(uint *)(*(int *)(param_1 + 0x1c) + 0x28) & 0x80) == 0) {
|
|
|
|
// Sine(angle)
|
|
iVar8 = FUN_8003d184(iVar18 + *(int *)(param_2 + 0xc));
|
|
|
|
_DAT_1f800108 =
|
|
_DAT_1f800108 & 0xffff0000 | (uint)(ushort)(DAT_1f800108 - (short)(iVar8 >> 6));
|
|
|
|
// Cosine(angle)
|
|
iVar8 = FUN_8003d1c0(iVar18 + *(int *)(param_2 + 0xc));
|
|
|
|
_DAT_1f80010c =
|
|
_DAT_1f80010c & 0xffff0000 | (uint)(ushort)(DAT_1f80010c - (short)(iVar8 >> 6));
|
|
|
|
// Sine(angle)
|
|
FUN_8003d184(iVar18 + *(int *)(param_2 + 0xc));
|
|
|
|
DAT_1f800188._0_2_ = (short)DAT_1f800188 + extraout_var;
|
|
|
|
// Cosine(angle)
|
|
FUN_8003d1c0(iVar18 + *(int *)(param_2 + 0xc));
|
|
|
|
DAT_1f80018c._0_2_ = (short)DAT_1f80018c + extraout_var_00;
|
|
}
|
|
|
|
// if driver is visible
|
|
else
|
|
{
|
|
// add dust puff
|
|
FUN_800685b0(&DAT_1f800108);
|
|
}
|
|
|
|
uVar11 = 0x10;
|
|
|
|
// VehStuckProc_Warp_MoveDustPuff
|
|
FUN_800683f4(&DAT_1f800108,0x10,0x100,&DAT_1f8001c0);
|
|
|
|
iVar18 = 1;
|
|
puVar17 = (undefined4 *)&DAT_1f800108;
|
|
do {
|
|
puVar10 = (uint *)(iVar18 << 7);
|
|
|
|
// Sine(angle)
|
|
iVar8 = FUN_8003d184(puVar10);
|
|
|
|
iVar18 = iVar18 + 1;
|
|
*(short *)((int)puVar17 + 10) = *(short *)((int)puVar17 + 10) + (short)(iVar8 >> 7);
|
|
puVar17 = puVar17 + 2;
|
|
} while (iVar18 < 0x10);
|
|
sVar4 = sVar1 >> 10;
|
|
sVar5 = sVar2 >> 10;
|
|
DAT_1f800190 = CONCAT22(DAT_1f80010a + sVar5,DAT_1f800108 + sVar4);
|
|
sVar6 = (short)uVar3 >> 10;
|
|
DAT_1f800194 = DAT_1f800194 & 0xffff0000 | (uint)(ushort)(DAT_1f80010c + sVar6);
|
|
uVar9 = (_DAT_1f80010c & 0xffff) - ((int)((uint)uVar3 << 0x10) >> 0x1a);
|
|
DAT_1f800198 = CONCAT22(DAT_1f80010a - sVar5,DAT_1f800108 - sVar4);
|
|
DAT_1f80019c = DAT_1f80019c & 0xffff0000 | uVar9 & 0xffff;
|
|
|
|
#if 0
|
|
setCopReg(2,in_zero,DAT_1f800190);
|
|
setCopReg(2,in_at,DAT_1f800194);
|
|
setCopReg(2,0x1f800190,_DAT_1f800108);
|
|
setCopReg(2,uVar9,_DAT_1f80010c);
|
|
setCopReg(2,puVar10,DAT_1f800198);
|
|
setCopReg(2,uVar11,DAT_1f80019c);
|
|
|
|
// RTPT - Perspective Transformation (triple)
|
|
gte_rtpt();
|
|
|
|
DAT_1f8001a0 = getCopReg(2,0xc);
|
|
DAT_1f8001a4 = getCopReg(2,0xd);
|
|
DAT_1f8001a8 = getCopReg(2,0xe);
|
|
DAT_1f8001ac = getCopReg(2,0x11);
|
|
#else
|
|
gte_ldv01();
|
|
gte_ldv2();
|
|
gte_rtpt();
|
|
gte_stsxy3c();
|
|
gte_stSZ1();
|
|
#endif
|
|
|
|
iVar18 = 0;
|
|
puVar12 = puVar19 + 0x11;
|
|
puVar7 = &DAT_1f8001a0;
|
|
psVar14 = &DAT_1f80010c;
|
|
puVar16 = &DAT_1f8001b0;
|
|
puVar17 = (undefined4 *)&DAT_1f800108;
|
|
do {
|
|
puVar13 = puVar7;
|
|
puVar17 = puVar17 + 2;
|
|
psVar15 = psVar14 + 4;
|
|
DAT_1f800190 = CONCAT22(psVar14[3] + sVar5,*(short *)puVar17 + sVar4);
|
|
DAT_1f800194 = DAT_1f800194 & 0xffff0000 | (uint)(ushort)(*psVar15 + sVar6);
|
|
DAT_1f800198 = CONCAT22(psVar14[3] - sVar5,*(short *)puVar17 - sVar4);
|
|
DAT_1f80019c = DAT_1f80019c & 0xffff0000 | (uint)(ushort)(*psVar15 - sVar6);
|
|
|
|
#if 0
|
|
setCopReg(2,in_zero,DAT_1f800190);
|
|
setCopReg(2,in_at,DAT_1f800194);
|
|
setCopReg(2,0x1f800190,*puVar17);
|
|
setCopReg(2,puVar16,puVar17[3]);
|
|
setCopReg(2,puVar10,DAT_1f800198);
|
|
setCopReg(2,puVar12,DAT_1f80019c);
|
|
|
|
gte_rtpt();
|
|
|
|
uVar9 = getCopReg(2,0xc);
|
|
*puVar16 = uVar9;
|
|
uVar9 = getCopReg(2,0xd);
|
|
puVar16[1] = uVar9;
|
|
uVar9 = getCopReg(2,0xe);
|
|
puVar16[2] = uVar9;
|
|
uVar9 = getCopReg(2,0x11);
|
|
puVar16[3] = uVar9;
|
|
#else
|
|
gte_ldv01();
|
|
gte_ldv2();
|
|
gte_rtpt();
|
|
gte_stsxy3c();
|
|
gte_stSZ1();
|
|
#endnif
|
|
|
|
puVar12[-0x10] = 0xe1000a20;
|
|
puVar12[-0xf] = 0x3a000000;
|
|
puVar12[-0xd] = 0x7f1f3f;
|
|
puVar12[-0xb] = 0;
|
|
puVar12[-9] = 0x7f1f3f;
|
|
puVar12[-0xe] = *puVar16;
|
|
puVar12[-0xc] = puVar16[1];
|
|
puVar12[-10] = *puVar13;
|
|
uVar9 = puVar13[1];
|
|
puVar12[-7] = 0x3a000000;
|
|
puVar12[-5] = 0x7f1f3f;
|
|
puVar12[-3] = 0;
|
|
puVar12[-1] = 0x7f1f3f;
|
|
puVar12[-8] = uVar9;
|
|
puVar12[-6] = puVar16[2];
|
|
puVar12[-4] = puVar16[1];
|
|
iVar18 = iVar18 + 1;
|
|
puVar12[-2] = puVar13[2];
|
|
*puVar12 = puVar13[1];
|
|
puVar10 = (uint *)(*(int *)(puVar20 + 0xf4) + ((int)puVar16[3] >> 6) * 4);
|
|
puVar12 = puVar12 + 0x12;
|
|
*puVar19 = *puVar10 | 0x11000000;
|
|
*puVar10 = (uint)puVar19 & 0xffffff;
|
|
puVar19 = puVar19 + 0x12;
|
|
puVar7 = puVar16;
|
|
psVar14 = psVar15;
|
|
puVar16 = puVar13;
|
|
puVar17 = puVar17;
|
|
} while (iVar18 < 0x10);
|
|
local_30 = local_30 + 1;
|
|
} while (local_30 < 6);
|
|
|
|
// backBuffer->primMem.curr
|
|
*(uint **)(*(int *)(PTR_DAT_8008d2ac + 0x10) + 0x80) = puVar19;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
// VehStuckProc_Warp_PhysAngular
|
|
// param1 = thread, param2 = driver
|
|
// animate rotation and scale in warppad
|
|
void FUN_80068be8(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
undefined2 uVar1;
|
|
short sVar2;
|
|
int iVar3;
|
|
int iVar4;
|
|
int *piVar5;
|
|
undefined2 local_18;
|
|
short local_16;
|
|
undefined2 local_14;
|
|
|
|
// get instance from driver object
|
|
iVar4 = *(int *)(param_2 + 0x1c);
|
|
|
|
piVar5 = (int *)(param_2 + 0x580);
|
|
|
|
// if driver is visible
|
|
if ((*(uint *)(iVar4 + 0x28) & 0x80) == 0)
|
|
{
|
|
// height + 0x100
|
|
iVar3 = *(int *)(param_2 + 0x2d8) + 0x100;
|
|
|
|
*(int *)(param_2 + 0x590) = iVar3;
|
|
if (iVar3 < *(int *)(param_2 + 0x588)) {
|
|
*(int *)(param_2 + 0x590) = *(int *)(param_2 + 0x588);
|
|
}
|
|
|
|
// if driver is visible
|
|
if ((*(uint *)(iVar4 + 0x28) & 0x80) == 0)
|
|
{
|
|
// stop particle spawning
|
|
*(int *)(param_2 + 0x58c) = *(int *)(param_2 + 0x58c) + -100;
|
|
}
|
|
|
|
// add dust puff
|
|
FUN_80068644(param_2,piVar5);
|
|
}
|
|
|
|
// timer
|
|
iVar3 = *piVar5;
|
|
*piVar5 = iVar3 + 0x1a;
|
|
|
|
// timer < 801
|
|
if (iVar3 + 0x1a < 0x321)
|
|
{
|
|
// interpolate until scale is [0x12c0, 0x960, 0x12c0],
|
|
// car is wide and short
|
|
|
|
// Interpolate scale by speed
|
|
uVar1 = FUN_80058f54((int)*(short *)(iVar4 + 0x1c),0x78,0x12c0);
|
|
*(undefined2 *)(iVar4 + 0x1c) = uVar1;
|
|
|
|
// Interpolate scale by speed
|
|
uVar1 = FUN_80058f54((int)*(short *)(iVar4 + 0x1e),0x78,0x960);
|
|
*(undefined2 *)(iVar4 + 0x1e) = uVar1;
|
|
|
|
// Interpolate scale by speed
|
|
uVar1 = FUN_80058f54((int)*(short *)(iVar4 + 0x20),0x78,0x12c0);
|
|
*(undefined2 *)(iVar4 + 0x20) = uVar1;
|
|
|
|
iVar4 = *(int *)(param_2 + 0x2d8) + 0x800;
|
|
if (*(int *)(param_2 + 0x2d0) + 0x8000 <= *(int *)(param_2 + 0x2d8)) goto LAB_80068db0;
|
|
}
|
|
else
|
|
{
|
|
// cap to 800
|
|
*piVar5 = 800;
|
|
|
|
*(undefined *)(param_2 + 0x4fe) = 2;
|
|
|
|
// interpolate until scale is [0, 24000, 0],
|
|
// car is tall and thin
|
|
|
|
// Interpolate scale by speed
|
|
uVar1 = FUN_80058f54((int)*(short *)(iVar4 + 0x1c),600,0);
|
|
*(undefined2 *)(iVar4 + 0x1c) = uVar1;
|
|
|
|
// Interpolate scale by speed
|
|
uVar1 = FUN_80058f54((int)*(short *)(iVar4 + 0x1e),0xc80,24000);
|
|
*(undefined2 *)(iVar4 + 0x1e) = uVar1;
|
|
|
|
// Interpolate scale by speed
|
|
uVar1 = FUN_80058f54((int)*(short *)(iVar4 + 0x20),600,0);
|
|
*(undefined2 *)(iVar4 + 0x20) = uVar1;
|
|
|
|
// if scale shrinks to zero
|
|
if (*(short *)(iVar4 + 0x1c) == 0)
|
|
{
|
|
// if car is visible
|
|
if ((*(uint *)(iVar4 + 0x28) & 0x80) == 0)
|
|
{
|
|
// position above kart
|
|
local_18 = (undefined2)((uint)*(undefined4 *)(param_2 + 0x2d4) >> 8);
|
|
local_16 = (short)((uint)*(undefined4 *)(param_2 + 0x588) >> 8) + 0x40;
|
|
local_14 = (undefined2)((uint)*(undefined4 *)(param_2 + 0x2dc) >> 8);
|
|
|
|
// FLARE_Init
|
|
FUN_80025138(&local_18);
|
|
}
|
|
|
|
// make invisible
|
|
*(uint *)(iVar4 + 0x28) = *(uint *)(iVar4 + 0x28) | 0x80;
|
|
|
|
goto LAB_80068db0;
|
|
}
|
|
|
|
iVar4 = *(int *)(param_2 + 0x584) + -0x1800;
|
|
*(int *)(param_2 + 0x584) = iVar4;
|
|
|
|
iVar4 = *(int *)(param_2 + 0x2d8) + iVar4;
|
|
}
|
|
*(int *)(param_2 + 0x2d8) = iVar4;
|
|
LAB_80068db0:
|
|
|
|
// drift angle = ((drift angle + warp timer + 0x800) & 0xfff) - 0x800
|
|
sVar2 = (*(short *)(param_2 + 0x3c6) + *(short *)piVar5 + 0x800U & 0xfff) - 0x800;
|
|
*(short *)(param_2 + 0x3c6) = sVar2;
|
|
|
|
// cameraRotY = ??? + kart angle + drift angle
|
|
*(short *)(param_2 + 0x2ee) = *(short *)(param_2 + 0x3d4) + *(short *)(param_2 + 0x39a) + sVar2;
|
|
|
|
// driver is warping
|
|
*(uint *)(param_2 + 0x2c8) = *(uint *)(param_2 + 0x2c8) | 0x4000;
|
|
return;
|
|
}
|
|
|
|
|
|
// VehStuckProc_Warp_Init
|
|
// param1 = thread, param2 = driver
|
|
void FUN_80068e04(undefined4 param_1,int param_2)
|
|
|
|
{
|
|
int iVar1;
|
|
|
|
// If you are not in a warp pad
|
|
if (*(char *)(param_2 + 0x376) != '\n')
|
|
{
|
|
*(undefined4 *)(param_2 + 0x580) = 0x3c;
|
|
*(undefined4 *)(param_2 + 0x584) = 0;
|
|
*(undefined4 *)(param_2 + 0x588) = *(undefined4 *)(param_2 + 0x2d0);
|
|
|
|
// OtherFX_Play
|
|
FUN_80028468(0x97,1);
|
|
|
|
// OtherFX_Stop1 (three sounds)
|
|
FUN_80028808(*(undefined4 *)(param_2 + 0x304));
|
|
*(undefined4 *)(param_2 + 0x304) = 0;
|
|
FUN_80028808(*(undefined4 *)(param_2 + 0x308));
|
|
*(undefined4 *)(param_2 + 0x308) = 0;
|
|
FUN_80028808(*(undefined4 *)(param_2 + 0x300));
|
|
*(undefined4 *)(param_2 + 0x300) = 0;
|
|
|
|
// engineID from metadata, given characterID
|
|
FUN_80028b54((uint)*(byte *)(param_2 + 0x4a) +
|
|
*(int *)(&DAT_80086d90 +
|
|
(int)(short)(&DAT_80086e84)[*(byte *)(param_2 + 0x4a)] * 0x10) * 4 & 0xffff
|
|
);
|
|
|
|
// driver -> instSelf
|
|
iVar1 = *(int *)(param_2 + 0x1c);
|
|
|
|
// instance flags, now reflective
|
|
*(uint *)(iVar1 + 0x28) = *(uint *)(iVar1 + 0x28) | 0x4000;
|
|
|
|
// vertical line for split or reflection
|
|
*(undefined2 *)(iVar1 + 0x56) = (short)((uint)*(undefined4 *)(param_2 + 0x2d0) >> 8);
|
|
|
|
// CameraDC, freecam mode
|
|
*(undefined2 *)(PTR_DAT_8008d2ac + (uint)*(byte *)(param_2 + 0x4a) * 0xdc + 0x1532) = 3;
|
|
|
|
*(undefined4 *)(param_2 + 0x60) = 0x80062a2c; // OnAudio
|
|
|
|
// eventually calls AddDustPuff
|
|
*(undefined4 *)(param_2 + 100) = 0x80068be8; // OnPhysAngular
|
|
|
|
*(undefined4 *)(param_2 + 0x7c) = 0x8005ee34; // VehPhysForce_TranslateMatrix -- move position to instance matrix
|
|
|
|
*(undefined4 *)(param_2 + 0x80) = 0x8005b178; // VehFrameProc_Driving
|
|
|
|
// you are now in a warp pad
|
|
*(undefined *)(param_2 + 0x376) = 10;
|
|
|
|
*(undefined2 *)(param_2 + 0x38c) = 0;
|
|
*(undefined2 *)(param_2 + 0x38e) = 0;
|
|
|
|
*(undefined4 *)(param_2 + 0x54) = 0; // OnInit
|
|
*(undefined4 *)(param_2 + 0x58) = 0; // OnUpdate
|
|
*(undefined4 *)(param_2 + 0x5c) = 0; // OnPhysLinear -- disable input, timers, and effects
|
|
|
|
*(undefined4 *)(param_2 + 0x68) = 0;
|
|
*(undefined4 *)(param_2 + 0x6c) = 0; // COLL_StartSearch_NearPlayer
|
|
*(undefined4 *)(param_2 + 0x70) = 0; // VehPhysForce_CollideDrivers
|
|
*(undefined4 *)(param_2 + 0x74) = 0; // COLL_StartSearch_Player
|
|
*(undefined4 *)(param_2 + 0x78) = 0; // cant move anymore
|
|
|
|
// VehEmitter_DriverMain
|
|
*(undefined4 *)(param_2 + 0x84) = 0x80059a18;
|
|
|
|
// driver is warping
|
|
*(uint *)(param_2 + 0x2c8) = *(uint *)(param_2 + 0x2c8) | 0x4000;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// VehTalkMask_ThTick
|
|
void FUN_80068f90(int param_1)
|
|
|
|
{
|
|
undefined *puVar1;
|
|
undefined2 uVar2;
|
|
uint uVar3;
|
|
int iVar4;
|
|
int iVar5;
|
|
int iVar6;
|
|
int iVar7;
|
|
int iVar8;
|
|
|
|
puVar1 = PTR_DAT_8008d2ac;
|
|
|
|
// get object attached to thread
|
|
iVar8 = *(int *)(param_1 + 0x30);
|
|
|
|
// get instance attached to thread
|
|
iVar7 = *(int *)(param_1 + 0x34);
|
|
|
|
iVar4 = 0x2000;
|
|
|
|
// if mask model is nullptr
|
|
if (DAT_8008d0f0 == 0) {
|
|
iVar4 = 0x1000;
|
|
|
|
// Check if P1 is valid
|
|
if (*(int *)(PTR_DAT_8008d2ac + 0x24ec) != 0)
|
|
{
|
|
// VehPickupItem_MaskBoolGoodGuy
|
|
uVar3 = FUN_80064be4();
|
|
|
|
// If you use Uka mask,
|
|
// uka model
|
|
iVar4 = 0xe8;
|
|
|
|
// If you use Aku mask
|
|
if ((uVar3 & 0xffff) != 0)
|
|
{
|
|
// aku model
|
|
iVar4 = 0xe4;
|
|
}
|
|
|
|
// set instance's model pointer
|
|
*(undefined4 *)(iVar7 + 0x18) = *(undefined4 *)(puVar1 + iVar4 + 0x2160);
|
|
|
|
iVar4 = 0x1000;
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
// set model of talking mask
|
|
*(int *)(iVar7 + 0x18) = DAT_8008d0f0;
|
|
}
|
|
|
|
// max value in some SPU data
|
|
DAT_8008d9f8 = DAT_8008d6f4;
|
|
|
|
uVar2 = (undefined2)(*(short *)(iVar8 + 4) * iVar4 >> 0xc);
|
|
|
|
// scale
|
|
*(undefined2 *)(iVar7 + 0x20) = uVar2;
|
|
*(undefined2 *)(iVar7 + 0x1e) = uVar2;
|
|
*(undefined2 *)(iVar7 + 0x1c) = uVar2;
|
|
|
|
// number of animFrames
|
|
iVar8 = FUN_8005b0f4(iVar7,0);
|
|
|
|
// multiply by 7
|
|
iVar4 = DAT_8008d9f8 * 7;
|
|
|
|
if (iVar4 < 0) {
|
|
iVar4 = iVar4 + 0x3fff;
|
|
}
|
|
|
|
iVar4 = iVar4 >> 0xe;
|
|
|
|
if (DAT_8008d9fc < iVar4) {
|
|
DAT_8008d9fc = iVar4;
|
|
}
|
|
|
|
iVar6 = iVar4;
|
|
if (iVar4 < 2) {
|
|
iVar6 = 0;
|
|
}
|
|
if (iVar4 < 4)
|
|
{
|
|
// animFrame
|
|
iVar5 = (int)*(short *)(iVar7 + 0x54);
|
|
}
|
|
|
|
else
|
|
{
|
|
// animFrame
|
|
iVar5 = (int)*(short *)(iVar7 + 0x54);
|
|
|
|
iVar4 = iVar5 - iVar6;
|
|
|
|
if (iVar4 < 0) {
|
|
iVar4 = -iVar4;
|
|
}
|
|
|
|
if (3 < iVar4)
|
|
{
|
|
// animFrame
|
|
*(undefined2 *)(iVar7 + 0x54) = (short)iVar6;
|
|
|
|
goto LAB_800690dc;
|
|
}
|
|
}
|
|
|
|
// EngineSound_VolumeAdjust
|
|
uVar2 = FUN_8002fc28(iVar6,iVar5,1);
|
|
|
|
// animFrame
|
|
*(undefined2 *)(iVar7 + 0x54) = uVar2;
|
|
|
|
LAB_800690dc:
|
|
|
|
// animFrame
|
|
iVar4 = (int)*(short *)(iVar7 + 0x54) - iVar6;
|
|
|
|
if (iVar4 < 0) {
|
|
iVar4 = -iVar4;
|
|
}
|
|
|
|
if (iVar4 < 6)
|
|
{
|
|
// EngineSound_VolumeAdjust
|
|
uVar2 = FUN_8002fc28(iVar6,(int)*(short *)(iVar7 + 0x54),1);
|
|
|
|
// animFrame
|
|
*(undefined2 *)(iVar7 + 0x54) = uVar2;
|
|
}
|
|
else
|
|
{
|
|
// animFrame
|
|
*(undefined2 *)(iVar7 + 0x54) = (short)iVar6;
|
|
}
|
|
|
|
// animation frame goes back and forth
|
|
// 0x00: mouth close
|
|
// 0x0C: mouth open
|
|
|
|
// if frame is less than zero, set to zero
|
|
if ((int)*(short *)(iVar7 + 0x54) < 0) {
|
|
*(undefined2 *)(iVar7 + 0x54) = 0;
|
|
}
|
|
|
|
// if frame is positive
|
|
else
|
|
{
|
|
// if animation frame goes beyond number of frames
|
|
if (iVar8 + -1 < (int)*(short *)(iVar7 + 0x54))
|
|
{
|
|
// set animation frame to last frame
|
|
*(undefined2 *)(iVar7 + 0x54) = (short)(iVar8 + -1);
|
|
}
|
|
}
|
|
|
|
// If mask should disappear
|
|
if (DAT_8008da00 != '\0')
|
|
{
|
|
// dont need this variable anymore,
|
|
// so set it from one to zero
|
|
DAT_8008da00 = '\0';
|
|
|
|
// 0x800 = this thread needs to be deleted
|
|
*(uint *)(param_1 + 0x1c) = *(uint *)(param_1 + 0x1c) | 0x800;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// VehTalkMask_Init
|
|
void FUN_80069178(void)
|
|
|
|
{
|
|
int iVar1;
|
|
|
|
// mask is now talking (I think)
|
|
DAT_8008d65c = 1;
|
|
|
|
// talking mask does not
|
|
// need to go away
|
|
DAT_8008da00 = 0;
|
|
|
|
// DAT_8008d660
|
|
// "head"
|
|
|
|
// 0x39 = aku aku model pointer
|
|
// it changes in FUN_80068f90
|
|
|
|
// INSTANCE_BirthWithThread
|
|
// 0x300 flag = SmallStackPool
|
|
// 0xe = "aku aku" thread bucket
|
|
// 0x6 = sizeof(struct MaskHint)
|
|
iVar1 = FUN_800309a4(0x39,&DAT_8008d660,0x300,0xe,FUN_80068f90,6,0);
|
|
|
|
// get thread from instance
|
|
iVar1 = *(int *)(iVar1 + 0x6c);
|
|
|
|
// set funcThDestroy to remove instance from instance pool
|
|
*(undefined4 *)(iVar1 + 0x24) = 0x80041dfc;
|
|
|
|
// object -> 4
|
|
*(undefined2 *)(*(int *)(iVar1 + 0x30) + 4) = 0;
|
|
|
|
return instance;
|
|
}
|
|
|
|
|
|
// VehTalkMask_PlayXA
|
|
void FUN_800691e4(undefined4 param_1,short param_2)
|
|
|
|
{
|
|
uint uVar1;
|
|
|
|
if (
|
|
// If Player Structure pointer is not nullptr
|
|
(*(int *)(PTR_DAT_8008d2ac + 0x24ec) != 0) &&
|
|
(
|
|
// VehPickupItem_MaskBoolGoodGuy
|
|
uVar1 = FUN_80064be4(),
|
|
|
|
// if player uses uka
|
|
(uVar1 & 0xffff) == 0
|
|
)
|
|
)
|
|
{
|
|
// if you use uka, increment parameter
|
|
param_2 = param_2 + 0x1f;
|
|
}
|
|
|
|
// if you use aku, leave parameter alone
|
|
|
|
// CDSYS_XAPlay(CDSYS_XA_TYPE_EXTRA, (int)param_2);
|
|
FUN_8001cdb4(1,(int)param_2);
|
|
|
|
return;
|
|
}
|
|
|
|
// VehTalkMask_boolNoXA
|
|
bool FUN_8006924c(void)
|
|
|
|
{
|
|
return DAT_8008d708 == 0;
|
|
}
|
|
|
|
// VehTalkMask_End
|
|
void FUN_8006925c(void)
|
|
|
|
{
|
|
// CDSYS_XAPauseRequest
|
|
FUN_8001cf98();
|
|
|
|
// sdata->boolIsMaskThreadAlive
|
|
DAT_8008d65c = 0;
|
|
|
|
// sdata->talkMask_boolDead
|
|
DAT_8008da00 = 1;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
// VehTurbo_ProcessBucket
|
|
void FUN_80069284(int param_1)
|
|
|
|
{
|
|
undefined2 uVar1;
|
|
undefined *puVar2;
|
|
undefined *puVar3;
|
|
int iVar4;
|
|
undefined4 uVar5;
|
|
int iVar6;
|
|
int iVar7;
|
|
int iVar8;
|
|
|
|
puVar2 = PTR_DAT_8008d2ac;
|
|
|
|
// if first thread is valid
|
|
if (param_1 != 0)
|
|
{
|
|
// loop through all threads
|
|
do
|
|
{
|
|
puVar3 = PTR_DAT_8008d2ac;
|
|
|
|
// get instance from thread
|
|
iVar6 = *(int *)(param_1 + 0x34);
|
|
|
|
// get object from thread
|
|
iVar7 = **(int **)(param_1 + 0x30);
|
|
|
|
// object -> driver -> instSelf
|
|
iVar4 = *(int *)((*(int **)(param_1 + 0x30))[1] + 0x1c);
|
|
|
|
iVar8 = 0;
|
|
|
|
// numPlyrCurrGame is not zero
|
|
if (puVar2[0x1ca8] != '\0')
|
|
{
|
|
// each InstDrawPerPlayer
|
|
// for iVar8 = 0; iVar8 < numPlyrCurrGame; iVar8++
|
|
do
|
|
{
|
|
// if pushBuffer does not exist ?
|
|
// judging by 0x28 being copied to 0xb8 ?
|
|
if ((*(uint *)(iVar4 + 0xb8) & 0x100) == 0)
|
|
{
|
|
// flags
|
|
*(uint *)(iVar7 + 0xb8) =
|
|
*(uint *)(iVar7 + 0xb8) & (*(uint *)(iVar4 + 0xb8) | 0xffffffbf);
|
|
*(uint *)(iVar6 + 0xb8) =
|
|
*(uint *)(iVar6 + 0xb8) & (*(uint *)(iVar4 + 0xb8) | 0xffffffbf);
|
|
|
|
uVar5 = *(undefined4 *)(iVar4 + 0xe4);
|
|
*(undefined4 *)(iVar6 + 0xe4) = uVar5;
|
|
*(undefined4 *)(iVar7 + 0xe4) = uVar5;
|
|
uVar5 = *(undefined4 *)(iVar4 + 0xe8);
|
|
*(undefined4 *)(iVar6 + 0xe8) = uVar5;
|
|
*(undefined4 *)(iVar7 + 0xe8) = uVar5;
|
|
uVar1 = *(undefined2 *)(iVar4 + 0xdc);
|
|
*(undefined2 *)(iVar6 + 0xdc) = uVar1;
|
|
*(undefined2 *)(iVar7 + 0xdc) = uVar1;
|
|
uVar1 = *(undefined2 *)(iVar4 + 0xde);
|
|
*(undefined2 *)(iVar6 + 0xde) = uVar1;
|
|
*(undefined2 *)(iVar7 + 0xde) = uVar1;
|
|
}
|
|
|
|
// InstDrawPerPlayer
|
|
iVar6 = iVar6 + 0x88;
|
|
iVar7 = iVar7 + 0x88;
|
|
iVar8 = iVar8 + 1;
|
|
iVar4 = iVar4 + 0x88;
|
|
|
|
} while (iVar8 < (int)(uint)(byte)puVar3[0x1ca8]);
|
|
}
|
|
|
|
// go to next thread
|
|
|
|
// thread = thread->sibling
|
|
param_1 = *(int *)(param_1 + 0x10);
|
|
|
|
} while (param_1 != 0);
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
// VehTurbo_ThDestroy
|
|
void FUN_80069370(int param_1)
|
|
|
|
{
|
|
int iVar1;
|
|
undefined4 *puVar2;
|
|
|
|
// thread -> object
|
|
puVar2 = *(undefined4 **)(param_1 + 0x30);
|
|
|
|
// get Driver object from Turbo object
|
|
iVar1 = puVar2[1];
|
|
|
|
// remove flags for boosting
|
|
*(uint *)(iVar1 + 0x2c8) = *(uint *)(iVar1 + 0x2c8) & 0xfffffdff;
|
|
|
|
// INSTANCE_Death
|
|
FUN_80030aa8(*puVar2);
|
|
FUN_80030aa8(*(undefined4 *)(param_1 + 0x34));
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
// VehTurbo_ThTick
|
|
void FUN_800693c8(int param_1)
|
|
|
|
{
|
|
char cVar1;
|
|
short sVar2;
|
|
ushort uVar3;
|
|
undefined *puVar4;
|
|
uint uVar5;
|
|
int iVar6;
|
|
int iVar7;
|
|
undefined4 uVar8;
|
|
int *piVar9;
|
|
int iVar10;
|
|
int iVar11;
|
|
int iVar12;
|
|
|
|
// get object attached to thread
|
|
piVar9 = *(int **)(param_1 + 0x30);
|
|
|
|
// turbo -> driver
|
|
iVar12 = piVar9[1];
|
|
|
|
// get instance
|
|
iVar11 = *(int *)(param_1 + 0x34);
|
|
|
|
// driver -> instSelf
|
|
iVar10 = *(int *)(iVar12 + 0x1c);
|
|
|
|
do {
|
|
if (
|
|
(
|
|
// if not burnt
|
|
(*(short *)(iVar12 + 0x402) == 0) &&
|
|
|
|
// if alpha of turbo is zero
|
|
(*(short *)(iVar11 + 0x22) == 0)) &&
|
|
|
|
// instance -> thread -> modelID == DYNAMIC_GHOST
|
|
(*(short *)(*(int *)(iVar10 + 0x6c) + 0x44) != 0x4b)
|
|
)
|
|
{
|
|
// cut driverInst transparency in half
|
|
*(ushort *)(iVar10 + 0x22) = *(ushort *)(iVar10 + 0x22) >> 1;
|
|
}
|
|
|
|
// if instance is not split by water
|
|
if ((*(uint *)(iVar10 + 0x28) & 0x2000) == 0)
|
|
{
|
|
// instance flags
|
|
*(uint *)(iVar11 + 0x28) = *(uint *)(iVar11 + 0x28) & 0xffffdfff;
|
|
*(uint *)(*piVar9 + 0x28) = *(uint *)(*piVar9 + 0x28) & 0xffffdfff;
|
|
}
|
|
|
|
// if instance is split by water
|
|
else
|
|
{
|
|
// turbos are now split by water, set vertical split height
|
|
*(uint *)(iVar11 + 0x28) = *(uint *)(iVar11 + 0x28) | 0x2000;
|
|
*(undefined2 *)(iVar11 + 0x56) = *(undefined2 *)(iVar10 + 0x56);
|
|
*(uint *)(*piVar9 + 0x28) = *(uint *)(*piVar9 + 0x28) | 0x2000;
|
|
*(undefined2 *)(*piVar9 + 0x56) = *(undefined2 *)(iVar10 + 0x56);
|
|
}
|
|
|
|
// if driver instance is not reflective
|
|
if ((*(uint *)(iVar10 + 0x28) & 0x4000) == 0)
|
|
{
|
|
// remove reflection from turbo instances
|
|
*(uint *)(iVar11 + 0x28) = *(uint *)(iVar11 + 0x28) & 0xffffbfff;
|
|
*(uint *)(*piVar9 + 0x28) = *(uint *)(*piVar9 + 0x28) & 0xffffbfff;
|
|
}
|
|
|
|
// if driver instance is reflective
|
|
else
|
|
{
|
|
// make turbo instances reflective
|
|
// copy reflection height axis to instance
|
|
*(uint *)(iVar11 + 0x28) = *(uint *)(iVar11 + 0x28) | 0x4000;
|
|
*(undefined2 *)(iVar11 + 0x56) = *(undefined2 *)(iVar10 + 0x56);
|
|
*(uint *)(*piVar9 + 0x28) = *(uint *)(*piVar9 + 0x28) | 0x4000;
|
|
*(undefined2 *)(*piVar9 + 0x56) = *(undefined2 *)(iVar10 + 0x56);
|
|
}
|
|
|
|
// matrix from instance
|
|
gte_SetRotMatrix(iVar10 + 0x30);
|
|
gte_SetTransMatrix(iVar10 + 0x30);
|
|
|
|
iVar6 = (int)*(short *)((int)piVar9 + 10);
|
|
iVar7 = iVar6;
|
|
if (8 < iVar6) {
|
|
iVar7 = 8;
|
|
}
|
|
if (iVar6 < 4) {
|
|
iVar7 = 4;
|
|
}
|
|
|
|
// matrix of first turbo instance
|
|
*(undefined2 *)(iVar11 + 0x30) = (short)(*(short *)(iVar10 + 0x30) * iVar7 >> 3);
|
|
*(undefined2 *)(iVar11 + 0x32) = (short)(*(short *)(iVar10 + 0x32) * iVar7 >> 3);
|
|
*(undefined2 *)(iVar11 + 0x34) = (short)(*(short *)(iVar10 + 0x34) * iVar7 >> 3);
|
|
*(undefined2 *)(iVar11 + 0x36) = (short)(*(short *)(iVar10 + 0x36) * iVar7 >> 3);
|
|
*(undefined2 *)(iVar11 + 0x38) = (short)(*(short *)(iVar10 + 0x38) * iVar7 >> 3);
|
|
*(undefined2 *)(iVar11 + 0x3a) = (short)(*(short *)(iVar10 + 0x3a) * iVar7 >> 3);
|
|
*(undefined2 *)(iVar11 + 0x3c) = (short)(*(short *)(iVar10 + 0x3c) * iVar7 >> 3);
|
|
*(undefined2 *)(iVar11 + 0x3e) = (short)(*(short *)(iVar10 + 0x3e) * iVar7 >> 3);
|
|
*(undefined2 *)(iVar11 + 0x40) = (short)(*(short *)(iVar10 + 0x40) * iVar7 >> 3);
|
|
|
|
// driver -> instSelf
|
|
iVar6 = *(int *)(iVar12 + 0x1c);
|
|
|
|
gte_ldVXY0(*(short *)(iVar6 + 0x1c) * 9 >> 0xb & 0xffffU |
|
|
(*(short *)(iVar6 + 0x1e) * 3 >> 8) << 0x10);
|
|
gte_ldVZ0(*(short *)(iVar6 + 0x20) * -0x34 >> 0xc);
|
|
gte_rt();
|
|
|
|
// set translation vector
|
|
gte_stlvl((VECTOR *)(iVar11 + 0x44));
|
|
|
|
// matrix of second turbo instance, negate X axis
|
|
*(undefined2 *)(*piVar9 + 0x30) = (short)(-(int)*(short *)(iVar10 + 0x30) * iVar7 >> 3);
|
|
*(undefined2 *)(*piVar9 + 0x32) = (short)(*(short *)(iVar10 + 0x32) * iVar7 >> 3);
|
|
*(undefined2 *)(*piVar9 + 0x34) = (short)(*(short *)(iVar10 + 0x34) * iVar7 >> 3);
|
|
*(undefined2 *)(*piVar9 + 0x36) = (short)(-(int)*(short *)(iVar10 + 0x36) * iVar7 >> 3);
|
|
*(undefined2 *)(*piVar9 + 0x38) = (short)(*(short *)(iVar10 + 0x38) * iVar7 >> 3);
|
|
*(undefined2 *)(*piVar9 + 0x3a) = (short)(*(short *)(iVar10 + 0x3a) * iVar7 >> 3);
|
|
*(undefined2 *)(*piVar9 + 0x3c) = (short)(-(int)*(short *)(iVar10 + 0x3c) * iVar7 >> 3);
|
|
*(undefined2 *)(*piVar9 + 0x3e) = (short)(*(short *)(iVar10 + 0x3e) * iVar7 >> 3);
|
|
*(undefined2 *)(*piVar9 + 0x40) = (short)(*(short *)(iVar10 + 0x40) * iVar7 >> 3);
|
|
|
|
// driver -> instSelf
|
|
iVar7 = *(int *)(iVar12 + 0x1c);
|
|
|
|
gte_ldVXY0(*(short *)(iVar7 + 0x1c) * -0x12 >> 0xc & 0xffffU |
|
|
(*(short *)(iVar7 + 0x1e) * 3 >> 8) << 0x10);
|
|
gte_ldVZ0(*(short *)(iVar7 + 0x20) * -0x34 >> 0xc);
|
|
gte_rt();
|
|
|
|
// set translation vector
|
|
gte_stlvl((VECTOR *)(*piVar9 + 0x44));
|
|
|
|
// elapsed milliseconds per frame, ~32
|
|
iVar7 = (uint)*(ushort *)((int)piVar9 + 0xe) - (uint)*(ushort *)(PTR_DAT_8008d2ac + 0x1d04);
|
|
|
|
*(undefined2 *)((int)piVar9 + 0xe) = (short)iVar7;
|
|
if (iVar7 * 0x10000 < 0) {
|
|
*(undefined2 *)((int)piVar9 + 0xe) = 0;
|
|
}
|
|
|
|
if (*(short *)((int)piVar9 + 0xe) == 0)
|
|
{
|
|
// make visible
|
|
*(uint *)(iVar11 + 0x28) = *(uint *)(iVar11 + 0x28) & 0xffffff7f;
|
|
*(uint *)(*piVar9 + 0x28) = *(uint *)(*piVar9 + 0x28) & 0xffffff7f;
|
|
}
|
|
|
|
if (*(ushort *)(iVar11 + 0x22) < 2500)
|
|
{
|
|
// GAMEPAD_ShockFreq
|
|
FUN_80026440(iVar12,4,4);
|
|
}
|
|
|
|
puVar4 = PTR_DAT_8008d2ac;
|
|
|
|
// set new model pointer, one of seven
|
|
*(undefined4 *)(iVar11 + 0x18) =
|
|
*(undefined4 *)(PTR_DAT_8008d2ac + ((int)*(short *)(piVar9 + 2) + 0x2c) * 4 + 0x2160);
|
|
|
|
// set new model pointer, one of seven
|
|
*(undefined4 *)(*piVar9 + 0x18) =
|
|
*(undefined4 *)(puVar4 + (((int)*(short *)(piVar9 + 2) + 3U & 7) + 0x2c) * 4 + 0x2160);
|
|
|
|
// increment frame index
|
|
sVar2 = *(short *)(piVar9 + 2);
|
|
*(short *)(piVar9 + 2) = sVar2 + 1;
|
|
|
|
// if gone past seven frames of fire
|
|
if (7 < (short)(sVar2 + 1))
|
|
{
|
|
// back to first frame of fire
|
|
*(undefined2 *)(piVar9 + 2) = 0;
|
|
}
|
|
|
|
if ('\0' < *(char *)(piVar9 + 3)) {
|
|
*(char *)(piVar9 + 3) = *(char *)(piVar9 + 3) + -1;
|
|
}
|
|
|
|
// instance -> thread -> modelIndex == "player" of any kind
|
|
if (*(short *)(*(int *)(iVar10 + 0x6c) + 0x44) == 0x18) {
|
|
iVar7 = 0x100 - (uint)(*(ushort *)(iVar11 + 0x22) >> 4);
|
|
if (iVar7 < 0) {
|
|
iVar7 = 0;
|
|
}
|
|
else {
|
|
if (0x82 < iVar7) {
|
|
iVar7 = 0x82;
|
|
}
|
|
}
|
|
uVar5 = (uint)*(byte *)((int)piVar9 + 0xd) + 0x10;
|
|
if ((int)uVar5 < 0) {
|
|
uVar5 = 0;
|
|
}
|
|
else {
|
|
if (0x80 < uVar5) {
|
|
uVar5 = 0x80;
|
|
}
|
|
}
|
|
|
|
// distort
|
|
uVar5 = uVar5 << 8;
|
|
|
|
// if echo is required
|
|
if ((*(uint *)(iVar12 + 0x2c8) & 0x10000) != 0)
|
|
{
|
|
// add echo
|
|
uVar5 = uVar5 | 0x1000000;
|
|
}
|
|
|
|
// driver audio
|
|
FUN_8002e690(iVar12 + 0x30c,0xe,iVar7 << 0x10 | uVar5 | 0x80);
|
|
|
|
if (*(byte *)((int)piVar9 + 0xd) < 0xc0) {
|
|
*(char *)((int)piVar9 + 0xd) = *(byte *)((int)piVar9 + 0xd) + 1;
|
|
}
|
|
}
|
|
|
|
if (
|
|
// if this is a ghost
|
|
(*(short *)(*(int *)(iVar10 + 0x6c) + 0x44) == 0x4b) ||
|
|
|
|
// kart state
|
|
(((cVar1 = *(char *)(iVar12 + 0x376),
|
|
|
|
// if not being mask grabbed, not crashing, not being warped
|
|
cVar1 != '\x05' && (cVar1 != '\x01')) && (cVar1 != '\n')))
|
|
)
|
|
{
|
|
// if reserves are nearing zero
|
|
if ((*(short *)(iVar12 + 0x3e2) < 0x10) || (*(char *)(piVar9 + 3) == '\0'))
|
|
{
|
|
// get turboInst alpha
|
|
uVar3 = *(ushort *)(iVar11 + 0x22);
|
|
|
|
// if fully transparent, skip lines
|
|
if (0xfff < uVar3) goto LAB_80069b50;
|
|
|
|
if (*(char *)(piVar9 + 3) == '\0')
|
|
{
|
|
// increase transparency
|
|
*(short *)(iVar11 + 0x22) = uVar3 + 0x100;
|
|
*(short *)(*piVar9 + 0x22) = *(short *)(*piVar9 + 0x22) + 0x100;
|
|
}
|
|
else
|
|
{
|
|
// increase transparency
|
|
*(short *)(iVar11 + 0x22) = uVar3 + 0x40;
|
|
*(short *)(*piVar9 + 0x22) = *(short *)(*piVar9 + 0x22) + 0x40;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// if scale is big, skip lines
|
|
if (0xfff < *(ushort *)(iVar11 + 0x22)) goto LAB_80069b50;
|
|
}
|
|
}
|
|
|
|
// if not a ghost, and
|
|
// kart state is mask grab, crashed, or warped
|
|
else
|
|
{
|
|
// restore backup of alpha
|
|
*(undefined2 *)(iVar10 + 0x22) = *(undefined2 *)(iVar12 + 0x508);
|
|
LAB_80069b50:
|
|
|
|
// instance -> thread -> modelIndex == "player" of any kind
|
|
if (*(short *)(*(int *)(iVar10 + 0x6c) + 0x44) == 0x18)
|
|
{
|
|
// volume, distortion, left/right
|
|
uVar8 = 0x8080;
|
|
|
|
// if echo is required
|
|
if ((*(uint *)(iVar12 + 0x2c8) & 0x10000) != 0)
|
|
{
|
|
// add echo, volume, distortion, left/right
|
|
uVar8 = 0x1008080;
|
|
}
|
|
|
|
// driver audio
|
|
FUN_8002e690(iVar12 + 0x30c,0xffffffff,uVar8);
|
|
}
|
|
|
|
// 0x800 = this thread needs to be deleted
|
|
*(uint *)(param_1 + 0x1c) = *(uint *)(param_1 + 0x1c) | 0x800;
|
|
}
|
|
|
|
// this skips $RA backup/restore, faster than JR $RA
|
|
FUN_80071694(param_1);
|
|
|
|
} while( true );
|
|
}
|