From 6e8ee67cf66176c811ebbc5170ba0d5807c843cc Mon Sep 17 00:00:00 2001 From: Fazana <52551480+FazanaJ@users.noreply.github.com> Date: Fri, 28 Apr 2023 17:52:12 +0100 Subject: [PATCH] Adventure two 25% (#387) * identify transition bug * Document fog system * Label fogchanger attributes * and more * anti aliasing * name some object vars * block the racer inputs * Update unknown_0255E0.c * Update README.md * Update src/object_functions.c * I just did thing I guess??? * me when I realise almost all the pass through discs are just copy and pasted code. * YOU'RE PUSHING THEM?!?! bruh bruh bruh bruh * I guess I'm in the object naming rabbit hole now wow maybe I'll actually get these looking good :flushed: * i did frogs * got it * Quick fixes --- README.md | 362 ++++---- asm/non_matchings/racer/func_800452A0.s | 20 +- include/enums.h | 12 +- include/level_object_entries.h | 64 +- include/structs.h | 90 +- src/collision.h | 2 +- src/game.c | 31 +- src/game.h | 4 +- src/object_functions.c | 1112 +++++++++++++---------- src/object_functions.h | 28 +- src/objects.c | 14 +- src/objects.h | 20 + src/racer.c | 63 +- src/racer.h | 1 + src/vehicle_bluey.c | 2 +- src/vehicle_bubbler.c | 2 +- src/vehicle_rocket.c | 4 +- src/vehicle_smokey.c | 2 +- src/vehicle_tricky.c | 8 +- src/vehicle_wizpig.c | 4 +- 20 files changed, 1000 insertions(+), 845 deletions(-) diff --git a/README.md b/README.md index 720e38e2..910f2305 100644 --- a/README.md +++ b/README.md @@ -1,181 +1,181 @@ -# Diddy Kong Racing - -This repo contains a work-in-progress decompilation of Diddy Kong Racing for the N64. You will need to have a original copy of the ROM to extract the game's assets. - -Currently, only the US 1.0 version of the game is supported. US 1.1, EU 1.0, EU 1.1, and JP are not supported at this time. - - -As of April 24, 2023, this is our current score: - -    Decomp progress: 51.18% - -    Documentation progress: 24.34% - - ---- - -## Dependencies - -* `libcapstone-dev` -* `gcc`, Version 8.0 or higher -* `make`, Version 4.2 or higher -* `python3` -* `wget` - -`sudo apt install build-essential pkg-config git python3 wget libcapstone-dev` - -### binutils - -You are not required to install a binutils package, but it does speed up the initial setup if you do have it installed. - -* Ubuntu/Debian (x86): `sudo apt install binutils-mips-linux-gnu` - -## Setup / Building -1. Install the dependencies -2. Place the ROM file within the `baseroms` directory. - **a.** The name of the ROM file does not matter, but it must end with one of these extensions: `.z64`, `.v64`, `.n64`, or `.rom`. It will be detected automatically from an md5 checksum. - **b.** If you use a byte-swapped or little-endian ROM, then it will automatically be converted to a big-endian (.z64) ROM file. -3. Run `make` in the main directory. - **a.** Use the `-jN` argument to use `N` number of threads to speed up building. For example, if you have a system with 4 cores / 4 threads, you should do `make -j4`. - -### Building on MacOS -1. `brew install gcc capstone coreutils` -2. Put GNU-coreutils `bin` on path using by adding `PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH"` to your shell rcfile (or update any GNU-util usage in `Makefile` and `tools/Makefile` to use the `g`-prefixed versions). -3. Download latest `macos` build of `ido-static-recomp` from [here](https://github.com/decompals/ido-static-recomp/releases/), and add `cp` the binaries to `tools/ido-static-recomp/build5.3/out`. -4. Take a look at [this gist](https://gist.github.com/tonyspumoni/fc1b4c9217c5f2821a9fc4cbf69b51ef) to see what other updates are needed to get the build to pass, and apply them if they are relevant to your environment. You may need to add specific `-I` and `-L` flags to get things like `openssl` and `gcc-12` includes/libs included. -5. `make` from repository root should work now. - -## Modding -If you are modifying the code in the repo, then you should add `NON_MATCHING=1` to the make command. -Example: `make NON_MATCHING=1 -j4` - -The `NON_MATCHING` define will include the functions that don't exactly match one-to-one, but should be no different functionality-wise. If you do notice any bugs that occur in a `NON_MATCHING` build that are not in the vanilla game, then please file an issue describing the bug. It would be helpful if you can track down which function is causing the bug, but that is not required. - -## Style Guide - -The style guide for the project can be found here: https://docs.google.com/document/d/1euQf8nwynGcCZL1MfoMaLs-XRvx3ejjj8fIfykUZ-NQ - -If you see variables/functions/structs/etc. that doesn't follow these rules, then file an issue and we'll try to fix them. - -## Scripts - -There are some useful scripts that should be kept in mind when working on this repo. - ---- - -#### `./extract.sh ` - -This script will extract all the assets from a DKR ROM and place them into `/assets/` folder according to the config file within the `/extract-ver/` folder. The version parameter should either be `us_1.0`, `us_1.1`, `eu_1.0`, `eu_1.1`, or `jp`. - -Example: `./extract.sh us_1.0` - ---- - -#### `./diff.sh ` - -Compares the assembly output of a function from a built ROM to the base ROM. Useful for decompiling. - -Example: `./diff.sh menu_init` - ---- - -#### `./rename.sh ` - -This script will rename an existing symbol, file name, and/or folder name within the repo with a new one. - -Example: `./rename.sh D_A4001000 SP_IMEM` - ---- - -#### `./get_symbol.sh |` - -Given either a RAM address or symbol, returns its `(symbol, address)` pairing as defined in `/build/us_1.0/dkr.map`. If specified, the RAM address must be in base 16. The `0x` prefix is not required. - -Example: -``` -./get_symbol.sh 0xA4001000 -0xA4001000 = SP_IMEM - -./get_symbol.sh osCicId -0x80000310 = osCicId -``` - ---- - -#### `./score.sh` - -Prints out the current completion percentage of the decomp. You do need to have an `OK` build for this to work properly. - -The scoring is split into 2 sections: -1. Assembly to C Decompilation (Adventure One) -2. Cleanup and Documentation (Adventure Two) - -Show scores for Adventure One & Adventure Two: `./score.sh` -Show score for Adventure One only: `./score.sh -a 1` -Show score for Adventure Two only: `./score.sh -a 2` -Show top 10 files remaining: `./score.sh -t 10` - -To make progress in Adventure 2, a function must be properly named (must not start with `func_`) and also include a doxygen comment above it. - -For example: -```c -/** - * Returns 1 if Drumstick is avaliable to use, or 0 if not. - */ -s32 is_drumstick_unlocked(void) { - return gActiveMagicCodes & 2; -} -``` - - -As of April 24, 2023, this is our current score: -``` - ================================================= - ADVENTURE ONE (ASM -> C Decompilation) - ---------------- 51.18% Complete ---------------- - # Decompiled functions: 1501 - # GLOBAL_ASM remaining: 331 - # NON_MATCHING functions: 12 - # NON_EQUIVALENT WIP functions: 64 - ------------------ Game Status ------------------ - Balloons: 25/47, Keys: 3/4, Trophies: 2/5 - T.T. Amulets: 2/4, Wizpig Amulets: 2/4 - ------------------------------------------------- - We are racing in Treasure Caves. (Lap 3/3) - ================================================= - ADVENTURE TWO (Cleanup & Documentation) - ---------------- 24.34% Complete ---------------- - # Documented functions: 485 - # Undocumented remaining: 1079 - ------------------ Game Status ------------------ - Balloons: 12/47, Keys: 1/4, Trophies: 1/5 - T.T. Amulets: 1/4, Wizpig Amulets: 1/4 - ------------------------------------------------- - We are racing Taj in the Car Challenge. (Lap 1/3) - ================================================= -``` - - ---- - -## TODO list - -### Major - -What should be focused on. - -* Decompiling the non-matching asm files into matching C functions. -* Documenting variables & functions - -### Minor - -What can be done, but not essential. - -* Figuring out the formats for the assets in the /assets/ folder. -* Creating tools to modify assets - -### Future - -These features won't be complete anytime soon. - -* Add support for the other 4 versions. +# Diddy Kong Racing + +This repo contains a work-in-progress decompilation of Diddy Kong Racing for the N64. You will need to have a original copy of the ROM to extract the game's assets. + +Currently, only the US 1.0 version of the game is supported. US 1.1, EU 1.0, EU 1.1, and JP are not supported at this time. + + +As of April 24, 2023, this is our current score: + +    Decomp progress: 51.18% + +    Documentation progress: 24.34% + + +--- + +## Dependencies + +* `libcapstone-dev` +* `gcc`, Version 8.0 or higher +* `make`, Version 4.2 or higher +* `python3` +* `wget` + +`sudo apt install build-essential pkg-config git python3 wget libcapstone-dev` + +### binutils + +You are not required to install a binutils package, but it does speed up the initial setup if you do have it installed. + +* Ubuntu/Debian (x86): `sudo apt install binutils-mips-linux-gnu` + +## Setup / Building +1. Install the dependencies +2. Place the ROM file within the `baseroms` directory. + **a.** The name of the ROM file does not matter, but it must end with one of these extensions: `.z64`, `.v64`, `.n64`, or `.rom`. It will be detected automatically from an md5 checksum. + **b.** If you use a byte-swapped or little-endian ROM, then it will automatically be converted to a big-endian (.z64) ROM file. +3. Run `make` in the main directory. + **a.** Use the `-jN` argument to use `N` number of threads to speed up building. For example, if you have a system with 4 cores / 4 threads, you should do `make -j4`. + +### Building on MacOS +1. `brew install gcc capstone coreutils` +2. Put GNU-coreutils `bin` on path using by adding `PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH"` to your shell rcfile (or update any GNU-util usage in `Makefile` and `tools/Makefile` to use the `g`-prefixed versions). +3. Download latest `macos` build of `ido-static-recomp` from [here](https://github.com/decompals/ido-static-recomp/releases/), and add `cp` the binaries to `tools/ido-static-recomp/build5.3/out`. +4. Take a look at [this gist](https://gist.github.com/tonyspumoni/fc1b4c9217c5f2821a9fc4cbf69b51ef) to see what other updates are needed to get the build to pass, and apply them if they are relevant to your environment. You may need to add specific `-I` and `-L` flags to get things like `openssl` and `gcc-12` includes/libs included. +5. `make` from repository root should work now. + +## Modding +If you are modifying the code in the repo, then you should add `NON_MATCHING=1` to the make command. +Example: `make NON_MATCHING=1 -j4` + +The `NON_MATCHING` define will include the functions that don't exactly match one-to-one, but should be no different functionality-wise. If you do notice any bugs that occur in a `NON_MATCHING` build that are not in the vanilla game, then please file an issue describing the bug. It would be helpful if you can track down which function is causing the bug, but that is not required. + +## Style Guide + +The style guide for the project can be found here: https://docs.google.com/document/d/1euQf8nwynGcCZL1MfoMaLs-XRvx3ejjj8fIfykUZ-NQ + +If you see variables/functions/structs/etc. that doesn't follow these rules, then file an issue and we'll try to fix them. + +## Scripts + +There are some useful scripts that should be kept in mind when working on this repo. + +--- + +#### `./extract.sh ` + +This script will extract all the assets from a DKR ROM and place them into `/assets/` folder according to the config file within the `/extract-ver/` folder. The version parameter should either be `us_1.0`, `us_1.1`, `eu_1.0`, `eu_1.1`, or `jp`. + +Example: `./extract.sh us_1.0` + +--- + +#### `./diff.sh ` + +Compares the assembly output of a function from a built ROM to the base ROM. Useful for decompiling. + +Example: `./diff.sh menu_init` + +--- + +#### `./rename.sh ` + +This script will rename an existing symbol, file name, and/or folder name within the repo with a new one. + +Example: `./rename.sh D_A4001000 SP_IMEM` + +--- + +#### `./get_symbol.sh |` + +Given either a RAM address or symbol, returns its `(symbol, address)` pairing as defined in `/build/us_1.0/dkr.map`. If specified, the RAM address must be in base 16. The `0x` prefix is not required. + +Example: +``` +./get_symbol.sh 0xA4001000 +0xA4001000 = SP_IMEM + +./get_symbol.sh osCicId +0x80000310 = osCicId +``` + +--- + +#### `./score.sh` + +Prints out the current completion percentage of the decomp. You do need to have an `OK` build for this to work properly. + +The scoring is split into 2 sections: +1. Assembly to C Decompilation (Adventure One) +2. Cleanup and Documentation (Adventure Two) + +Show scores for Adventure One & Adventure Two: `./score.sh` +Show score for Adventure One only: `./score.sh -a 1` +Show score for Adventure Two only: `./score.sh -a 2` +Show top 10 files remaining: `./score.sh -t 10` + +To make progress in Adventure 2, a function must be properly named (must not start with `func_`) and also include a doxygen comment above it. + +For example: +```c +/** + * Returns 1 if Drumstick is avaliable to use, or 0 if not. + */ +s32 is_drumstick_unlocked(void) { + return gActiveMagicCodes & 2; +} +``` + + +As of April 24, 2023, this is our current score: +``` + ================================================= + ADVENTURE ONE (ASM -> C Decompilation) + ---------------- 51.18% Complete ---------------- + # Decompiled functions: 1501 + # GLOBAL_ASM remaining: 331 + # NON_MATCHING functions: 12 + # NON_EQUIVALENT WIP functions: 64 + ------------------ Game Status ------------------ + Balloons: 25/47, Keys: 3/4, Trophies: 2/5 + T.T. Amulets: 2/4, Wizpig Amulets: 2/4 + ------------------------------------------------- + We are racing in Treasure Caves. (Lap 3/3) + ================================================= + ADVENTURE TWO (Cleanup & Documentation) + ---------------- 25.01% Complete ---------------- + # Documented functions: 511 + # Undocumented remaining: 1053 + ------------------ Game Status ------------------ + Balloons: 12/47, Keys: 1/4, Trophies: 1/5 + T.T. Amulets: 1/4, Wizpig Amulets: 1/4 + ------------------------------------------------- + We are racing Taj in the Car Challenge. (Lap 2/3) + ================================================= +``` + + +--- + +## TODO list + +### Major + +What should be focused on. + +* Decompiling the non-matching asm files into matching C functions. +* Documenting variables & functions + +### Minor + +What can be done, but not essential. + +* Figuring out the formats for the assets in the /assets/ folder. +* Creating tools to modify assets + +### Future + +These features won't be complete anytime soon. + +* Add support for the other 4 versions. diff --git a/asm/non_matchings/racer/func_800452A0.s b/asm/non_matchings/racer/func_800452A0.s index 7a6936f7..4ef45c0d 100644 --- a/asm/non_matchings/racer/func_800452A0.s +++ b/asm/non_matchings/racer/func_800452A0.s @@ -79,11 +79,11 @@ glabel func_800452A0 /* 045F9C 8004539C 8FBE0080 */ lw $fp, 0x80($sp) /* 045FA0 800453A0 24170003 */ li $s7, 3 .L800453A4: -/* 045FA4 800453A4 3C058012 */ lui $a1, %hi(D_8011D588+3) # $a1, 0x8012 +/* 045FA4 800453A4 3C058012 */ lui $a1, %hi(gEggChallengeFlags+3) # $a1, 0x8012 /* 045FA8 800453A8 2411FFFF */ li $s1, -1 /* 045FAC 800453AC 00008025 */ move $s0, $zero /* 045FB0 800453B0 00009025 */ move $s2, $zero -/* 045FB4 800453B4 24A5D58B */ addiu $a1, %lo(D_8011D588+3) # addiu $a1, $a1, -0x2a75 +/* 045FB4 800453B4 24A5D58B */ addiu $a1, %lo(gEggChallengeFlags+3) # addiu $a1, $a1, -0x2a75 /* 045FB8 800453B8 02E02025 */ move $a0, $s7 /* 045FBC 800453BC 00009825 */ move $s3, $zero .L800453C0: @@ -168,8 +168,8 @@ glabel func_800452A0 /* 0460D8 800454D8 82A20002 */ lb $v0, 2($s5) /* 0460DC 800454DC 24010001 */ li $at, 1 /* 0460E0 800454E0 10400007 */ beqz $v0, .L80045500 -/* 0460E4 800454E4 3C0A8012 */ lui $t2, %hi(D_8011D588) # $t2, 0x8012 -/* 0460E8 800454E8 814AD588 */ lb $t2, %lo(D_8011D588)($t2) +/* 0460E4 800454E4 3C0A8012 */ lui $t2, %hi(gEggChallengeFlags) # $t2, 0x8012 +/* 0460E8 800454E8 814AD588 */ lb $t2, %lo(gEggChallengeFlags)($t2) /* 0460EC 800454EC 00000000 */ nop /* 0460F0 800454F0 314B0040 */ andi $t3, $t2, 0x40 /* 0460F4 800454F4 11600002 */ beqz $t3, .L80045500 @@ -177,8 +177,8 @@ glabel func_800452A0 /* 0460FC 800454FC 00008825 */ move $s1, $zero .L80045500: /* 046100 80045500 10410007 */ beq $v0, $at, .L80045520 -/* 046104 80045504 3C0C8012 */ lui $t4, %hi(D_8011D588+1) # $t4, 0x8012 -/* 046108 80045508 818CD589 */ lb $t4, %lo(D_8011D588+1)($t4) +/* 046104 80045504 3C0C8012 */ lui $t4, %hi(gEggChallengeFlags+1) # $t4, 0x8012 +/* 046108 80045508 818CD589 */ lb $t4, %lo(gEggChallengeFlags+1)($t4) /* 04610C 8004550C 00000000 */ nop /* 046110 80045510 318D0040 */ andi $t5, $t4, 0x40 /* 046114 80045514 11A00003 */ beqz $t5, .L80045524 @@ -188,8 +188,8 @@ glabel func_800452A0 /* 046120 80045520 24010002 */ li $at, 2 .L80045524: /* 046124 80045524 10410007 */ beq $v0, $at, .L80045544 -/* 046128 80045528 3C0E8012 */ lui $t6, %hi(D_8011D588+2) # $t6, 0x8012 -/* 04612C 8004552C 81CED58A */ lb $t6, %lo(D_8011D588+2)($t6) +/* 046128 80045528 3C0E8012 */ lui $t6, %hi(gEggChallengeFlags+2) # $t6, 0x8012 +/* 04612C 8004552C 81CED58A */ lb $t6, %lo(gEggChallengeFlags+2)($t6) /* 046130 80045530 00000000 */ nop /* 046134 80045534 31CF0040 */ andi $t7, $t6, 0x40 /* 046138 80045538 11E00003 */ beqz $t7, .L80045548 @@ -199,8 +199,8 @@ glabel func_800452A0 /* 046144 80045544 24010003 */ li $at, 3 .L80045548: /* 046148 80045548 10410009 */ beq $v0, $at, .L80045570 -/* 04614C 8004554C 3C188012 */ lui $t8, %hi(D_8011D588+3) # $t8, 0x8012 -/* 046150 80045550 8318D58B */ lb $t8, %lo(D_8011D588+3)($t8) +/* 04614C 8004554C 3C188012 */ lui $t8, %hi(gEggChallengeFlags+3) # $t8, 0x8012 +/* 046150 80045550 8318D58B */ lb $t8, %lo(gEggChallengeFlags+3)($t8) /* 046154 80045554 00000000 */ nop /* 046158 80045558 33190040 */ andi $t9, $t8, 0x40 /* 04615C 8004555C 13200005 */ beqz $t9, .L80045574 diff --git a/include/enums.h b/include/enums.h index 3567471c..cc2d9e2d 100644 --- a/include/enums.h +++ b/include/enums.h @@ -159,7 +159,7 @@ typedef enum MiscAsset { MISC_ASSET_UNK35, MISC_ASSET_UNK36, MISC_ASSET_UNK37, - MISC_ASSET_UNK38, + MISC_ASSET_RACER_HITBOX_SIZE, MISC_ASSET_UNK39, MISC_ASSET_UNK3A, MISC_ASSET_UNK3B, @@ -188,11 +188,11 @@ typedef enum SurfaceType { SURFACE_SAND, SURFACE_ZIP_PAD, SURFACE_STONE, - SURFACE_UNK05, - SURFACE_UNK06, - SURFACE_UNK07, - SURFACE_UNK08, - SURFACE_UNK09, + SURFACE_EGG_SPAWN, + SURFACE_EGG_01, + SURFACE_EGG_02, + SURFACE_EGG_03, + SURFACE_EGG_04, SURFACE_FROZEN_WATER, SURFACE_UNK0B, SURFACE_TAJ_PAD, diff --git a/include/level_object_entries.h b/include/level_object_entries.h index b318705a..6f6a1fb2 100644 --- a/include/level_object_entries.h +++ b/include/level_object_entries.h @@ -15,9 +15,9 @@ typedef struct LevelObjectEntry_Racer { typedef struct LevelObjectEntry_Scenery { /* 0x00 */ LevelObjectEntryCommon common; /* 0x08 */ u8 unk8; - /* 0x09 */ u8 unk9; + /* 0x09 */ u8 radius; /* 0x0A */ u8 unkA; - /* 0x0B */ u8 unkB; + /* 0x0B */ u8 solid; } LevelObjectEntry_Scenery; typedef struct LevelObjectEntry_Fish { @@ -28,9 +28,9 @@ typedef struct LevelObjectEntry_Fish { typedef struct LevelObjectEntry_Animator { /* 0x00 */ LevelObjectEntryCommon common; - /* 0x08 */ s8 unk8; - /* 0x09 */ s8 unk9; - /* 0x0A */ s8 unkA; + /* 0x08 */ s8 batchID; + /* 0x09 */ s8 speedFactorX; + /* 0x0A */ s8 speedfactorY; } LevelObjectEntry_Animator; typedef struct LevelObjectEntry_Weapon { @@ -78,7 +78,7 @@ typedef struct LevelObjectEntry_Exit { typedef struct LevelObjectEntry_Audio { /* 0x00 */ LevelObjectEntryCommon common; - /* 0x08 */ u16 unk8; + /* 0x08 */ u16 soundId; /* 0x0A */ u16 unkA; /* 0x0C */ u8 unkC; /* 0x0D */ u8 unkD; @@ -121,7 +121,7 @@ typedef struct LevelObjectEntry_Checkpoint { /* 0x00 */ LevelObjectEntryCommon common; /* 0x08 */ u8 scale; /* 0x09 */ u8 unk9; - /* 0x0A */ u8 yRotation; + /* 0x0A */ u8 angleY; /* 0x0B */ s8 unkB; /* 0x0C */ s8 unkC; /* 0x0D */ s8 unkD; @@ -204,7 +204,7 @@ typedef struct LevelObjectEntry_Unknown25 { typedef struct LevelObjectEntry_SkyControl { /* 0x00 */ LevelObjectEntryCommon common; /* 0x08 */ u8 unk8; - /* 0x09 */ u8 unk9; + /* 0x09 */ u8 radius; } LevelObjectEntry_SkyControl; typedef struct LevelObjectEntry_AudioReverb { @@ -216,21 +216,21 @@ typedef struct LevelObjectEntry_AudioReverb { typedef struct LevelObjectEntry_Torch_Mist { /* 0x00 */ LevelObjectEntryCommon common; - /* 0x08 */ u8 unk8; - /* 0x09 */ u8 unk9; + /* 0x08 */ u8 animSpeed; + /* 0x09 */ u8 radius; } LevelObjectEntry_Torch_Mist; typedef struct LevelObjectEntry_TexScroll { /* 0x00 */ LevelObjectEntryCommon common; - /* 0x08 */ s16 unk8; + /* 0x08 */ s16 numTextures; /* 0x0A */ s8 unkA; /* 0x0B */ s8 unkB; } LevelObjectEntry_TexScroll; typedef struct LevelObjectEntry_ModeChange { /* 0x00 */ LevelObjectEntryCommon common; - /* 0x08 */ u8 unk8; - /* 0x09 */ u8 unk9; + /* 0x08 */ u8 radius; + /* 0x09 */ u8 angleY; /* 0x0A */ u8 vehicleID; } LevelObjectEntry_ModeChange; @@ -252,7 +252,7 @@ typedef struct LevelObjectEntry_Buoy_PirateShip { typedef struct LevelObjectEntry_Weather { /* 0x00 */ LevelObjectEntryCommon common; - /* 0x08 */ s16 unk8; + /* 0x08 */ s16 radius; /* 0x0A */ s16 unkA; /* 0x0C */ s16 unkC; /* 0x0E */ s16 unkE; @@ -284,8 +284,8 @@ typedef struct LevelObjectEntry_SeaMonster { typedef struct LevelObjectEntry_Bonus { /* 0x00 */ LevelObjectEntryCommon common; - /* 0x08 */ u8 unk8; - /* 0x09 */ u8 unk9; + /* 0x08 */ u8 radius; + /* 0x09 */ u8 angleY; /* 0x0A */ u8 unkA; } LevelObjectEntry_Bonus; @@ -295,7 +295,7 @@ typedef struct LevelObjectEntry_LensFlare { typedef struct LevelObjectEntry_LensFlareSwitch { /* 0x00 */ LevelObjectEntryCommon common; - /* 0x08 */ s16 unk8; + /* 0x08 */ s16 radius; } LevelObjectEntry_LensFlareSwitch; typedef struct LevelObjectEntry_CollectEgg { @@ -374,8 +374,8 @@ typedef struct LevelObjectEntry_Trigger { typedef struct LevelObjectEntry_AirZippers_WaterZippers { /* 0x00 */ LevelObjectEntryCommon common; /* 0x08 */ u8 unk8; - /* 0x09 */ u8 unk9; - /* 0x0A */ u8 unkA; + /* 0x09 */ u8 radius; + /* 0x0A */ u8 angleY; } LevelObjectEntry_AirZippers_WaterZippers; typedef struct LevelObjectEntry_Unknown58 { @@ -400,7 +400,7 @@ typedef struct LevelObjectEntry_Parkwarden { typedef struct LevelObjectEntry_WorldKey { /* 0x00 */ LevelObjectEntryCommon common; - /* 0x08 */ u8 unk8; + /* 0x08 */ u8 keyID; } LevelObjectEntry_WorldKey; typedef struct LevelObjectEntry_BananaCreator { @@ -415,14 +415,14 @@ typedef struct LevelObjectEntry_TreasureSucker { typedef struct LevelObjectEntry_Log { /* 0x00 */ LevelObjectEntryCommon common; /* 0x08 */ u8 unk8; - /* 0x09 */ u8 unk9; - /* 0x0A */ u8 unkA; + /* 0x09 */ u8 radius; + /* 0x0A */ u8 angleY; } LevelObjectEntry_Log; typedef struct LevelObjectEntry_LavaSpurt { /* 0x00 */ LevelObjectEntryCommon common; - /* 0x08 */ u8 unk8; - /* 0x09 */ u8 unk9; + /* 0x08 */ u8 delayTimer; + /* 0x09 */ u8 initialTimer; } LevelObjectEntry_LavaSpurt; typedef struct LevelObjectEntry_PosArrow { @@ -489,8 +489,8 @@ typedef struct LevelObjectEntry_Lasergun { /* 0x09 */ u8 angleY; /* 0x0A */ s8 targeting; /* 0x0B */ s8 fireRate; - /* 0x0C */ u8 unkC; - /* 0x0D */ u8 unkD; + /* 0x0C */ u8 laserDuration; + /* 0x0D */ u8 radius; } LevelObjectEntry_Lasergun; typedef struct LevelObjectEntry_GroundZipper { @@ -535,14 +535,14 @@ typedef struct LevelObjectEntry_Snowball { typedef struct LevelObjectEntry_Teleport { /* 0x00 */ LevelObjectEntryCommon common; - /* 0x08 */ s8 unk8; + /* 0x08 */ s8 levelID; } LevelObjectEntry_Teleport; typedef struct LevelObjectEntry_Lighthouse_RocketSignpost { /* 0x00 */ LevelObjectEntryCommon common; /* 0x08 */ u8 unk8; - /* 0x09 */ u8 unk9; - /* 0x0A */ u8 unkA; + /* 0x09 */ u8 radius; + /* 0x0A */ u8 angleY; } LevelObjectEntry_Lighthouse_RocketSignpost; typedef struct LevelObjectEntry_Windsail { @@ -561,8 +561,8 @@ typedef struct LevelObjectEntry_Fireball_Octoweapon { typedef struct LevelObjectEntry_Frog { /* 0x00 */ LevelObjectEntryCommon common; - /* 0x08 */ s16 unk8; - /* 0x0A */ u8 unkA; + /* 0x08 */ s16 homeRadius; + /* 0x0A */ u8 drumstick; } LevelObjectEntry_Frog; typedef struct LevelObjectEntry_SilverCoinAdv2 { @@ -577,7 +577,7 @@ typedef struct LevelObjectEntry_TTDoor { /* 0x0B */ u8 unkB; /* 0x0C */ u8 unkC; /* 0x0D */ u8 padD; - /* 0x0E */ s8 unkE; + /* 0x0E */ s8 doorID; } LevelObjectEntry_TTDoor; typedef struct LevelObjectEntry_MidiFadePoint { diff --git a/include/structs.h b/include/structs.h index 36d112ee..ec9fc6f5 100644 --- a/include/structs.h +++ b/include/structs.h @@ -644,7 +644,7 @@ typedef struct ObjectHeader24 { typedef struct ObjectHeader { u8 pad0[0x4]; - /* 0x04 */ f32 unk4; + /* 0x04 */ f32 shadowScale; /* 0x08 */ f32 unk8; /* 0x0C */ f32 scale; /* 0x10 */ s32 *modelIds; @@ -718,11 +718,11 @@ typedef struct ObjectInteraction { f32 x_position; f32 y_position; f32 z_position; - u8 unk10; + u8 hitboxRadius; u8 unk11; - u8 unk12; + u8 pushForce; u8 distance; - s16 unk14; + s16 flags; s8 unk16; s8 unk17; } ObjectInteraction; @@ -799,8 +799,8 @@ typedef struct Object_LaserGun { /* 0x0C */ s16 fireTimer; /* 0x0E */ s8 targeting; /* 0x0F */ s8 fireRate; - /* 0x10 */ u8 unk10; - /* 0x11 */ u8 unk11; + /* 0x10 */ u8 laserDuration; + /* 0x11 */ u8 radius; } Object_LaserGun; typedef struct Object_Laser { @@ -817,8 +817,8 @@ typedef struct Object_TrophyCabinet { typedef struct Object_Animator { /* 0x00 */ s16 segmentId; /* 0x02 */ s16 batchId; - /* 0x04 */ s16 xSpeedFactor; - /* 0x06 */ s16 ySpeedFactor; + /* 0x04 */ s16 speedFactorX; + /* 0x06 */ s16 speedFactorY; /* 0x08 */ s16 xSpeed; /* 0x0A */ s16 ySpeed; } Object_Animator; @@ -890,15 +890,15 @@ typedef struct Object_EffectBox { typedef struct Object_EggCreator { /* 0x0 */ u8 pad0[4]; - /* 0x4 */ struct Object *unk4; + /* 0x4 */ struct Object *currentEgg; } Object_EggCreator; typedef struct Object_CollectEgg { /* 0x0 */ u8 pad0[4]; /* 0x4 */ struct Object *unk4; - /* 0x8 */ s16 unk8; - /* 0xA */ s8 unkA; - /* 0xB */ s8 unkB; + /* 0x8 */ s16 hatchTimer; + /* 0xA */ s8 racerID; + /* 0xB */ s8 status; } Object_CollectEgg; typedef struct Object_UnkId58 { @@ -937,7 +937,7 @@ typedef struct Object_TTDoor { /* 0x08 */ s32 unk8; /* 0x0C */ s16 unkC; /* 0x0C */ s8 unkE; - /* 0x0F */ u8 unkF; + /* 0x0F */ u8 doorID; /* 0x10 */ u8 pad10[2]; /* 0x12 */ u8 unk12; /* 0x13 */ s8 unk13; @@ -979,7 +979,7 @@ typedef struct Object_AudioReverb { } Object_AudioReverb; typedef struct Object_TexScroll { - /* 0x0 */ s16 unk0; + /* 0x0 */ s16 numTextures; /* 0x2 */ s16 pad2; /* 0x4 */ s16 unk4; /* 0x6 */ s16 unk6; @@ -988,23 +988,23 @@ typedef struct Object_TexScroll { } Object_TexScroll; typedef struct Object_Frog { - /* 0x00 */ f32 unk0; - /* 0x04 */ f32 unk4; - /* 0x08 */ f32 unk8; - /* 0x0C */ f32 unkC; - /* 0x10 */ f32 unk10; - /* 0x14 */ u8 unk14; - /* 0x15 */ u8 unk15; - /* 0x16 */ s16 unk16; - /* 0x18 */ s8 unk18; - /* 0x19 */ s8 unk19; - /* 0x1A */ s16 unk1A; - /* 0x1C */ f32 unk1C; - /* 0x20 */ f32 unk20; - /* 0x24 */ f32 unk24; - /* 0x28 */ f32 unk28; - /* 0x2C */ f32 unk2C; - /* 0x30 */ f32 unk30; + /* 0x00 */ f32 homeX; + /* 0x04 */ f32 homeY; + /* 0x08 */ f32 homeZ; + /* 0x0C */ f32 homeRadius; + /* 0x10 */ f32 homeRadiusSquare; + /* 0x14 */ u8 action; + /* 0x15 */ u8 drumstick; + /* 0x16 */ s16 hopTimer; + /* 0x18 */ s8 hopFrame; // Animation frame while jumping + /* 0x19 */ s8 squishCooldown; + /* 0x1A */ s16 hopDirection; + /* 0x1C */ f32 forwardVel; + /* 0x20 */ f32 hopStartX; + /* 0x24 */ f32 hopStartZ; + /* 0x28 */ f32 hopTargetX; + /* 0x2C */ f32 hopTargetZ; + /* 0x30 */ f32 scaleY; } Object_Frog; typedef struct Object_Wizpig2 { @@ -1103,7 +1103,7 @@ typedef struct Object_Racer { /* 0x140 */ struct Object *magnetTargetObj; /* 0x144 */ struct Object *held_obj; /* 0x148 */ struct Object *approachTarget; - /* 0x14C */ struct Object *unk14C; + /* 0x14C */ struct Object *zipperObj; /* 0x150 */ struct Object *unk150; /* 0x154 */ struct Object *unk154; /* 0x158 */ struct Object *unk158; @@ -1170,7 +1170,7 @@ typedef struct Object_Racer { /* 0x1CC */ s8 aiSkill; /* 0x1CD */ u8 unk1CD; /* 0x1CE */ u8 unk1CE; - /* 0x1CF */ s8 unk1CF; + /* 0x1CF */ s8 eggHudCounter; /* 0x1D0 */ s8 spectateCamID; /* 0x1D1 */ s8 unk1D1; /* 0x1D2 */ s8 unk1D2; @@ -1205,7 +1205,7 @@ typedef struct Object_Racer { /* 0x1F2 */ u8 unk1F2; /* 0x1F3 */ u8 unk1F3; /* 0x1F4 */ u8 startInput; - /* 0x1F5 */ u8 unk1F5; + /* 0x1F5 */ u8 zipperDirCorrection; /* 0x1F6 */ s8 unk1F6; /* 0x1F7 */ u8 transparency; /* 0x290 */ u8 indicator_type; @@ -1243,20 +1243,20 @@ typedef struct Object_Racer { } Object_Racer; typedef struct Object_Bonus { - /* 0x00 */ f32 unk0; - /* 0x04 */ f32 unk4; - /* 0x08 */ f32 unk8; - /* 0x0C */ f32 unkC; - /* 0x10 */ s32 unk10; + /* 0x00 */ f32 directionX; + /* 0x04 */ f32 directionY; + /* 0x08 */ f32 directionZ; + /* 0x0C */ f32 rotationDiff; // Rotational offset, to test intersection when the exit is rotated. + /* 0x10 */ s32 radius; // Activation radius. /* 0x14 */ s8 unk14; } Object_Bonus; typedef struct Object_ModeChange { - /* 0x00 */ f32 unk0; - /* 0x04 */ f32 unk4; - /* 0x08 */ f32 unk8; - /* 0x0C */ f32 unkC; - /* 0x10 */ s32 unk10; + /* 0x00 */ f32 directionX; + /* 0x04 */ f32 directionY; + /* 0x08 */ f32 directionZ; + /* 0x0C */ f32 rotationDiff; // Rotational offset, to test intersection when the exit is rotated. + /* 0x10 */ s32 radius; // Activation radius. /* 0x14 */ u8 vehicleID; } Object_ModeChange; @@ -1412,7 +1412,7 @@ typedef struct Object_Log { typedef struct Object_Fireball_Octoweapon { u8 pad0[0x1C]; - s32 unk1C; + s32 soundMask; } Object_Fireball_Octoweapon; typedef struct Object_AnimatedObject { diff --git a/src/collision.h b/src/collision.h index aefb4419..8c8611e6 100644 --- a/src/collision.h +++ b/src/collision.h @@ -6,6 +6,6 @@ void func_80031130(s32, f32 *, f32*, s32); s32 func_800314DC(LevelModelSegmentBoundingBox *segment, s32 x1, s32 z1, s32 x2, s32 z2); -s32 func_80031600(f32 *pos, f32 *pos2, f32*, s8 *surface, s32, s32 *); +s32 func_80031600(f32 *pos, f32 *pos2, f32 *radius, s8 *surface, s32, s32 *hasCollision); #endif diff --git a/src/game.c b/src/game.c index 039306da..6d899391 100644 --- a/src/game.c +++ b/src/game.c @@ -114,7 +114,7 @@ FadeTransition D_800DD408 = FADE_TRANSITION(FADE_FULLSCREEN, FADE_FLAG_NONE, FAD UNUSED char *D_800DD410[3] = { (char *)sDebugCarString, (char *)sDebugHovercraftString, (char *)sDebugPlaneString }; -FadeTransition D_800DD41C = FADE_TRANSITION(FADE_FULLSCREEN, FADE_FLAG_NONE, FADE_COLOR_BLACK, 30, -1); +FadeTransition gLevelFadeOutTransition = FADE_TRANSITION(FADE_FULLSCREEN, FADE_FLAG_NONE, FADE_COLOR_BLACK, 30, -1); FadeTransition D_800DD424 = FADE_TRANSITION(FADE_FULLSCREEN, FADE_FLAG_NONE, FADE_COLOR_BLACK, 260, -1); /*******************************/ @@ -166,7 +166,7 @@ Vehicle gLevelDefaultVehicleID; Vehicle D_8012351C; // Looks to be the current level's vehicle ID. s32 sBootDelayTimer; s8 D_80123524; -s8 D_80123525; +s8 gNextMap; UNUSED s8 D_80123526; // Set to 0 then never used. s32 gCurrNumF3dCmdsPerPlayer; s32 gCurrNumHudMatPerPlayer; @@ -1359,7 +1359,7 @@ void ingame_logic_loop(s32 updateRate) { // fall-through case 4: D_801234F8 = 1; - gPlayableMapId = D_80123525; + gPlayableMapId = gNextMap; D_80123504 = 0; D_80123508 = 0; buttonHeldInputs = 0; @@ -2166,7 +2166,7 @@ void func_8006F140(s32 arg0) { D_80123524 = 0; D_80123526 = 0; if (arg0 == 1) { //FADE_BARNDOOR_HORIZONTAL? - transition_begin(&D_800DD41C); + transition_begin(&gLevelFadeOutTransition); } if (arg0 == 3) { //FADE_CIRCLE? gLevelLoadTimer = 282; @@ -2184,7 +2184,7 @@ void func_8006F140(s32 arg0) { UNUSED void func_8006F20C(void) { if (gLevelLoadTimer == 0) { - transition_begin(&D_800DD41C); + transition_begin(&gLevelFadeOutTransition); gLevelLoadTimer = 40; D_80123524 = 1; } @@ -2192,28 +2192,35 @@ UNUSED void func_8006F20C(void) { void func_8006F254(void) { if (gLevelLoadTimer == 0) { - transition_begin(&D_800DD41C); + transition_begin(&gLevelFadeOutTransition); gLevelLoadTimer = 40; D_80123524 = 2; } } -void func_8006F29C(void) { +/** + * Check if all available trophy races and Wizpig 1 has been beaten, and if the cutscene has not yet played. +*/ +void begin_lighthouse_rocket_cutscene(void) { if (gLevelLoadTimer == 0) { if ((gSettingsPtr->trophies & 0xFF) == 0xFF && !(gSettingsPtr->cutsceneFlags & CUTSCENE_LIGHTHOUSE_ROCKET) && gSettingsPtr->bosses & 1) { gSettingsPtr->cutsceneFlags |= CUTSCENE_LIGHTHOUSE_ROCKET; - transition_begin(&D_800DD41C); + transition_begin(&gLevelFadeOutTransition); gLevelLoadTimer = 40; - D_80123525 = 0x2D; + gNextMap = ASSET_LEVEL_ROCKETSEQUENCE; D_80123524 = 3; } } } -void func_8006F338(s32 arg0) { +/** + * Begin a transition, then set the next level to the passed argument. + * This is used only to warp to Future Fun Land from the hub area. +*/ +void begin_level_teleport(s32 levelID) { if (gLevelLoadTimer == 0) { - D_80123525 = arg0; - transition_begin(&D_800DD41C); + gNextMap = levelID; + transition_begin(&gLevelFadeOutTransition); gLevelLoadTimer = 40; D_80123524 = 4; } diff --git a/src/game.h b/src/game.h index d6003a2e..1db10aca 100644 --- a/src/game.h +++ b/src/game.h @@ -148,8 +148,8 @@ s32 check_dmem_validity(void); void func_8006F140(s32 arg0); void func_8006F20C(void); void func_8006F254(void); -void func_8006F29C(void); -void func_8006F338(s32 arg0); +void begin_lighthouse_rocket_cutscene(void); +void begin_level_teleport(s32 arg0); void func_8006F388(u8 arg0); void func_8006F398(void); void set_frame_blackout_timer(void); diff --git a/src/object_functions.c b/src/object_functions.c index 7a8c2719..0cec3899 100644 --- a/src/object_functions.c +++ b/src/object_functions.c @@ -38,7 +38,7 @@ FadeTransition D_800DC970 = FADE_TRANSITION(FADE_FULLSCREEN, FADE_FLAG_UNK1, FADE_COLOR_WHITE, 7, 3); FadeTransition D_800DC978 = FADE_TRANSITION(FADE_FULLSCREEN, FADE_FLAG_NONE, FADE_COLOR_BLACK, 30, 0xFFFF); -Vertex D_800DC980[4] = { +Vertex gCharacterFlagVertices[4] = { { -256, 256, 0, 255, 255, 255, 255 }, { 256, 256, 0, 255, 255, 255, 255 }, { 256, -256, 0, 255, 255, 255, 255 }, @@ -130,25 +130,30 @@ s16 D_8011D4E2; // Taj Voice clips /******************************/ +/** + * Level scenery init behaviour. + * Set rotation and scale based off spawn info. + * Also have the option based off spawn info to add solidity to the hitbox. +*/ void obj_init_scenery(Object *obj, LevelObjectEntry_Scenery *entry) { - f32 phi_f0; + f32 radius; obj->segment.trans.unk6 |= 2; - phi_f0 = entry->unk9 & 0xFF; - if (phi_f0 < 10) { - phi_f0 = 10; + radius = entry->radius & 0xFF; + if (radius < 10) { + radius = 10; } - phi_f0 /= 64; - obj->segment.trans.scale = obj->segment.header->scale * phi_f0; - obj->shadow->scale = obj->segment.header->unk4 * phi_f0; + radius /= 64; + obj->segment.trans.scale = obj->segment.header->scale * radius; + obj->shadow->scale = obj->segment.header->shadowScale * radius; obj->segment.unk38.byte.unk3A = entry->unk8; obj->segment.trans.y_rotation = entry->unkA << 6 << 4; - if (entry->unkB) { - obj->interactObj->unk14 = 1; + if (entry->solid) { + obj->interactObj->flags = INTERACT_FLAGS_SOLID; obj->interactObj->unk11 = 1; - obj->interactObj->unk10 = 20; - obj->interactObj->unk12 = 0; + obj->interactObj->hitboxRadius = 20; + obj->interactObj->pushForce = 0; obj->interactObj->unk16 = -5; - obj->interactObj->unk17 = entry->unkB; + obj->interactObj->unk17 = entry->solid; } if (obj->segment.unk38.byte.unk3A >= obj->segment.header->numberOfModelIds) { obj->segment.unk38.byte.unk3A = 0; @@ -157,6 +162,10 @@ void obj_init_scenery(Object *obj, LevelObjectEntry_Scenery *entry) { obj->unk7C.word = 0; } +/** + * Level scenery loop behaviour. + * When hit by a racer, give it an elastic behaviour as feedback. +*/ void obj_loop_scenery(Object *obj, s32 updateRate) { Object78_80033DD0 *obj78; s32 temp_v0; @@ -166,9 +175,9 @@ void obj_loop_scenery(Object *obj, s32 updateRate) { if (obj->unk7C.half.upper > 0) { obj78->unk4 -= updateRate; } - if ((obj->interactObj->unk14 & 0x40) && ((s32) obj78->unk4 <= 0)) { + if (obj->interactObj->flags & INTERACT_FLAGS_COLLIDED && obj78->unk4 <= 0) { play_sound_at_position(SOUND_TWANG, obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 4, NULL); - obj78->unk0 = (s32*) obj->interactObj->obj; + obj78->unk0 = (s32 *) obj->interactObj->obj; obj78->unk6 = 1820; obj78->unk4 = 10; if (get_number_of_active_players() < 2) { @@ -185,13 +194,17 @@ void obj_loop_scenery(Object *obj, s32 updateRate) { } else if (obj78->unk4 <= 0) { obj78->unk0 = 0; } - obj->segment.trans.z_rotation = (s16) obj78->unk6; + obj->segment.trans.z_rotation = obj78->unk6; obj78->unk6 = (obj78->unk6 * -200) >> 8; } } +/** + * Bubbler boss obstacle init behaviour. + * Sets hitbox info so it can be interacted with. + */ void obj_init_fireball_octoweapon(Object *obj, UNUSED LevelObjectEntry_Fireball_Octoweapon *entry) { - obj->interactObj->unk14 = 2; + obj->interactObj->flags = INTERACT_FLAGS_TANGIBLE; obj->interactObj->unk11 = 0; } @@ -202,15 +215,15 @@ void obj_init_fireball_octoweapon(Object *obj, UNUSED LevelObjectEntry_Fireball_ */ void obj_loop_fireball_octoweapon(Object *obj, s32 updateRate) { Object *someObj; - f32 var_f2; + f32 diff; f32 updateRateF; UNUSED s32 pad; Object_Fireball_Octoweapon *weapon; Object_Racer *racer; UNUSED s32 pad2[6]; - ObjectInteraction *obj4C; - s32 temp; - f32 sp4C; + ObjectInteraction *interactObj; + s32 soundMask; + f32 waveHeight; someObj = (Object *) obj->unk78; updateRateF = updateRate; @@ -224,60 +237,60 @@ void obj_loop_fireball_octoweapon(Object *obj, s32 updateRate) { func_80011560(); move_object(obj, someObj->segment.trans.x_position, someObj->segment.trans.y_position, someObj->segment.trans.z_position); } else { - var_f2 = (someObj->segment.trans.x_position - obj->segment.trans.x_position) * 0.1; - if (var_f2 > 10.0) { - var_f2 = 10.0f; + diff = (someObj->segment.trans.x_position - obj->segment.trans.x_position) * 0.1; + if (diff > 10.0) { + diff = 10.0f; } - if (var_f2 < -10.0) { - var_f2 = -10.0f; + if (diff < -10.0) { + diff = -10.0f; } - obj->segment.x_velocity += (var_f2 - obj->segment.x_velocity) * 0.125 * updateRateF; - var_f2 = (someObj->segment.trans.y_position - obj->segment.trans.y_position) * 0.1; - if (var_f2 > 10.0) { - var_f2 = 10.0f; + obj->segment.x_velocity += (diff - obj->segment.x_velocity) * 0.125 * updateRateF; + diff = (someObj->segment.trans.y_position - obj->segment.trans.y_position) * 0.1; + if (diff > 10.0) { + diff = 10.0f; } - if (var_f2 < -10.0) { - var_f2 = -10.0f; + if (diff < -10.0) { + diff = -10.0f; } - obj->segment.y_velocity += (var_f2 - obj->segment.y_velocity) * 0.125 * updateRateF; - var_f2 = (someObj->segment.trans.z_position - obj->segment.trans.z_position) * 0.1; - if (var_f2 > 10.0) { - var_f2 = 10.0f; + obj->segment.y_velocity += (diff - obj->segment.y_velocity) * 0.125 * updateRateF; + diff = (someObj->segment.trans.z_position - obj->segment.trans.z_position) * 0.1; + if (diff > 10.0) { + diff = 10.0f; } - if (var_f2 < -10.0) { - var_f2 = -10.0f; + if (diff < -10.0) { + diff = -10.0f; } - obj->segment.z_velocity += (var_f2 - obj->segment.z_velocity) * 0.125 * updateRateF; + obj->segment.z_velocity += (diff - obj->segment.z_velocity) * 0.125 * updateRateF; if (sqrtf((obj->segment.x_velocity * obj->segment.x_velocity) + (obj->segment.z_velocity * obj->segment.z_velocity)) > 0.5) { obj->segment.trans.y_rotation = arctan2_f(obj->segment.x_velocity, obj->segment.z_velocity); obj->segment.trans.x_rotation -= updateRate * 0x200; } move_object(obj, obj->segment.x_velocity * updateRateF, obj->segment.y_velocity * updateRateF, obj->segment.z_velocity * updateRateF); if (obj->unk4A == 298) { - if (get_wave_properties(obj->segment.trans.y_position, &sp4C, NULL)) { - obj->segment.trans.y_position = sp4C; + if (get_wave_properties(obj->segment.trans.y_position, &waveHeight, NULL)) { + obj->segment.trans.y_position = waveHeight; } } } obj->segment.animFrame += updateRate * 10; weapon = (Object_Fireball_Octoweapon *) obj->unk64; - obj4C = obj->interactObj; - if ((obj4C->obj)) { - if ((obj4C->distance < 60)) { - someObj = obj4C->obj; + interactObj = obj->interactObj; + if ((interactObj->obj)) { + if ((interactObj->distance < 60)) { + someObj = interactObj->obj; if((someObj->segment.header->behaviorId == BHV_RACER)) { racer = (Object_Racer *) someObj->unk64; if (racer->playerIndex != PLAYER_COMPUTER) { if (obj->behaviorId == BHV_FIREBALL_OCTOWEAPON) { racer->attackType = ATTACK_EXPLOSION; obj->unk7C.word = 20; - func_8003FC44(obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 44, 17, 1.0f, 1); + func_8003FC44(obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 44, SOUND_EXPLOSION, 1.0f, 1); gParticlePtrList_addObject(obj); } else if (obj->unk7C.word > 0) { racer->unk204 = 60; obj->unk7C.word = -60; obj->unk78 = (s32) someObj; - play_sound_global(SOUND_BUBBLE_RISE, &weapon->unk1C); + play_sound_global(SOUND_BUBBLE_RISE, &weapon->soundMask); } } } @@ -290,7 +303,7 @@ void obj_loop_fireball_octoweapon(Object *obj, s32 updateRate) { if (obj->unk7C.word < 0) { if (obj->unk4A == 298) { gParticlePtrList_addObject(obj); - func_8003FC44(obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 44, 17, 1.0f, 1); + func_8003FC44(obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 44, SOUND_EXPLOSION, 1.0f, 1); } obj->segment.trans.scale *= 0.9; if (obj->segment.trans.scale < 0.5) { @@ -310,9 +323,9 @@ void obj_loop_fireball_octoweapon(Object *obj, s32 updateRate) { } } if (obj->unk7C.word == 0) { - temp = weapon->unk1C; - if (temp != 0) { - func_8000488C(temp); + soundMask = weapon->soundMask; + if (soundMask != NULL) { + func_8000488C(soundMask); } play_sound_at_position(SOUND_POP, obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 4, NULL); gParticlePtrList_addObject(obj); @@ -327,13 +340,13 @@ void obj_loop_fireball_octoweapon(Object *obj, s32 updateRate) { */ void obj_init_lasergun(Object *obj, LevelObjectEntry_Lasergun *entry) { Object_LaserGun *laserGun; - obj->interactObj->unk14 = 34; + obj->interactObj->flags = INTERACT_FLAGS_TANGIBLE | INTERACT_FLAGS_UNK_0020; obj->interactObj->unk11 = 0; laserGun = &obj->unk64->lasergun; laserGun->targeting = entry->targeting; laserGun->fireRate = entry->fireRate; - laserGun->unk10 = entry->unkC; - laserGun->unk11 = entry->unkD; + laserGun->laserDuration = entry->laserDuration; + laserGun->radius = entry->radius; laserGun->fireTimer = laserGun->fireRate; obj->segment.trans.y_rotation = entry->angleX << 4 << 4; // Not sure about the shift amounts here, but it obj->segment.trans.x_rotation = entry->angleY << 4 << 4; // just needs to be 2 left shifts that add up to 8. @@ -354,17 +367,17 @@ void obj_loop_lasergun(Object *obj, s32 updateRate) { f32 diffX; f32 diffZ; f32 diffY; - ObjectInteraction *obj4C; + ObjectInteraction *interactObj; LevelObjectEntryCommon spawnObj; lasergun = (Object_LaserGun *) obj->unk64; if (lasergun->fireTimer > 0) { lasergun->fireTimer -= updateRate; } else { - obj4C = obj->interactObj; - if (lasergun->unk11 >= obj4C->distance) { + interactObj = obj->interactObj; + if (lasergun->radius >= interactObj->distance) { if (lasergun->targeting) { - racerObj = obj4C->obj; + racerObj = interactObj->obj; if (racerObj != NULL && racerObj->behaviorId == BHV_RACER) { diffX = obj->segment.trans.x_position - racerObj->segment.trans.x_position; diffY = obj->segment.trans.y_position - racerObj->segment.trans.y_position; @@ -391,7 +404,7 @@ void obj_loop_lasergun(Object *obj, s32 updateRate) { laserBoltObj->segment.unk3C_a.level_entry = NULL; laserBoltObj->segment.trans.y_rotation = obj->segment.trans.y_rotation; laserBoltObj->segment.trans.x_rotation = obj->segment.trans.x_rotation; - laserBoltObj->unk78 = lasergun->unk10; + laserBoltObj->unk78 = lasergun->laserDuration; laserBoltObj->unk7C.word = (s32) lasergun; trans.x_position = 0.0f; trans.y_position = 0.0f; @@ -411,8 +424,12 @@ void obj_loop_lasergun(Object *obj, s32 updateRate) { } } +/** + * Laser Bolt init behaviour. + * Sets hitbox data so it can be interacted with. +*/ void obj_init_laserbolt(Object *obj, UNUSED LevelObjectEntry_Laserbolt *entry) { - obj->interactObj->unk14 = 2; + obj->interactObj->flags = INTERACT_FLAGS_TANGIBLE; obj->interactObj->unk11 = 0; } @@ -421,84 +438,96 @@ typedef struct Object_7C_80034860 { s16 unkC; } Object_7C_80034860; +/** + * Laser Bolt init behaviour. + * Move in a set direction, until it either times out, hits a racer, or hits a wall. +*/ void obj_loop_laserbolt(Object *obj, s32 updateRate) { f32 updateRateF; - Object *obj4C_obj; + Object *racerObj; Object_7C_80034860 *obj7C; - Object_Laser *obj4C_obj64; + Object_Laser *laser; - s8 sp4F; // Boolean - s8 sp4E; - f32 sp48; - f32 sp44; - f32 sp40; - f32 sp3C; - s32 sp38; // Boolean + s8 delete; // Boolean + s8 surface; + f32 dirZ; + f32 dirY; + f32 dirX; + f32 radius; + s32 hasCollision; // Boolean - sp4F = FALSE; + delete = FALSE; updateRateF = updateRate; if (osTvType == TV_TYPE_PAL) { updateRateF *= 1.2; } - sp40 = obj->segment.trans.x_position + (obj->segment.x_velocity * updateRateF); - sp44 = obj->segment.trans.y_position + (obj->segment.y_velocity * updateRateF); - sp48 = obj->segment.trans.z_position + (obj->segment.z_velocity * updateRateF); - sp3C = 9.0f; + dirX = obj->segment.trans.x_position + (obj->segment.x_velocity * updateRateF); + dirY = obj->segment.trans.y_position + (obj->segment.y_velocity * updateRateF); + dirZ = obj->segment.trans.z_position + (obj->segment.z_velocity * updateRateF); + radius = 9.0f; - func_80031130(1, &obj->segment.trans.x_position, &sp40, -1); - sp38 = FALSE; - func_80031600(&obj->segment.trans.x_position, &sp40, &sp3C, &sp4E, 1, &sp38); - if (sp38) { - obj->segment.x_velocity = (sp40 - obj->segment.trans.x_position) / updateRateF; - obj->segment.y_velocity = (sp44 - obj->segment.trans.y_position) / updateRateF; - obj->segment.z_velocity = (sp48 - obj->segment.trans.z_position) / updateRateF; + func_80031130(1, &obj->segment.trans.x_position, &dirX, -1); + hasCollision = FALSE; + func_80031600(&obj->segment.trans.x_position, &dirX, &radius, &surface, TRUE, &hasCollision); + if (hasCollision) { + obj->segment.x_velocity = (dirX - obj->segment.trans.x_position) / updateRateF; + obj->segment.y_velocity = (dirY - obj->segment.trans.y_position) / updateRateF; + obj->segment.z_velocity = (dirZ - obj->segment.trans.z_position) / updateRateF; } move_object(obj, obj->segment.x_velocity * updateRateF, obj->segment.y_velocity * updateRateF, obj->segment.z_velocity * updateRateF); - if (sp38) { - func_8003FC44(obj->segment.trans.x_position, obj->segment.trans.y_position - 36.0f, obj->segment.trans.z_position, 44, 0, 0.2, 0); - sp4F = TRUE; + if (hasCollision) { + func_8003FC44(obj->segment.trans.x_position, obj->segment.trans.y_position - 36.0f, obj->segment.trans.z_position, 44, SOUND_NONE, 0.2, 0); + delete = TRUE; } if (obj->unk78 > 0) { obj->unk78 -= updateRate; } else { - sp4F = TRUE; + delete = TRUE; } if (obj->interactObj->distance < 80) { - obj4C_obj = (Object*)obj->interactObj->obj; - if (obj4C_obj && (obj4C_obj->behaviorId == 1)) { - obj4C_obj64 = &obj4C_obj->unk64->laser; - sp4F = TRUE; - if (obj4C_obj64->unk0 != -1) { - obj4C_obj64->unk187 = 1; + racerObj = obj->interactObj->obj; + if (racerObj && racerObj->behaviorId == BHV_RACER) { + laser = &racerObj->unk64->laser; + delete = TRUE; + if (laser->unk0 != -1) { + laser->unk187 = 1; } - obj7C = (Object_7C_80034860 *)obj->unk7C.word; + obj7C = (Object_7C_80034860 *) obj->unk7C.word; if (obj7C) { obj7C->unkC = 180; } - sp4F = TRUE; - func_8003FC44(obj->segment.trans.x_position, obj->segment.trans.y_position - 36.0f, obj->segment.trans.z_position, 44, 17, 0.5, 0); + delete = TRUE; + func_8003FC44(obj->segment.trans.x_position, obj->segment.trans.y_position - 36.0f, obj->segment.trans.z_position, 44, SOUND_EXPLOSION, 0.5, 0); } } - if (sp4F) { + if (delete) { gParticlePtrList_addObject(obj); } } +/** + * Torch / Mist init behaviour. + * Sets scale and animation speed based off spawn info. +*/ void obj_init_torch_mist(Object *obj, LevelObjectEntry_Torch_Mist *entry) { - f32 phi_f0 = (s32)(entry->unk9 & 0xFF); - if (phi_f0 < 10.0f) { - phi_f0 = 10.0f; + f32 radius = entry->radius & 0xFF; + if (radius < 10.0f) { + radius = 10.0f; } - phi_f0 /= 64; - obj->segment.trans.scale = obj->segment.header->scale * phi_f0; - obj->unk78 = entry->unk8; + radius /= 64; + obj->segment.trans.scale = obj->segment.header->scale * radius; + obj->unk78 = entry->animSpeed; } +/** + * Torch / Mist loop behaviour. + * Updates the animation frame based on spawn info's animation speed. +*/ void obj_loop_torch_mist(Object *obj, s32 updateRate) { obj->segment.animFrame += obj->unk78 * updateRate; } @@ -559,8 +588,12 @@ void obj_loop_effectbox(Object *obj, UNUSED s32 updateRate) { GLOBAL_ASM("asm/non_matchings/unknown_032760/obj_loop_effectbox.s") #endif +/** + * Trophy Cabinet loop behaviour. + * Sets rotation and hitbox data so it can be collided with. +*/ void obj_init_trophycab(Object *obj, LevelObjectEntry_TrophyCab *entry) { - obj->interactObj->unk14 = 1; + obj->interactObj->flags = INTERACT_FLAGS_SOLID; obj->interactObj->unk11 = 2; obj->segment.trans.y_rotation = entry->rotation << 6 << 4; // Not sure about the values here. } @@ -590,7 +623,7 @@ void obj_loop_trophycab(Object *obj, s32 updateRate) { if (obj->unk7C.word == 0) { if (header->race_type != RACETYPE_CUTSCENE_2 && header->race_type != RACETYPE_CUTSCENE_1) { obj->unk7C.word = 1; - if ((settings->trophies >> (((settings->worldId - 1) ^ 0) * 2)) & 3) { + if ((settings->trophies >> (((settings->worldId - 1) ^ 0) * 2)) & 3) { // Fakematch newObject.objectID = 0x80; newObject.x = obj->segment.unk3C_a.level_entry->animation.common.x; newObject.y = obj->segment.unk3C_a.level_entry->animation.common.y; @@ -675,98 +708,107 @@ void obj_loop_trophycab(Object *obj, s32 updateRate) { } } +/** + * Fire Mountain egg init function. + * Sets up hitbox data so it can be picked up. +*/ void obj_init_collectegg(Object *obj, UNUSED LevelObjectEntry_CollectEgg *entry) { - obj->interactObj->unk14 = 2; + obj->interactObj->flags = INTERACT_FLAGS_TANGIBLE; obj->interactObj->unk11 = 0; - obj->interactObj->unk10 = 0x14; - obj->interactObj->unk12 = 0; + obj->interactObj->hitboxRadius = 20; + obj->interactObj->pushForce = 0; } +/** + * Fire Mountain egg loop function. + * Spawn on SURFACE_EGG_SPAWN, and if dropped on surfaces SURFACE_EGG_01 to SURFACE_EGG_04, begin ticking down to hatch. +*/ void obj_loop_collectegg(Object *obj, s32 updateRate) { Object_CollectEgg *egg; Object *racerObj; Object_Racer *racer; - f32 sp40[3]; - f32 sp3C; + f32 dir[3]; + f32 radius; f32 updateRateF; - s32 sp34; - s8 sp33; + s32 hasCollision; + s8 surface; egg = (Object_CollectEgg *) obj->unk64; updateRateF = updateRate; if (osTvType == TV_TYPE_PAL) { updateRateF *= 1.2; } - switch (egg->unkB) { - case 0: + switch (egg->status) { + case EGG_SPAWNED: func_80036040(obj, (Object_64 *) egg); break; - case 2: + case EGG_MOVING: obj->segment.trans.unk6 &= 0xBFFF; - sp40[0] = obj->segment.trans.x_position + (obj->segment.x_velocity * updateRateF); - sp40[1] = obj->segment.trans.y_position + (obj->segment.y_velocity * updateRateF); - sp40[2] = obj->segment.trans.z_position + (obj->segment.z_velocity * updateRateF); - sp3C = 9.0f; - func_80031130(1, &obj->segment.trans.x_position, sp40, -1); - sp34 = 0; - sp33 = 0; - func_80031600(&obj->segment.trans.x_position, sp40, &sp3C, &sp33, 1, &sp34); - obj->segment.x_velocity = (sp40[0] - obj->segment.trans.x_position) / updateRateF; - obj->segment.y_velocity = (sp40[1] - obj->segment.trans.y_position) / updateRateF; - obj->segment.z_velocity = (sp40[2] - obj->segment.trans.z_position) / updateRateF; - obj->segment.trans.x_position = sp40[0]; - obj->segment.trans.y_position = sp40[1]; - obj->segment.trans.z_position = sp40[2]; + dir[0] = obj->segment.trans.x_position + (obj->segment.x_velocity * updateRateF); + dir[1] = obj->segment.trans.y_position + (obj->segment.y_velocity * updateRateF); + dir[2] = obj->segment.trans.z_position + (obj->segment.z_velocity * updateRateF); + radius = 9.0f; + func_80031130(1, &obj->segment.trans.x_position, dir, -1); + hasCollision = FALSE; + surface = SURFACE_DEFAULT; + func_80031600(&obj->segment.trans.x_position, dir, &radius, &surface, TRUE, &hasCollision); + obj->segment.x_velocity = (dir[0] - obj->segment.trans.x_position) / updateRateF; + obj->segment.y_velocity = (dir[1] - obj->segment.trans.y_position) / updateRateF; + obj->segment.z_velocity = (dir[2] - obj->segment.trans.z_position) / updateRateF; + obj->segment.trans.x_position = dir[0]; + obj->segment.trans.y_position = dir[1]; + obj->segment.trans.z_position = dir[2]; obj->segment.y_velocity -= 0.5; obj->segment.x_velocity *= 0.98; obj->segment.z_velocity *= 0.98; obj->segment.y_velocity *= 0.95; - if (obj->segment.trans.y_position < -2000.0f || (sp34 != 0 && (sp33 < 5 || sp33 >= 10))) { + // Destroy the egg if it lands on an invalid surface. + if (obj->segment.trans.y_position < -2000.0f || (hasCollision && (surface < SURFACE_EGG_SPAWN || surface > SURFACE_EGG_04))) { if (egg->unk4 != NULL) { egg->unk4->action = 0; } gParticlePtrList_addObject(obj); } - if (sp34 != 0 && sp33 == 5) { - egg->unkB = 0; + if (hasCollision && surface == SURFACE_EGG_SPAWN) { + egg->status = EGG_SPAWNED; obj->segment.x_velocity = 0.0f; obj->segment.z_velocity = 0.0f; } - if (sp34 != 0 && sp33 >= 6 && sp33 < 10) { - egg->unkA = sp33 - 6; - egg->unkB = 3; - racerObj = get_racer_object(egg->unkA); + if (hasCollision && surface >= SURFACE_EGG_01 && surface <= SURFACE_EGG_04) { + egg->racerID = surface - SURFACE_EGG_01; + egg->status = EGG_IN_BASE; + racerObj = get_racer_object(egg->racerID); if (racerObj != NULL) { racer = (Object_Racer *) racerObj->unk64; - racer->unk1CF += 1; + racer->eggHudCounter += 1; } - egg->unk8 = 600; + egg->hatchTimer = 600; obj->segment.x_velocity = 0.0f; obj->segment.z_velocity = 0.0f; } break; - case 3: - egg->unk8 -= updateRate; - racerObj = get_racer_object(egg->unkA); + case EGG_IN_BASE: + egg->hatchTimer -= updateRate; + racerObj = get_racer_object(egg->racerID); if (racerObj != NULL) { racer = (Object_Racer *) racerObj->unk64; } - if (egg->unk8 <= 0) { + if (egg->hatchTimer <= 0) { if (racerObj != NULL) { racer->lap += 1; } - egg->unkB = 4; + egg->status = EGG_HATCHED; egg->unk4->action = 0; } - if (egg->unk8 < 540) { + if (egg->hatchTimer < 540) { func_80036040(obj, (Object_64 *) egg); } - if (racerObj != NULL && egg->unkB != 3) { - racer->unk1CF -= 1; + if (racerObj != NULL && egg->status != EGG_IN_BASE) { + racer->eggHudCounter -= 1; } break; - case 4: - racerObj = get_racer_object(egg->unkA); + case EGG_HATCHED: + racerObj = get_racer_object(egg->racerID); if (racerObj != NULL) { racer = (Object_Racer *) racerObj->unk64; if (racer->lap >= 3) { @@ -778,58 +820,76 @@ void obj_loop_collectegg(Object *obj, s32 updateRate) { } } +/** + * Egg Spawner init behaviour. + * Does nothing. +*/ void obj_init_eggcreator(UNUSED Object *obj, UNUSED LevelObjectEntry_EggCreator *entry) { } +/** + * Egg Spawner Sign init behaviour. + * Action is set to 0 if it has no egg child object. + * Spawns an egg and tracks its existence. +*/ void obj_loop_eggcreator(Object *obj, UNUSED s32 updateRate) { - unk8003564C sp20; - Object *someObj; + LevelObjectEntryCommon spawnObj; + Object *eggObj; if (obj->action == 0) { - sp20.unk2 = obj->segment.trans.x_position; - sp20.unk4 = obj->segment.trans.y_position; - sp20.unk6 = obj->segment.trans.z_position; - sp20.unk1 = 8; - sp20.unk0 = 0x34; - someObj = spawn_object(&sp20, 1); - if (someObj != NULL) { - Object_EggCreator *someObj64 = &someObj->unk64->egg_creator; - someObj64->unk4 = obj; - obj->unk78 = (s32) someObj; - someObj->segment.unk3C_a.level_entry = NULL; + spawnObj.x = obj->segment.trans.x_position; + spawnObj.y = obj->segment.trans.y_position; + spawnObj.z = obj->segment.trans.z_position; + spawnObj.size = 8; + spawnObj.objectID = 0x34; + eggObj = spawn_object(&spawnObj, 1); + if (eggObj != NULL) { + Object_EggCreator *eggSpawner = &eggObj->unk64->egg_creator; + eggSpawner->currentEgg = obj; + obj->unk78 = (s32) eggObj; + eggObj->segment.unk3C_a.level_entry = NULL; } } } +/** + * Trophy Race Sign init behaviour. + * Sets size and rotation based off spawn info. +*/ void obj_init_lighthouse_rocketsignpost(Object *obj, LevelObjectEntry_Lighthouse_RocketSignpost *entry) { - f32 phi_f0 = entry->unk9 & 0xFF; - if (phi_f0 < 10) { - phi_f0 = 10; + f32 radius = entry->radius & 0xFF; + if (radius < 10) { + radius = 10; } - phi_f0 /= 64; - obj->segment.trans.scale = obj->segment.header->scale * phi_f0; - obj->segment.trans.y_rotation = entry->unkA << 6 << 4; + radius /= 64; + obj->segment.trans.scale = obj->segment.header->scale * radius; + obj->segment.trans.y_rotation = entry->angleY << 6 << 4; if (obj->segment.unk38.byte.unk3A >= obj->segment.header->numberOfModelIds) { obj->segment.unk38.byte.unk3A = 0; } - obj->interactObj->unk14 = 1; + obj->interactObj->flags = INTERACT_FLAGS_SOLID; obj->interactObj->unk11 = 2; - obj->interactObj->unk10 = 0x14; - obj->interactObj->unk12 = 0; + obj->interactObj->hitboxRadius = 20; + obj->interactObj->pushForce = 0; } +/** + * Trophy Race Sign loop behaviour. + * Checks if the player is nearby and if they have tried to initiate dialogue. + * It then calls the function to check if it should start the lighthouse cutscene. +*/ void obj_loop_rocketsignpost(Object *obj, UNUSED s32 updateRate) { Object *playerObj; - ObjectInteraction *obj4C; + ObjectInteraction *interactObj; playerObj = get_racer_object(0); if (playerObj != NULL) { - obj4C = obj->interactObj; - if (obj4C->distance < 0xC8) { - if (playerObj == obj4C->obj) { + interactObj = obj->interactObj; + if (interactObj->distance < 200) { + if (playerObj == interactObj->obj) { // Detect if the player honks or slams into the signpost. if ((get_buttons_pressed_from_player(PLAYER_ONE) & Z_TRIG) || playerObj == obj->unk5C->unk100) { - func_8006F29C(); + begin_lighthouse_rocket_cutscene(); } } } @@ -837,31 +897,40 @@ void obj_loop_rocketsignpost(Object *obj, UNUSED s32 updateRate) { obj->interactObj->distance = 0xFF; } +/** + * Air/Water Zipper init behaviour. + * Sets scale and angle based on entry data. +*/ void obj_init_airzippers_waterzippers(Object *obj, LevelObjectEntry_AirZippers_WaterZippers *entry) { ObjectHeader *objHeader; - f32 phi_f0; + f32 radius; - phi_f0 = entry->unk9 & 0xFF; - if (phi_f0 < 10.0f) { - phi_f0 = 10.0f; + radius = entry->radius & 0xFF; + if (radius < 10.0f) { + radius = 10.0f; } objHeader = obj->segment.header; - phi_f0 /= 64; - obj->segment.trans.scale = objHeader->scale * phi_f0; - obj->segment.trans.y_rotation = entry->unkA << 6 << 4; + radius /= 64; + obj->segment.trans.scale = objHeader->scale * radius; + obj->segment.trans.y_rotation = entry->angleY << 6 << 4; if (obj->segment.unk38.byte.unk3A >= objHeader->numberOfModelIds) { obj->segment.unk38.byte.unk3A = 0; } - obj->interactObj->unk14 = 2; + obj->interactObj->flags = INTERACT_FLAGS_TANGIBLE; obj->interactObj->unk11 = 0; - obj->interactObj->unk10 = 0x14; - obj->interactObj->unk12 = 0; + obj->interactObj->hitboxRadius = 20; + obj->interactObj->pushForce = 0; if (get_filtered_cheats() & CHEAT_TURN_OFF_ZIPPERS) { gParticlePtrList_addObject(obj); } } - +/** + * Air/Water Zipper loop behaviour. + * Searches for a racer among its interactions. + * If a racer passes over it, set the value to initiate a boost on their end to true. + * Will turn invisible and intangible if there are no hovercraft or airplanes being used. +*/ void obj_loop_airzippers_waterzippers(Object *obj, UNUSED s32 updateRate) { Object *curRacerObj; Object_Racer *racer; @@ -877,24 +946,28 @@ void obj_loop_airzippers_waterzippers(Object *obj, UNUSED s32 updateRate) { } else { obj->segment.trans.unk6 &= 0xBFFF; } - if ((obj->interactObj->distance < 100) && !(obj->segment.trans.unk6 & 0x4000)) { + if (obj->interactObj->distance < 100 && !(obj->segment.trans.unk6 & 0x4000)) { racerObjs = get_racer_objects(&numObjects); for (i = 0; i < numObjects; i++) { curRacerObj = racerObjs[i]; racer = &curRacerObj->unk64->racer; - if ((racer->unk1F5 == 0) && (racer->boostTimer < 15)) { + if (racer->zipperDirCorrection == FALSE && racer->boostTimer < 15) { diffX = curRacerObj->segment.trans.x_position - obj->segment.trans.x_position; diffY = curRacerObj->segment.trans.y_position - obj->segment.trans.y_position; diffZ = curRacerObj->segment.trans.z_position - obj->segment.trans.z_position; if ((s32) sqrtf((diffX * diffX) + (diffY * diffY) + (diffZ * diffZ)) < 100) { - racer->unk1F5 = 1; - racer->unk14C = obj; + racer->zipperDirCorrection = TRUE; + racer->zipperObj = obj; } } } } } +/** + * Ground Zipper init behaviour. + * Sets scale and angle based on entry data. +*/ void obj_init_groundzipper(Object *obj, LevelObjectEntry_GroundZipper *entry) { ObjectHeader *header; f32 objScale; @@ -906,7 +979,7 @@ void obj_init_groundzipper(Object *obj, LevelObjectEntry_GroundZipper *entry) { objScale /= 64; header = obj->segment.header; obj->segment.trans.scale = header->scale * objScale; - obj->shadow->scale = header->unk4 * objScale; + obj->shadow->scale = header->shadowScale * objScale; obj->segment.trans.y_rotation = entry->rotation << 6 << 4; if (obj->segment.unk38.byte.unk3A >= obj->segment.header->numberOfModelIds) { obj->segment.unk38.byte.unk3A = 0; @@ -918,10 +991,10 @@ void obj_init_groundzipper(Object *obj, LevelObjectEntry_GroundZipper *entry) { if (obj->unk78 > 255) { obj->unk78 = 255; } - obj->interactObj->unk14 = 2; + obj->interactObj->flags = INTERACT_FLAGS_TANGIBLE; obj->interactObj->unk11 = 0; - obj->interactObj->unk10 = 0x14; - obj->interactObj->unk12 = 0; + obj->interactObj->hitboxRadius = 20; + obj->interactObj->pushForce = 0; obj->interactObj->unk16 = -0x64; obj->interactObj->unk17 = 0x64; if (get_filtered_cheats() & CHEAT_TURN_OFF_ZIPPERS) { @@ -929,6 +1002,11 @@ void obj_init_groundzipper(Object *obj, LevelObjectEntry_GroundZipper *entry) { } } +/** + * Ground Zipper loop behaviour. + * Searches for a racer among its interactions. + * If a racer passes over it, initiate a boost, which can be empowered by releasing the A button. +*/ void obj_loop_groundzipper(Object *obj, UNUSED s32 updateRate) { Object *curRacerObj; Object_Racer *racer; @@ -969,6 +1047,7 @@ void obj_loop_groundzipper(Object *obj, UNUSED s32 updateRate) { } } +// This I'm quite sure is related to time trial checkpoints. void obj_init_unknown58(Object *obj, UNUSED LevelObjectEntry_Unknown58 *entry) { obj->unk78 = 0; obj->unk7C.word = (s32) obj->segment.header; @@ -1031,7 +1110,7 @@ void obj_loop_characterflag(Object *obj, UNUSED s32 updateRate) { if (obj->unk7C.word < 0 || obj->unk7C.word >= 10) { obj->unk7C.word = 0; } - obj64->vertices = D_800DC980; + obj64->vertices = gCharacterFlagVertices; obj64->texture = (TextureHeader *) &obj->unk68[obj->unk7C.word]->texHeader; temp_t4 = (obj64->texture->width - 1) << 21; temp_t5 = (obj64->texture->height - 1) << 5; @@ -1052,14 +1131,14 @@ GLOBAL_ASM("asm/non_matchings/unknown_032760/func_80036040.s") void obj_init_stopwatchman(Object *obj, UNUSED LevelObjectEntry_StopWatchMan *entry) { Object_TT *temp; - obj->interactObj->unk14 = 1; + obj->interactObj->flags = INTERACT_FLAGS_SOLID; obj->interactObj->unk11 = 0; - obj->interactObj->unk10 = 0x1E; - obj->interactObj->unk12 = 0; + obj->interactObj->hitboxRadius = 30; + obj->interactObj->pushForce = 0; temp = &obj->unk64->tt; temp->unkD = 0xFF; temp->unk0 = 0.0f; - gTTSoundMask = 0; + gTTSoundMask = NULL; } /** @@ -1119,7 +1198,7 @@ void obj_loop_stopwatchman(Object *obj, s32 updateRate) { index = get_buttons_pressed_from_player(PLAYER_ONE); if (obj->action == TT_MODE_ROAM && distance < 300.0 && obj->unk7C.word == 0) { if (angleDiff > -0x2000 && angleDiff < 0x2000) { - if ((obj->interactObj->unk14 & 8 && racerObj == obj->interactObj->obj) || index & Z_TRIG) { + if ((obj->interactObj->flags & INTERACT_FLAGS_PUSHING && racerObj == obj->interactObj->obj) || index & Z_TRIG) { if (index & Z_TRIG) { play_char_horn_sound(racerObj, racer); } @@ -1288,9 +1367,9 @@ void obj_loop_stopwatchman(Object *obj, s32 updateRate) { void play_tt_voice_clip(u16 soundID, s32 interrupt) { if (gTTSoundMask && interrupt & 1) { func_8000488C(gTTSoundMask); //This is likely wrong and will need to be fixed - gTTSoundMask = 0; + gTTSoundMask = NULL; } - if (gTTSoundMask == 0) { + if (gTTSoundMask == NULL) { play_sound_global(soundID, &gTTSoundMask); } } @@ -1298,11 +1377,19 @@ void play_tt_voice_clip(u16 soundID, s32 interrupt) { GLOBAL_ASM("asm/non_matchings/unknown_032760/obj_init_fish.s") GLOBAL_ASM("asm/non_matchings/unknown_032760/obj_loop_fish.s") +/** + * Lava Spurt init behaviour. + * Set the timer between animations, and also set the timer to wait before playing the first animation. +*/ void obj_init_lavaspurt(Object *obj, LevelObjectEntry_LavaSpurt *entry) { - obj->unk78 = entry->unk9 * 2; - obj->unk7C.word = entry->unk8; + obj->unk78 = entry->initialTimer * 2; + obj->unk7C.word = entry->delayTimer; } +/** + * Lava Spurt loop behaviour. + * Count down until zero, then play an animation, after which, set the down time to a random amount with an offset based on spawn properties. +*/ void obj_loop_lavaspurt(Object *obj, s32 updateRate) { if (obj->unk78 > 0) { obj->unk78 -= updateRate; @@ -1348,9 +1435,9 @@ void obj_init_animator(Object *obj, LevelObjectEntry_Animator *entry, s32 arg2) obj64 = &obj->unk64->animator; levelModel = get_current_level_model(); - obj64->batchId = entry->unk8; - obj64->xSpeedFactor = entry->unk9; - obj64->ySpeedFactor = entry->unkA; + obj64->batchId = entry->batchID; + obj64->speedFactorX = entry->speedFactorX; + obj64->speedFactorY = entry->speedfactorY; obj64->segmentId = get_level_segment_index_from_position(obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position); if (arg2 == 0) { obj64->xSpeed = 0; @@ -1394,12 +1481,12 @@ void obj_loop_animator(Object *obj, s32 updateRate) { obj64 = &obj->unk64->animator; - temp = obj64->xSpeedFactor * updateRate; + temp = obj64->speedFactorX * updateRate; obj64->xSpeed += temp << 4; sp20 = obj64->xSpeed >> 4; obj64->xSpeed &= 0xF; - temp2 = obj64->ySpeedFactor * updateRate; + temp2 = obj64->speedFactorY * updateRate; obj64->ySpeed += temp2 << 4; sp1C = obj64->ySpeed >> 4; obj64->ySpeed &= 0xF; @@ -1637,10 +1724,10 @@ void obj_loop_vehicleanim(Object *obj, s32 updateRate) { } void obj_init_hittester(Object *obj, UNUSED LevelObjectEntry_HitTester *entry) { - obj->interactObj->unk14 = 0x81; + obj->interactObj->flags = INTERACT_FLAGS_SOLID | INTERACT_FLAGS_UNK_0080; obj->interactObj->unk11 = 2; - obj->interactObj->unk10 = 0x14; - obj->interactObj->unk12 = 0; + obj->interactObj->hitboxRadius = 20; + obj->interactObj->pushForce = 0; } void obj_loop_hittester(Object *obj, s32 updateRate) { @@ -1648,24 +1735,24 @@ void obj_loop_hittester(Object *obj, s32 updateRate) { } void obj_init_dynamic_lighting_object(Object *obj, UNUSED LevelObjectEntry_DynamicLightingObject *entry) { - obj->interactObj->unk14 = 1; + obj->interactObj->flags = INTERACT_FLAGS_SOLID; obj->interactObj->unk11 = 2; - obj->interactObj->unk10 = 0x14; - obj->interactObj->unk12 = 0; + obj->interactObj->hitboxRadius = 20; + obj->interactObj->pushForce = 0; } void obj_init_unknown96(Object *obj, UNUSED LevelObjectEntry_Unknown96 *entry) { - obj->interactObj->unk14 = 0x81; + obj->interactObj->flags = INTERACT_FLAGS_SOLID | INTERACT_FLAGS_UNK_0080; obj->interactObj->unk11 = 2; - obj->interactObj->unk10 = 0x14; - obj->interactObj->unk12 = 0; + obj->interactObj->hitboxRadius = 20; + obj->interactObj->pushForce = 0; } void obj_init_snowball(Object *obj, UNUSED LevelObjectEntry_Snowball *entry) { - obj->interactObj->unk14 = 1; + obj->interactObj->flags = INTERACT_FLAGS_SOLID; obj->interactObj->unk11 = 2; - obj->interactObj->unk10 = 0x14; - obj->interactObj->unk12 = 0; + obj->interactObj->hitboxRadius = 20; + obj->interactObj->pushForce = 0; } void obj_loop_snowball(Object *obj, s32 updateRate) { @@ -1735,13 +1822,13 @@ void obj_loop_animcar(Object *obj, s32 updateRate) { void obj_init_infopoint(Object *obj, LevelObjectEntry_InfoPoint *entry) { if (entry->unk8[1] != 0) { - obj->interactObj->unk14 = 0x21; + obj->interactObj->flags = INTERACT_FLAGS_SOLID | INTERACT_FLAGS_UNK_0020; } else { - obj->interactObj->unk14 = 0x22; + obj->interactObj->flags = INTERACT_FLAGS_TANGIBLE | INTERACT_FLAGS_UNK_0020; } obj->interactObj->unk11 = 0; - obj->interactObj->unk10 = 0xF; - obj->interactObj->unk12 = 0; + obj->interactObj->hitboxRadius = 15; + obj->interactObj->pushForce = 0; obj->unk78 = (entry->unk8[2] << 16) | entry->unk8[0]; // Not sure about the values here. obj->unk7C.word = entry->unk8[1]; obj->segment.trans.y_rotation = entry->unkB << 10; // Not sure about the values here. @@ -1749,7 +1836,7 @@ void obj_init_infopoint(Object *obj, LevelObjectEntry_InfoPoint *entry) { void obj_loop_infopoint(Object *obj, UNUSED s32 updateRate) { s16 player; - ObjectInteraction *obj4C; + ObjectInteraction *interactObj; Object *playerObj; if (obj->unk7C.word == 0) { @@ -1758,9 +1845,9 @@ void obj_loop_infopoint(Object *obj, UNUSED s32 updateRate) { obj->segment.trans.unk6 &= ~0x4000; } - obj4C = obj->interactObj; - if (obj4C->distance < ((obj->unk78 >> 16) & 0xFF)) { - playerObj = obj4C->obj; + interactObj = obj->interactObj; + if (interactObj->distance < ((obj->unk78 >> 16) & 0xFF)) { + playerObj = interactObj->obj; if (playerObj->segment.header->behaviorId == 1) { Object_InfoPoint *playerObj64 = &playerObj->unk64->info_point; player = playerObj64->unk0; @@ -1839,7 +1926,7 @@ void obj_loop_bombexplosion(Object *obj, s32 updateRate) { temp_t8 = (obj->unk7C.word >> 8) & 0xFF; if (obj->unk78 > 10 && temp_t8 != 0) { obj->unk7C.word ^= (temp_t8 << 8); - func_8003FC44(obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 44, 0, 1.0f, temp_t8 - 1); + func_8003FC44(obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 44, SOUND_NONE, 1.0f, temp_t8 - 1); } if (obj->unk78 < 20) { obj->segment.trans.scale = ((obj->unk78 / 20.0f) * 10.0f) + 0.5f; @@ -1862,10 +1949,10 @@ void obj_loop_bombexplosion(Object *obj, s32 updateRate) { void obj_init_teleport(Object *obj, UNUSED LevelObjectEntry_Teleport *entry) { - obj->interactObj->unk14 = 2; + obj->interactObj->flags = INTERACT_FLAGS_TANGIBLE; obj->interactObj->unk11 = 0; - obj->interactObj->unk10 = 0xF; - obj->interactObj->unk12 = 0; + obj->interactObj->hitboxRadius = 15; + obj->interactObj->pushForce = 0; if (get_settings()->cutsceneFlags & CUTSCENE_LIGHTHOUSE_ROCKET) { obj->action = 1; } @@ -1874,8 +1961,8 @@ void obj_init_teleport(Object *obj, UNUSED LevelObjectEntry_Teleport *entry) { void obj_loop_teleport(Object *obj, UNUSED s32 updateRate) { if (obj->action != 0) { LevelObjectEntry_Teleport *level_entry = &obj->segment.unk3C_a.level_entry->teleport; - if (obj->interactObj->distance < 0x78) { - func_8006F338(level_entry->unk8); + if (obj->interactObj->distance < 120) { + begin_level_teleport(level_entry->levelID); obj->action = 0; play_sound_global(SOUND_WHOOSH2, NULL); func_80000FDC(SOUND_VOICE_TT_FUTURE_FUN_LAND, 0, 1.0f); @@ -1900,10 +1987,10 @@ void obj_init_exit(Object *obj, LevelObjectEntry_Exit *entry) { exit->rotationDiff = -((exit->directionX * obj->segment.trans.x_position) + (exit->directionZ * obj->segment.trans.z_position)); exit->radius = entry->radius; exit->bossFlag = entry->bossFlag; - obj->interactObj->unk14 = 2; + obj->interactObj->flags = INTERACT_FLAGS_TANGIBLE; obj->interactObj->unk11 = 0; - obj->interactObj->unk10 = entry->radius; - obj->interactObj->unk12 = 0; + obj->interactObj->hitboxRadius = entry->radius; + obj->interactObj->pushForce = 0; } void obj_loop_exit(Object *obj, UNUSED s32 updateRate) { @@ -1976,10 +2063,10 @@ void obj_loop_setuppoint(UNUSED Object *obj, UNUSED s32 updateRate) { } void obj_init_dino_whale(Object *obj, UNUSED LevelObjectEntry_Dino_Whale *entry) { - obj->interactObj->unk14 = 1; + obj->interactObj->flags = INTERACT_FLAGS_SOLID; obj->interactObj->unk11 = 3; - obj->interactObj->unk10 = 0x14; - obj->interactObj->unk12 = 0; + obj->interactObj->hitboxRadius = 20; + obj->interactObj->pushForce = 0; } void obj_loop_dino_whale(Object *obj, s32 updateRate) { @@ -2004,10 +2091,10 @@ void obj_loop_dino_whale(Object *obj, s32 updateRate) { void obj_init_parkwarden(Object *obj, UNUSED LevelObjectEntry_Parkwarden *entry) { Object_NPC *temp; - obj->interactObj->unk14 = (u16)1; - obj->interactObj->unk11 = (u8)0; - obj->interactObj->unk10 = (u8)0x1E; - obj->interactObj->unk12 = (u8)0; + obj->interactObj->flags = INTERACT_FLAGS_SOLID; + obj->interactObj->unk11 = 0; + obj->interactObj->hitboxRadius = 30; + obj->interactObj->pushForce = 0; temp = &obj->unk64->npc; temp->unkD = 0xFF; temp->unk0 = 0.0f; @@ -2083,7 +2170,7 @@ void obj_loop_parkwarden(Object *obj, s32 updateRate) { (obj->action == NULL) && (distance < 300.0) && ( - ((obj->interactObj->unk14 & 8) && (racerObj == obj->interactObj->obj)) || + ((obj->interactObj->flags & INTERACT_FLAGS_PUSHING) && (racerObj == obj->interactObj->obj)) || (buttonsPressed & Z_TRIG) ) ) { @@ -2102,7 +2189,7 @@ void obj_loop_parkwarden(Object *obj, s32 updateRate) { var_a2 = TRUE; } } - obj->interactObj->unk14 = 1; + obj->interactObj->flags = INTERACT_FLAGS_SOLID; if ((func_80052188() || (var_a2)) && ((obj->action == 0 || obj->action == 31))) { func_800012E8(); set_music_player_voice_limit(24); @@ -2476,7 +2563,7 @@ void obj_loop_parkwarden(Object *obj, s32 updateRate) { } break; case TAJ_MODE_RACE: - obj->interactObj->unk14 = 0; + obj->interactObj->flags = INTERACT_FLAGS_NONE; obj->segment.unk38.byte.unk3B = 6; obj->segment.unk38.byte.unk39 = 0xFF; taj->animFrameF += updateRateF * 1.0; @@ -2619,7 +2706,7 @@ void obj_loop_parkwarden(Object *obj, s32 updateRate) { D_8011D4D0 = obj->segment.trans.y_position; } if (sp6B != 0) { - func_8003FC44(obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 0xC, 0, 1.0f, 0); + func_8003FC44(obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 0xC, SOUND_NONE, 1.0f, 0); } obj->segment.animFrame = taj->animFrameF * 1.0; func_80061C0C(obj); @@ -2659,7 +2746,7 @@ void obj_init_checkpoint(Object *obj, LevelObjectEntry_Checkpoint *entry, UNUSED } scale /= 64; obj->segment.trans.scale = scale; - obj->segment.trans.y_rotation = entry->yRotation << 6 << 4; // Not sure about the values here. + obj->segment.trans.y_rotation = entry->angleY << 6 << 4; // Not sure about the values here. func_80011390(); } @@ -2675,26 +2762,26 @@ void obj_loop_checkpoint(UNUSED Object *obj, UNUSED s32 updateRate) { * Sets direction and vehicleID based off spawn info. */ void obj_init_modechange(Object *obj, LevelObjectEntry_ModeChange *entry) { - f32 phi_f0; + f32 radius; Object_ModeChange *obj64; - phi_f0 = entry->unk8 & 0xFF; - if (phi_f0 < 5) { - phi_f0 = 5; + radius = entry->radius & 0xFF; + if (radius < 5) { + radius = 5; } obj64 = &obj->unk64->mode_change; - phi_f0 /= 128; - obj->segment.trans.scale = phi_f0; - obj->segment.trans.y_rotation = entry->unk9 << 6 << 4; - obj64->unk0 = sins_f(obj->segment.trans.y_rotation); - obj64->unk4 = 0.0f; - obj64->unk8 = coss_f(obj->segment.trans.y_rotation); - obj64->unkC = -((obj64->unk0 * obj->segment.trans.x_position) + (obj64->unk8 * obj->segment.trans.z_position)); - obj64->unk10 = entry->unk8; + radius /= 128; + obj->segment.trans.scale = radius; + obj->segment.trans.y_rotation = entry->angleY << 6 << 4; + obj64->directionX = sins_f(obj->segment.trans.y_rotation); + obj64->directionY = 0.0f; + obj64->directionZ = coss_f(obj->segment.trans.y_rotation); + obj64->rotationDiff = -((obj64->directionX * obj->segment.trans.x_position) + (obj64->directionZ * obj->segment.trans.z_position)); + obj64->radius = entry->radius; obj64->vehicleID = entry->vehicleID; - obj->interactObj->unk14 = 2; + obj->interactObj->flags = INTERACT_FLAGS_TANGIBLE; obj->interactObj->unk11 = 0; - obj->interactObj->unk10 = entry->unk8; - obj->interactObj->unk12 = 0; + obj->interactObj->hitboxRadius = entry->radius; + obj->interactObj->pushForce = 0; } /** @@ -2716,8 +2803,8 @@ void obj_loop_modechange(Object *obj, UNUSED s32 updateRate) { f32 dist; modeChange = (Object_ModeChange *) obj->unk64; - if (obj->interactObj->distance < modeChange->unk10) { - radiusF = modeChange->unk10; + if (obj->interactObj->distance < modeChange->radius) { + radiusF = modeChange->radius; racerObjects = get_racer_objects(&numRacers); for (i = 0; i < numRacers; i++) { racerObj = racerObjects[i]; @@ -2728,7 +2815,7 @@ void obj_loop_modechange(Object *obj, UNUSED s32 updateRate) { diffZ = racerObj->segment.trans.z_position - obj->segment.trans.z_position; dist = sqrtf((diffX * diffX) + (diffY * diffY) + (diffZ * diffZ)); if (dist < radiusF) { - dist = ((modeChange->unk0 * racerObj->segment.trans.x_position) + (modeChange->unk8 * racerObj->segment.trans.z_position) + modeChange->unkC); + dist = ((modeChange->directionX * racerObj->segment.trans.x_position) + (modeChange->directionZ * racerObj->segment.trans.z_position) + modeChange->rotationDiff); if (dist < 0.0f) { racer->unk1E0 = 0; if (modeChange->vehicleID == VEHICLE_CAR) { @@ -2760,26 +2847,26 @@ void obj_loop_modechange(Object *obj, UNUSED s32 updateRate) { void obj_init_bonus(Object *obj, LevelObjectEntry_Bonus *entry) { - f32 phi_f0; + f32 radius; Object_Bonus *obj64; - phi_f0 = entry->unk8 & 0xFF; - if (phi_f0 < 5) { - phi_f0 = 5; + radius = entry->radius & 0xFF; + if (radius < 5) { + radius = 5; } obj64 = &obj->unk64->bonus; - phi_f0 /= 128; - obj->segment.trans.scale = phi_f0; - obj->segment.trans.y_rotation = entry->unk9 << 6 << 4; - obj64->unk0 = sins_f(obj->segment.trans.y_rotation); - obj64->unk4 = 0.0f; - obj64->unk8 = coss_f(obj->segment.trans.y_rotation); - obj64->unkC = -((obj64->unk0 * obj->segment.trans.x_position) + (obj64->unk8 * obj->segment.trans.z_position)); - obj64->unk10 = entry->unk8; + radius /= 128; + obj->segment.trans.scale = radius; + obj->segment.trans.y_rotation = entry->angleY << 6 << 4; + obj64->directionX = sins_f(obj->segment.trans.y_rotation); + obj64->directionY = 0.0f; + obj64->directionZ = coss_f(obj->segment.trans.y_rotation); + obj64->rotationDiff = -((obj64->directionX * obj->segment.trans.x_position) + (obj64->directionZ * obj->segment.trans.z_position)); + obj64->radius = entry->radius; obj64->unk14 = entry->unkA; - obj->interactObj->unk14 = 2; + obj->interactObj->flags = INTERACT_FLAGS_TANGIBLE; obj->interactObj->unk11 = 0; - obj->interactObj->unk10 = entry->unk8; - obj->interactObj->unk12 = 0; + obj->interactObj->hitboxRadius = entry->radius; + obj->interactObj->pushForce = 0; } void obj_loop_bonus(Object *obj, UNUSED s32 updateRate) { @@ -2796,8 +2883,8 @@ void obj_loop_bonus(Object *obj, UNUSED s32 updateRate) { s32 i; obj64 = &obj->unk64->bonus; - if (obj->interactObj->distance < obj64->unk10) { - dist = obj64->unk10; + if (obj->interactObj->distance < obj64->radius) { + dist = obj64->radius; halfDist = dist * 0.5; racerObjects = get_racer_objects(&numberOfRacers); for (i = 0; i < numberOfRacers; i++) { @@ -2808,7 +2895,7 @@ void obj_loop_bonus(Object *obj, UNUSED s32 updateRate) { diffX = racerObj->segment.trans.x_position - obj->segment.trans.x_position; diffZ = racerObj->segment.trans.z_position - obj->segment.trans.z_position; if ((sqrtf((diffX * diffX) + (diffY * diffY) + (diffZ * diffZ)) < dist)) { - f32 temp = (obj64->unk0 * racerObj->segment.trans.x_position) + (obj64->unk8 * racerObj->segment.trans.z_position) + obj64->unkC; + f32 temp = (obj64->directionX * racerObj->segment.trans.x_position) + (obj64->directionZ * racerObj->segment.trans.z_position) + obj64->rotationDiff; if (temp < 0.0f) { if ((s32) racer->bananas < 10) { racer->bananas = 10; @@ -2821,6 +2908,7 @@ void obj_loop_bonus(Object *obj, UNUSED s32 updateRate) { } } } + void obj_init_goldenballoon(Object *obj, LevelObjectEntry_GoldenBalloon *entry) { Object_NPC *obj64; f32 scalef; @@ -2833,10 +2921,10 @@ void obj_init_goldenballoon(Object *obj, LevelObjectEntry_GoldenBalloon *entry) if (entry->balloonID == -1) { rmonPrintf("Illegal door no!!!\n"); // Did the devs just copy-paste the door init function? } - obj->interactObj->unk14 = 2; + obj->interactObj->flags = INTERACT_FLAGS_TANGIBLE; obj->interactObj->unk11 = 4; - obj->interactObj->unk10 = 20; - obj->interactObj->unk12 = 0; + obj->interactObj->hitboxRadius = 20; + obj->interactObj->pushForce = 0; scalef = entry->scale & 0xFF; if (scalef < 10.0f) { scalef = 10.0f; @@ -2858,7 +2946,7 @@ void obj_init_goldenballoon(Object *obj, LevelObjectEntry_GoldenBalloon *entry) void obj_loop_goldenballoon(Object *obj, s32 updateRate) { LevelObjectEntry *levelEntry; - ObjectInteraction *obj4C; + ObjectInteraction *interactObj; Object_Racer *racer; Object_NPC *obj64; Settings *settings; @@ -2900,9 +2988,9 @@ void obj_loop_goldenballoon(Object *obj, s32 updateRate) { } else { obj->segment.unk38.byte.unk39 = 255; } - obj4C = obj->interactObj; - if ((obj4C->distance < 45) && (isPirated == FALSE)) { - racerObj = obj4C->obj; + interactObj = obj->interactObj; + if ((interactObj->distance < 45) && (isPirated == FALSE)) { + racerObj = interactObj->obj; if ((racerObj && (racerObj->segment.header->behaviorId == 1))) { racer = &racerObj->unk64->racer; if (racer->playerIndex == PLAYER_ONE) { @@ -2972,10 +3060,10 @@ void obj_init_door(Object *obj, LevelObjectEntry_Door *entry) { obj->segment.trans.scale = obj->segment.header->scale * phi_f0; obj64->unk13 = (u8) entry->unkF; obj64->unk14 = (s8) entry->unk11; - obj->interactObj->unk14 = 0x21; + obj->interactObj->flags = INTERACT_FLAGS_SOLID | INTERACT_FLAGS_UNK_0020; obj->interactObj->unk11 = 2; - obj->interactObj->unk10 = 0x14; - obj->interactObj->unk12 = 0; + obj->interactObj->hitboxRadius = 20; + obj->interactObj->pushForce = 0; if (obj->segment.unk38.byte.unk3A >= obj->segment.header->numberOfModelIds) { obj->segment.unk38.byte.unk3A = 0; } @@ -2990,7 +3078,7 @@ void obj_init_ttdoor(Object *obj, LevelObjectEntry_TTDoor *entry) { obj->segment.unk38.byte.unk3A = 0; obj64 = &obj->unk64->tt_door; obj->segment.trans.y_rotation = entry->unk8 << 6 << 4; - obj64->unkF = entry->unkE; + obj64->doorID = entry->doorID; obj64->unk13 = entry->unkB; obj64->unk0 = obj->segment.trans.y_position; obj64->unk8 = 0; @@ -3003,10 +3091,10 @@ void obj_init_ttdoor(Object *obj, LevelObjectEntry_TTDoor *entry) { } phi_f0 /= 64; obj->segment.trans.scale = obj->segment.header->scale * phi_f0; - obj->interactObj->unk14 = 0x21; + obj->interactObj->flags = INTERACT_FLAGS_SOLID | INTERACT_FLAGS_UNK_0020; obj->interactObj->unk11 = 2; - obj->interactObj->unk10 = 0x14; - obj->interactObj->unk12 = 0; + obj->interactObj->hitboxRadius = 20; + obj->interactObj->pushForce = 0; if (obj->segment.unk38.byte.unk3A >= obj->segment.header->numberOfModelIds) { obj->segment.unk38.byte.unk3A = 0; } @@ -3027,7 +3115,7 @@ void obj_loop_ttdoor(Object *obj, s32 updateRate) { ttDoor = (Object_TTDoor *) obj->unk64; settings = get_settings(); - if (ttDoor->unkF == 0) { + if (ttDoor->doorID == 0) { obj->segment.unk38.byte.unk3A = D_800DCA94[settings->ttAmulet]; } else { obj->segment.unk38.byte.unk3A = D_800DCA9C[settings->ttAmulet]; @@ -3094,7 +3182,7 @@ void obj_loop_ttdoor(Object *obj, s32 updateRate) { } obj->interactObj->distance = 0xFF; obj->interactObj->obj = NULL; - obj->interactObj->unk14 &= 0xFFF7; + obj->interactObj->flags &= 0xFFF7; obj->unk5C->unk100 = NULL; } @@ -3125,10 +3213,10 @@ void obj_init_trigger(Object *obj, LevelObjectEntry_Trigger *entry) { obj64->unkC = -((obj64->unk0 * obj->segment.trans.x_position) + (obj64->unk8 * obj->segment.trans.z_position)); obj64->unk10 = entry->scale; obj64->unk14 = entry->unkD; - obj->interactObj->unk14 = 2; + obj->interactObj->flags = INTERACT_FLAGS_TANGIBLE; obj->interactObj->unk11 = 0; - obj->interactObj->unk10 = entry->scale; - obj->interactObj->unk12 = 0; + obj->interactObj->hitboxRadius = entry->scale; + obj->interactObj->pushForce = 0; } @@ -3193,10 +3281,10 @@ void obj_init_bridge_whaleramp(Object *obj, LevelObjectEntry_Bridge_WhaleRamp *e obj->segment.unk38.byte.unk3A = entry->unk8; obj->segment.trans.y_rotation = entry->unk9 << 6 << 4; temp->unk0 = obj->segment.trans.y_position; - obj->interactObj->unk14 = 0x21; + obj->interactObj->flags = INTERACT_FLAGS_SOLID | INTERACT_FLAGS_UNK_0020; obj->interactObj->unk11 = 2; - obj->interactObj->unk10 = 0x14; - obj->interactObj->unk12 = 0; + obj->interactObj->hitboxRadius = 20; + obj->interactObj->pushForce = 0; temp->unk4 = 0; if (obj->segment.unk38.byte.unk3A >= obj->segment.header->numberOfModelIds) { obj->segment.unk38.byte.unk3A = 0; @@ -3321,14 +3409,14 @@ void obj_loop_bridge_whaleramp(Object *obj, s32 updateRate) { obj->interactObj->distance = 255; obj->interactObj->obj = NULL; - obj->interactObj->unk14 &= 0xFFF7; + obj->interactObj->flags &= 0xFFF7; } void obj_init_rampswitch(Object *obj, LevelObjectEntry_RampSwitch *entry) { - obj->interactObj->unk14 = 2; + obj->interactObj->flags = INTERACT_FLAGS_TANGIBLE; obj->interactObj->unk11 = 0; - obj->interactObj->unk10 = 0x14; - obj->interactObj->unk12 = 0; + obj->interactObj->hitboxRadius = 20; + obj->interactObj->pushForce = 0; obj->action = entry->unk8; } @@ -3354,11 +3442,11 @@ void obj_init_fogchanger(Object *obj, LevelObjectEntry_FogChanger *entry) { } void obj_init_skycontrol(Object *obj, LevelObjectEntry_SkyControl *entry) { - obj->interactObj->unk14 = 2; + obj->interactObj->flags = INTERACT_FLAGS_TANGIBLE; obj->interactObj->unk11 = 0; - obj->interactObj->unk10 = entry->unk9; + obj->interactObj->hitboxRadius = entry->radius; obj->action = entry->unk8; - obj->unk7C.word = entry->unk9; + obj->unk7C.word = entry->radius; } void obj_loop_skycontrol(Object *obj, UNUSED s32 updateRate) { @@ -3501,7 +3589,7 @@ void obj_loop_bananacreator(Object *obj, s32 updateRate) { newBananaObj->segment.unk3C_a.level_entry = NULL; newBananaObj64 = &newBananaObj->unk64->banana; newBananaObj64->spawner = obj; - func_8003FC44(obj->segment.trans.x_position, obj->segment.trans.y_position - 14.0f, obj->segment.trans.z_position, 44, 34, 0.25f, 0); + func_8003FC44(obj->segment.trans.x_position, obj->segment.trans.y_position - 14.0f, obj->segment.trans.z_position, 44, SOUND_SELECT, 0.25f, 0); obj->unk7C.word = 0; } obj->unk78 = TIME_SECONDS(20); // Set delay to respawn banana to 20 seconds. @@ -3510,9 +3598,9 @@ void obj_loop_bananacreator(Object *obj, s32 updateRate) { void obj_init_banana(Object *obj, UNUSED LevelObjectEntry_Banana *entry) { - obj->interactObj->unk14 = 2; + obj->interactObj->flags = INTERACT_FLAGS_TANGIBLE; obj->interactObj->unk11 = 0; - obj->interactObj->unk10 = 0x1E; + obj->interactObj->hitboxRadius = 30; obj->unk7C.half.upper = 0x14; obj->unk7C.half.lower = 0x10; if (get_filtered_cheats() & CHEAT_DISABLE_BANANAS) { @@ -3529,7 +3617,7 @@ void obj_loop_banana(Object *obj, s32 updateRate) { Object *racerObj; Object_Racer *racer; f32 tempPos[3]; - f32 sp58; + f32 radius; f32 updateRateF; f32 velX; f32 velZ; @@ -3566,10 +3654,10 @@ void obj_loop_banana(Object *obj, s32 updateRate) { tempPos[0] = obj->segment.trans.x_position + (obj->segment.x_velocity * updateRateF); tempPos[1] = obj->segment.trans.y_position + (obj->segment.y_velocity * updateRateF); tempPos[2] = obj->segment.trans.z_position + (obj->segment.z_velocity * updateRateF); - sp58 = 8.0f; + radius = 8.0f; func_80031130(1, &obj->segment.trans.x_position, tempPos, -1); sp48 = 0; - func_80031600(&obj->segment.trans.x_position, tempPos, &sp58, &sp43, 1, &sp48); + func_80031600(&obj->segment.trans.x_position, tempPos, &radius, &sp43, TRUE, &sp48); obj->segment.x_velocity = (tempPos[0] - obj->segment.trans.x_position) / updateRateF; obj->segment.y_velocity = (tempPos[1] - obj->segment.trans.y_position) / updateRateF; obj->segment.z_velocity = (tempPos[2] - obj->segment.trans.z_position) / updateRateF; @@ -3596,10 +3684,10 @@ void obj_loop_banana(Object *obj, s32 updateRate) { if (sp48 > 0 && velX < 0.5 && velZ < 0.5) { obj78->unk0 = 0; } - sp58 = -10000.0f; - if (func_8002B9BC(obj, &sp58, NULL, 1) != 0 && obj->segment.trans.y_position < sp58) { + radius = -10000.0f; + if (func_8002B9BC(obj, &radius, NULL, 1) != 0 && obj->segment.trans.y_position < radius) { obj78->unk0 = 0; - obj->segment.trans.y_position = sp58; + obj->segment.trans.y_position = radius; } } sp44 = 70; @@ -3662,9 +3750,9 @@ void obj_loop_banana(Object *obj, s32 updateRate) { * Rareware duplicated this function just to check for adventure 2... */ void obj_init_silvercoin_adv2(Object *obj, UNUSED LevelObjectEntry_SilverCoinAdv2 *entry) { - obj->interactObj->unk14 = 2; + obj->interactObj->flags = INTERACT_FLAGS_TANGIBLE; obj->interactObj->unk11 = 0; - obj->interactObj->unk10 = 0x1E; + obj->interactObj->hitboxRadius = 30; obj->action = 3; obj->unk7C.word = 16; if (!is_in_tracks_mode()) { @@ -3686,9 +3774,9 @@ void obj_init_silvercoin_adv2(Object *obj, UNUSED LevelObjectEntry_SilverCoinAdv * If the flag is inactive, destroy the object. */ void obj_init_silvercoin(Object *obj, UNUSED LevelObjectEntry_SilverCoin *entry) { - obj->interactObj->unk14 = 2; + obj->interactObj->flags = INTERACT_FLAGS_TANGIBLE; obj->interactObj->unk11 = 0; - obj->interactObj->unk10 = 0x1E; + obj->interactObj->hitboxRadius = 30; obj->action = SILVER_COIN_INACTIVE; obj->unk7C.word = 0; if (!is_in_tracks_mode()) { @@ -3743,14 +3831,18 @@ void obj_loop_silvercoin(Object *obj, s32 updateRate) { } } - +/** + * Challenge Key init behaviour. + * Sets hitbox info based off spawn info. + * Deletes itself in tracks mode, or if it's already been collected. + */ void obj_init_worldkey(Object *obj, LevelObjectEntry_WorldKey *entry) { Settings *settings; - obj->interactObj->unk14 = 2; + obj->interactObj->flags = INTERACT_FLAGS_TANGIBLE; obj->interactObj->unk11 = 0; - obj->interactObj->unk10 = 0x1E; - entry->unk8 &= 0xF; - obj->action = entry->unk8; + obj->interactObj->hitboxRadius = 30; + entry->keyID &= 0xF; + obj->action = entry->keyID; settings = get_settings(); if (!is_in_tracks_mode() && !(settings->keys & (1 << obj->action))) { return; @@ -3759,6 +3851,7 @@ void obj_init_worldkey(Object *obj, LevelObjectEntry_WorldKey *entry) { } /** + * Challenge Key loop behaviour. * Rotates the key and checks to see if the player grabbed it. */ void obj_loop_worldkey(Object *worldKeyObj, s32 updateRate) { @@ -3789,14 +3882,19 @@ void obj_loop_worldkey(Object *worldKeyObj, s32 updateRate) { worldKeyObj->segment.trans.y_rotation += updateRate * 0x100; } +/** + * Weapon Balloon init behaviour. + * Sets scale and rotation based off spawn info. + * Sets model ID based on balloon ID. +*/ void obj_init_weaponballoon(Object *obj, LevelObjectEntry_WeaponBalloon *entry) { s32 cheats; Object_WeaponBalloon *obj64; f32 scalef; - obj->interactObj->unk14 = 2; + obj->interactObj->flags = INTERACT_FLAGS_TANGIBLE; obj->interactObj->unk11 = 4; - obj->interactObj->unk10 = 0x14; + obj->interactObj->hitboxRadius = 20; cheats = get_filtered_cheats(); @@ -3949,17 +4047,30 @@ void obj_loop_weaponballoon(Object *obj, s32 updateRate) { GLOBAL_ASM("asm/non_matchings/unknown_032760/obj_loop_weaponballoon.s") #endif +/** + * Balloon Burst Effect init behaviour. + * Does nothing. +*/ void obj_init_wballoonpop(UNUSED Object *obj, UNUSED LevelObjectEntry_WBalloonPop *entry) { } +/** + * Balloon Burst Effect loop behaviour. + * Does nothing. +*/ void obj_loop_wballoonpop(UNUSED Object *obj, UNUSED s32 updateRate) { } +/** + * Racer weapon init behaviour. + * Sets hitbox info so racers can interact with it. + * Also sets a timer to remove the object after that many frames. +*/ void obj_init_weapon(Object *obj, UNUSED LevelObjectEntry_Weapon *entry) { - obj->interactObj->unk14 = 2; + obj->interactObj->flags = INTERACT_FLAGS_TANGIBLE; obj->interactObj->unk11 = 0; - obj->interactObj->unk10 = 0x18; - obj->interactObj->unk12 = 0; + obj->interactObj->hitboxRadius = 24; + obj->interactObj->pushForce = 0; obj->unk78 = normalise_time(480); obj->unk7C.word = 0; } @@ -4000,7 +4111,7 @@ void handle_rocket_projectile(Object *obj, s32 updateRate) { f32 offsetZ; f32 offsetY; f32 offsetX; - f32 spC4; + f32 radius; f32 updateRateF; f32 posX; f32 posY; @@ -4008,15 +4119,15 @@ void handle_rocket_projectile(Object *obj, s32 updateRate) { f32 diffX; f32 diffY; f32 diffZ; - s32 spA4; + s32 hasCollision; s32 size; s32 numCheckpoints; Object_Racer *racer; - s8 sp97; + s8 surface; Matrix mtxf; ObjectTransform trans; - obj->interactObj->unk14 |= 0x100; + obj->interactObj->flags |= INTERACT_FLAGS_UNK_0100; weapon = (Object_Weapon *) obj->unk64; posX = obj->segment.trans.x_position; posY = obj->segment.trans.y_position; @@ -4038,12 +4149,12 @@ void handle_rocket_projectile(Object *obj, s32 updateRate) { offsetY = obj->segment.trans.y_position + (obj->segment.y_velocity * updateRateF); offsetZ = obj->segment.trans.z_position + (obj->segment.z_velocity * updateRateF); if (weapon->weaponID != WEAPON_MAGNET_LEVEL_3) { - spC4 = 16.0f; + radius = 16.0f; func_80031130(1, &obj->segment.trans.x_position, &offsetX, -1); - spA4 = 0; - sp97 = -1; - func_80031600(&obj->segment.trans.x_position, &offsetX, &spC4, &sp97, 1, &spA4); - if (spA4 > 0) { + hasCollision = FALSE; + surface = SURFACE_NONE; + func_80031600(&obj->segment.trans.x_position, &offsetX, &radius, &surface, TRUE, &hasCollision); + if (hasCollision > 0) { if (func_8002ACD4(&diffX, &diffY, &diffZ) != 0) { obj->unk78 = 0; } @@ -4063,7 +4174,7 @@ void handle_rocket_projectile(Object *obj, s32 updateRate) { if (weapon->weaponID == WEAPON_ROCKET_HOMING) { numCheckpoints = get_checkpoint_count(); if (numCheckpoints > 0) { - if (func_800185E4(weapon->checkpoint, obj, posX, posY, posZ, &weapon->checkpointDist, (u8* ) &sp97) == FALSE) { + if (func_800185E4(weapon->checkpoint, obj, posX, posY, posZ, &weapon->checkpointDist, (u8 *) &surface) == FALSE) { weapon->checkpoint++; if (weapon->checkpoint >= numCheckpoints) { weapon->checkpoint = 0; @@ -4109,7 +4220,7 @@ block_25: func_80072348(racer->playerIndex, 9); } } - func_8003FC44(obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 44, 17, 1.0f, 1); + func_8003FC44(obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 44, SOUND_EXPLOSION, 1.0f, 1); gParticlePtrList_addObject(obj); return; } @@ -4128,7 +4239,7 @@ block_37: } obj->unk78 -= updateRate; if (obj->unk78 < 0) { - func_8003FC44(obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 44, 17, 1.0f, 1); + func_8003FC44(obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 44, SOUND_EXPLOSION, 1.0f, 1); gParticlePtrList_addObject(obj); return; } @@ -4307,7 +4418,7 @@ void play_rocket_trailing_sound(Object *obj, struct Object_Weapon *weapon, u16 s GLOBAL_ASM("asm/non_matchings/unknown_032760/func_8003F2E8.s") -void func_8003FC44(f32 x, f32 y, f32 z, s32 objectID, s32 arg4, f32 scale, s32 arg6) { +void func_8003FC44(f32 x, f32 y, f32 z, s32 objectID, s32 soundID, f32 scale, s32 arg6) { LevelObjectEntry8003FC44 spawnObj; Object *newObj; @@ -4325,8 +4436,8 @@ void func_8003FC44(f32 x, f32 y, f32 z, s32 objectID, s32 arg4, f32 scale, s32 a newObj->segment.z_velocity = 0.0f; newObj->segment.trans.scale = newObj->segment.trans.scale * 3.5 * scale; } - if (arg4 != 0) { - play_sound_at_position(arg4, x, y, z, 4, NULL); + if (soundID != SOUND_NONE) { + play_sound_at_position(soundID, x, y, z, 4, NULL); } } @@ -4334,7 +4445,7 @@ void obj_init_audio(Object *obj, LevelObjectEntry_Audio *entry) { Object_Audio *obj64; obj64 = &obj->unk64->audio; - obj64->soundId = entry->unk8; + obj64->soundId = entry->soundId; obj64->unk2 = entry->unkA; obj64->unkC = entry->unkF; obj64->unk6 = entry->unkE; @@ -4395,13 +4506,13 @@ void obj_init_texscroll(Object *obj, LevelObjectEntry_TexScroll *entry, s32 arg2 obj64 = &obj->unk64->tex_scroll; levelModel = get_current_level_model(); - obj64->unk0 = entry->unk8; - if (obj64->unk0 < 0) { - obj64->unk0 = 0; + obj64->numTextures = entry->numTextures; + if (obj64->numTextures < 0) { + obj64->numTextures = 0; } numberOfTexturesInLevel = levelModel->numberOfTextures; - if (obj64->unk0 >= numberOfTexturesInLevel) { - obj64->unk0 = numberOfTexturesInLevel - 1; + if (obj64->numTextures >= numberOfTexturesInLevel) { + obj64->numTextures = numberOfTexturesInLevel - 1; } obj64->unk4 = entry->unkA; obj64->unk6 = entry->unkB; @@ -4418,12 +4529,16 @@ void obj_init_rgbalight(Object *obj, LevelObjectEntry_RgbaLight *entry, UNUSED s obj->unk64 = func_80031CAC(obj, entry); } +/** + * Floating buoy init behaviour. + * Sets hitbox data from spawn info. +*/ void obj_init_buoy_pirateship(Object *obj, UNUSED LevelObjectEntry_Buoy_PirateShip *entry, UNUSED s32 arg2) { obj->unk64 = func_800BE654(obj->segment.unk2C.half.lower, obj->segment.trans.x_position, obj->segment.trans.z_position); - obj->interactObj->unk14 = 1; + obj->interactObj->flags = INTERACT_FLAGS_SOLID; obj->interactObj->unk11 = 0; - obj->interactObj->unk10 = 0x1E; - obj->interactObj->unk12 = 0; + obj->interactObj->hitboxRadius = 30; + obj->interactObj->pushForce = 0; } /** @@ -4438,20 +4553,24 @@ void obj_loop_buoy_pirateship(Object *obj, s32 updateRate) { obj->segment.animFrame += updateRate * 8; } +/** + * Spinning log init behaviour. + * Sets scale, angle and hitbox data based off the spawn info. +*/ void obj_init_log(Object *obj, LevelObjectEntry_Log *entry, UNUSED s32 arg2) { - f32 phi_f0; + f32 radius; obj->unk64 = func_800BE654(obj->segment.unk2C.half.lower, obj->segment.trans.x_position, obj->segment.trans.z_position); - obj->interactObj->unk14 = 1; + obj->interactObj->flags = INTERACT_FLAGS_SOLID; obj->interactObj->unk11 = 2; - obj->interactObj->unk10 = 0x1E; - phi_f0 = entry->unk9 & 0xFF; - if (phi_f0 < 10.0f) { - phi_f0 = 10.0f; + obj->interactObj->hitboxRadius = 30; + radius = entry->radius & 0xFF; + if (radius < 10.0f) { + radius = 10.0f; } - phi_f0 /= 64; - obj->segment.trans.scale = obj->segment.header->scale * phi_f0; + radius /= 64; + obj->segment.trans.scale = obj->segment.header->scale * radius; obj->segment.unk38.byte.unk3A = entry->unk8; - obj->segment.trans.y_rotation = entry->unkA << 6 << 4; + obj->segment.trans.y_rotation = entry->angleY << 6 << 4; } /** @@ -4523,9 +4642,9 @@ void obj_loop_log(Object *obj, s32 updateRate) { /* Official name: weatherInit */ void obj_init_weather(Object *obj, LevelObjectEntry_Weather *entry) { - f32 temp = entry->unk8; - temp *= temp; - obj->unk78f = temp; + f32 radius = entry->radius; + radius *= radius; + obj->unk78f = radius; } /** @@ -4534,22 +4653,22 @@ void obj_init_weather(Object *obj, LevelObjectEntry_Weather *entry) { * Can be used to stop, start or change the intensity of the current weather. */ void obj_loop_weather(Object *obj, UNUSED s32 updateRate) { - s32 currViewport; - s32 numberOfObjects; - Object_Racer *curObj64; - Object **objects; - Object *curObj; - LevelObjectEntry_Weather *entry; - f32 diffX; - f32 diffZ; - s32 cur; - s32 last; - f32 dist; - - currViewport = get_current_viewport(); - objects = get_racer_objects(&numberOfObjects); - cur = -1; - if (numberOfObjects != 0) { + s32 currViewport; + s32 numberOfObjects; + Object_Racer *curObj64; + Object **objects; + Object *curObj; + LevelObjectEntry_Weather *entry; + f32 diffX; + f32 diffZ; + s32 cur; + s32 last; + f32 dist; + + currViewport = get_current_viewport(); + objects = get_racer_objects(&numberOfObjects); + cur = -1; + if (numberOfObjects != 0) { last = numberOfObjects - 1; do { curObj = objects[cur + 1]; @@ -4560,9 +4679,9 @@ void obj_loop_weather(Object *obj, UNUSED s32 updateRate) { diffZ = obj->segment.trans.z_position - curObj->segment.trans.z_position; dist = obj->unk78f; entry = (LevelObjectEntry_Weather *)obj->segment.unk3C_a.level_entry; - if (((diffX * diffX) + (diffZ * diffZ)) <= dist){ - if (((!obj->segment.unk3C_a.level_entry) && (!obj->segment.unk3C_a.level_entry)) && (!obj->segment.unk3C_a.level_entry)){} // Fakematch - changeWeather(entry->unkA * 256, entry->unkC * 256, entry->unkE * 256, entry->unk10 * 257, entry->unk11 * 257, entry->unk12); + if ((diffX * diffX) + (diffZ * diffZ) <= dist){ + if (((!obj->segment.unk3C_a.level_entry) && (!obj->segment.unk3C_a.level_entry)) && (!obj->segment.unk3C_a.level_entry)){} // Fakematch + changeWeather(entry->unkA * 256, entry->unkC * 256, entry->unkE * 256, entry->unk10 * 257, entry->unk11 * 257, entry->unk12); } } } @@ -4573,7 +4692,7 @@ void obj_init_lensflare(Object *obj, UNUSED LevelObjectEntry_LensFlare *entry) { void obj_init_lensflareswitch(Object *obj, LevelObjectEntry_LensFlareSwitch *entry, UNUSED s32 arg2) { cameraAddOverrideObject(obj); - obj->segment.trans.scale = entry->unk8; + obj->segment.trans.scale = entry->radius; obj->segment.trans.scale /= 40.0f; } @@ -4752,20 +4871,20 @@ void obj_init_frog(Object *obj, LevelObjectEntry_Frog *entry) { Object_Frog *obj64; obj64 = &obj->unk64->frog; - obj64->unk15 = entry->unkA; - obj64->unk0 = obj->segment.trans.x_position; - obj64->unk4 = obj->segment.trans.y_position; - obj64->unk8 = obj->segment.trans.z_position; - obj64->unkC = entry->unk8; - obj64->unk10 = obj64->unkC * obj64->unkC; - obj64->unk14 = 0; - obj64->unk20 = obj->segment.trans.x_position; - obj64->unk24 = obj->segment.trans.z_position; - obj64->unk19 = 0; - obj64->unk30 = 1.0f; + obj64->drumstick = entry->drumstick; + obj64->homeX = obj->segment.trans.x_position; + obj64->homeY = obj->segment.trans.y_position; + obj64->homeZ = obj->segment.trans.z_position; + obj64->homeRadius = entry->homeRadius; + obj64->homeRadiusSquare = obj64->homeRadius * obj64->homeRadius; + obj64->action = FROG_IDLE; + obj64->hopStartX = obj->segment.trans.x_position; + obj64->hopStartZ = obj->segment.trans.z_position; + obj64->squishCooldown = 0; + obj64->scaleY = 1.0f; - if (obj64->unk15) { - obj->segment.unk38.byte.unk3A = 1; + if (obj64->drumstick) { + obj->segment.unk38.byte.unk3A = TRUE; /** * Don't spawn the chicken frog if drumstick is already unlocked, or * if the player hasn't completed the trophy races yet. @@ -4774,7 +4893,7 @@ void obj_init_frog(Object *obj, LevelObjectEntry_Frog *entry) { gParticlePtrList_addObject(obj); } } else { - obj->segment.unk38.byte.unk3A = 0; + obj->segment.unk38.byte.unk3A = FALSE; } } @@ -4786,7 +4905,7 @@ void obj_init_frog(Object *obj, LevelObjectEntry_Frog *entry) { void obj_loop_frog(Object *obj, s32 updateRate) { UNUSED s32 pad0; s32 i; - s32 sp104; + s32 hopping; s32 var_v1; UNUSED u8 pad[0x90]; f32 sp6C; @@ -4804,18 +4923,19 @@ void obj_loop_frog(Object *obj, s32 updateRate) { updateRateF *= 1.2; } frog = (Object_Frog *) obj->unk64; - switch (frog->unk14) { - case 0: - sp104 = FALSE; - if (frog->unk19 > 0) { - frog->unk19 -= updateRate; + + switch (frog->action) { + case FROG_IDLE: + hopping = FALSE; + if (frog->squishCooldown > 0) { + frog->squishCooldown -= updateRate; } if (func_80016DE8(obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 96.0f, 1, (unk80042178 *) &racerObj) > 0) { diffX = obj->segment.trans.x_position - racerObj->segment.trans.x_position; diffY = obj->segment.trans.y_position - racerObj->segment.trans.y_position; diffZ = obj->segment.trans.z_position - racerObj->segment.trans.z_position; - if (frog->unk19 <= 0 && (diffX * diffX) + (diffY * diffY) + (diffZ * diffZ) < 40.0f * 40.0f) { - if (frog->unk15 != 0) { + if (frog->squishCooldown <= 0 && (diffX * diffX) + (diffY * diffY) + (diffZ * diffZ) < 40.0f * 40.0f) { + if (frog->drumstick) { play_sound_at_position(SOUND_VOICE_DRUMSTICK_POSITIVE2, obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 4, NULL); set_eeprom_settings_value(2); set_magic_code_flags(CHEAT_CONTROL_DRUMSTICK); @@ -4823,71 +4943,71 @@ void obj_loop_frog(Object *obj, s32 updateRate) { gParticlePtrList_addObject(obj); break; } else { - frog->unk14 = 2; + frog->action = 2; play_sound_at_position(SOUND_SPLAT, obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 4, NULL); } } else { - frog->unk1C = 72.0f; - if (frog->unk15 != 0) { - frog->unk1C *= 1.34f; + frog->forwardVel = 72.0f; + if (frog->drumstick) { + frog->forwardVel *= 1.34f; } - frog->unk1A = arctan2_f(-diffX, -diffZ) + 0x8000; - sp104 = TRUE; + frog->hopDirection = arctan2_f(-diffX, -diffZ) + 0x8000; + hopping = TRUE; } } else { - frog->unk16 -= updateRate; - if (frog->unk16 < 0) { - sp104 = TRUE; - frog->unk1C = get_random_number_from_range(0x28, 0x48); - frog->unk1A = get_random_number_from_range(-0x4000, 0x4000) + obj->segment.trans.y_rotation; + frog->hopTimer -= updateRate; + if (frog->hopTimer < 0) { + hopping = TRUE; + frog->forwardVel = get_random_number_from_range(40, 72); + frog->hopDirection = get_random_number_from_range(-0x4000, 0x4000) + obj->segment.trans.y_rotation; } } - if (sp104) { + if (hopping) { for(i = 0, var_v1 = FALSE; i < 4 && var_v1 == FALSE; i++) { - frog->unk28 = sins_f(frog->unk1A) * frog->unk1C; - frog->unk2C = coss_f(frog->unk1A) * -frog->unk1C; - diffX = (obj->segment.trans.x_position + frog->unk28) - frog->unk0; - diffZ = (obj->segment.trans.z_position + frog->unk2C) - frog->unk8; - if ((diffX * diffX) + (diffZ * diffZ) < frog->unk10) { + frog->hopTargetX = sins_f(frog->hopDirection) * frog->forwardVel; + frog->hopTargetZ = coss_f(frog->hopDirection) * -frog->forwardVel; + diffX = (obj->segment.trans.x_position + frog->hopTargetX) - frog->homeX; + diffZ = (obj->segment.trans.z_position + frog->hopTargetZ) - frog->homeZ; + if ((diffX * diffX) + (diffZ * diffZ) < frog->homeRadiusSquare) { var_v1 = TRUE; } else { - frog->unk1A += 0x4000; + frog->hopDirection += 0x4000; } } if (var_v1 == FALSE) { - diffX = frog->unk0 - obj->segment.trans.x_position; - diffZ = frog->unk8 - obj->segment.trans.z_position; - frog->unk1A = arctan2_f(diffX, diffZ); + diffX = frog->homeX - obj->segment.trans.x_position; + diffZ = frog->homeZ - obj->segment.trans.z_position; + frog->hopDirection = arctan2_f(diffX, diffZ); } - if (frog->unk15 != 0) { + if (frog->drumstick) { play_sound_at_position(SOUND_VOICE_DRUMSTICK_POSITIVE6, obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 4, NULL); } else { play_sound_at_position(SOUND_RIBBIT, obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 4, NULL); } - frog->unk14 = 1; - frog->unk20 = obj->segment.trans.x_position; - frog->unk24 = obj->segment.trans.z_position; - frog->unk18 = 32; - obj->segment.trans.y_rotation = -frog->unk1A; + frog->action = FROG_HOP; + frog->hopStartX = obj->segment.trans.x_position; + frog->hopStartZ = obj->segment.trans.z_position; + frog->hopFrame = 32; + obj->segment.trans.y_rotation = -frog->hopDirection; } default: break; - case 1: - frog->unk18 -= updateRate; - if (frog->unk19 > 0) { - frog->unk19 -= updateRate; + case FROG_HOP: + frog->hopFrame -= updateRate; + if (frog->squishCooldown > 0) { + frog->squishCooldown -= updateRate; } - if (frog->unk18 < 0) { - frog->unk14 = 0; - frog->unk16 = get_random_number_from_range(0, 300); - frog->unk18 = 0; + if (frog->hopFrame < 0) { + frog->action = FROG_IDLE; + frog->hopTimer = get_random_number_from_range(0, 300); + frog->hopFrame = 0; } - obj->segment.animFrame = ((32 - frog->unk18) << 3) / 3; - cosine = (coss_f(frog->unk18 << 10) + 1.0f) * 0.5f; - obj->segment.trans.x_position = frog->unk20; - obj->segment.trans.z_position = frog->unk24; - obj->segment.x_velocity = frog->unk28 * cosine; - obj->segment.z_velocity = frog->unk2C * cosine; + obj->segment.animFrame = ((32 - frog->hopFrame) << 3) / 3; + cosine = (coss_f(frog->hopFrame << 10) + 1.0f) * 0.5f; + obj->segment.trans.x_position = frog->hopStartX; + obj->segment.trans.z_position = frog->hopStartZ; + obj->segment.x_velocity = frog->hopTargetX * cosine; + obj->segment.z_velocity = frog->hopTargetZ * cosine; func_80011560(); move_object(obj, obj->segment.x_velocity, 0.0f, obj->segment.z_velocity); if (func_8002BAB0(obj->segment.unk2C.half.lower, obj->segment.trans.x_position, obj->segment.trans.z_position, &sp6C) != 0) { @@ -4895,44 +5015,44 @@ void obj_loop_frog(Object *obj, s32 updateRate) { func_80011560(); move_object(obj, 0.0f, sp6C, 0.0f); } - if (frog->unk19 <= 0 && (frog->unk18 < 6 || frog->unk18 >= 27)) { - if (func_80016DE8(obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 40.0f, 0, (unk80042178 *) &racerObj) != 0) { - if (frog->unk15 != 0) { + if (frog->squishCooldown <= 0 && (frog->hopFrame < 6 || frog->hopFrame >= 27)) { + if (func_80016DE8(obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 40.0f, 0, (unk80042178 *) &racerObj)) { + if (frog->drumstick) { play_sound_at_position(SOUND_VOICE_DRUMSTICK_POSITIVE2, obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 4, NULL); set_eeprom_settings_value(2); set_magic_code_flags(CHEAT_CONTROL_DRUMSTICK); func_8006D8A4(); gParticlePtrList_addObject(obj); } else { - frog->unk14 = 2; + frog->action = FROG_SQUISH; play_sound_at_position(SOUND_SPLAT, obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 4, NULL); } } } break; - case 2: - frog->unk30 -= 0.15f * updateRateF; - if (frog->unk30 < 0.05f) { - frog->unk30 = 0.05f; - frog->unk14 = 3; - frog->unk16 = 40; + case FROG_SQUISH: + frog->scaleY -= 0.15f * updateRateF; + if (frog->scaleY < 0.05f) { + frog->scaleY = 0.05f; + frog->action = FROG_FLAT; + frog->hopTimer = 40; } break; - case 3: - frog->unk16 -= updateRate; - if (frog->unk16 < 0) { - frog->unk14 = 4; + case FROG_FLAT: + frog->hopTimer -= updateRate; + if (frog->hopTimer < 0) { + frog->action = FROG_UNSQUISH; play_sound_at_position(SOUND_PLOP2, obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 4, NULL); } break; - case 4: - if (frog->unk30 > 1.0f) { - frog->unk30 = 1.0f; - frog->unk14 = 0; - frog->unk16 = 0; - frog->unk19 = 60; + case FROG_UNSQUISH: + if (frog->scaleY > 1.0f) { + frog->scaleY = 1.0f; + frog->action = FROG_IDLE; + frog->hopTimer = 0; + frog->squishCooldown = 60; } else { - frog->unk30 += 0.15f * updateRateF; + frog->scaleY += 0.15f * updateRateF; } break; } @@ -4957,11 +5077,17 @@ void obj_loop_pigrocketeer(Object *obj, s32 updateRate) { } } +/** + * Overworld level name init behaviour. + * Sets level name and radius based off spawn info. +*/ void obj_init_levelname(Object *obj, LevelObjectEntry_LevelName *entry) { - obj->unk78f = entry->unk9 * 8.0f; - obj->unk78f *= obj->unk78f; - obj->unk7C.half.upper = entry->unk8; - obj->unk7C.half.lower = 0; + Object_LevelName_78 *temp_s0; + temp_s0 = (Object_LevelName_78 *) &obj->unk78; + temp_s0->radius = entry->unk9 * 8.0f; + temp_s0->radius *= temp_s0->radius; + temp_s0->levelID = entry->unk8; + temp_s0->opacity = 0; if (is_in_tracks_mode()) { gParticlePtrList_addObject(obj); } @@ -4969,7 +5095,7 @@ void obj_init_levelname(Object *obj, LevelObjectEntry_LevelName *entry) { } /** - * Overworld level name behaviour. + * Overworld level name loop behaviour. * Placed at a level entrance, when a player gets near, display the level name on screen. */ void obj_loop_levelname(Object *obj, s32 updateRate) { @@ -4985,24 +5111,24 @@ void obj_loop_levelname(Object *obj, s32 updateRate) { f32 diffZ; Object_LevelName_78 *temp_s0; - racerObj = get_racer_object_by_port(0); + racerObj = get_racer_object_by_port(PLAYER_ONE); if (racerObj != NULL) { diffX = obj->segment.trans.x_position - racerObj->segment.trans.x_position; diffZ = obj->segment.trans.z_position - racerObj->segment.trans.z_position; temp_s0 = (Object_LevelName_78 *) &obj->unk78; if ((diffX * diffX) + (diffZ * diffZ) < temp_s0->radius) { - temp_s0->unk6 += updateRate * 16; - if (temp_s0->unk6 > 256) { - temp_s0->unk6 = 256; + temp_s0->opacity += updateRate * 16; + if (temp_s0->opacity > 256) { + temp_s0->opacity = 256; } } else { - temp_s0->unk6 -= updateRate * 16; - if (temp_s0->unk6 < 0) { - temp_s0->unk6 = 0; + temp_s0->opacity -= updateRate * 16; + if (temp_s0->opacity < 0) { + temp_s0->opacity = 0; } } - if (temp_s0->unk6 > 0) { - levelName = get_level_name(temp_s0->unk4); + if (temp_s0->opacity > 0) { + levelName = get_level_name(temp_s0->levelID); textWidth = (get_text_width(levelName, 0, 0) + 24) >> 1; x1 = SCREEN_WIDTH_HALF - textWidth; x2 = textWidth + SCREEN_WIDTH_HALF; @@ -5015,10 +5141,10 @@ void obj_loop_levelname(Object *obj, s32 updateRate) { } assign_dialogue_box_id(4); set_current_dialogue_box_coords(4, x1, y1, x2, y2); - set_current_dialogue_background_colour(4, 128, 64, 128, (temp_s0->unk6 * SCREEN_WIDTH_HALF) >> 8); + set_current_dialogue_background_colour(4, 128, 64, 128, (temp_s0->opacity * SCREEN_WIDTH_HALF) >> 8); set_current_text_background_colour(4, 0, 0, 0, 0); - set_dialogue_font(4, 0); - set_current_text_colour(4, 255, 255, 255, 0, (temp_s0->unk6 * 255) >> 8); + set_dialogue_font(4, FONT_COLOURFUL); + set_current_text_colour(4, 255, 255, 255, 0, (temp_s0->opacity * 255) >> 8); render_dialogue_text(4, (x2 - x1) >> 1, ((y2 - y1) >> 1) + 2, levelName, 1, 12); open_dialogue_box(4); } diff --git a/src/object_functions.h b/src/object_functions.h index 1fe84e7a..0c127fbe 100644 --- a/src/object_functions.h +++ b/src/object_functions.h @@ -51,6 +51,22 @@ enum SilvereCoinBehaviours { SILVER_COIN_INACTIVE }; +enum EggPickupStatus { + EGG_SPAWNED, + EGG_UNK_01, + EGG_MOVING, + EGG_IN_BASE, + EGG_HATCHED +}; + +enum FrogActions { + FROG_IDLE, + FROG_HOP, + FROG_SQUISH, + FROG_FLAT, + FROG_UNSQUISH +}; + typedef struct Object78_80033DD0 { s32 *unk0; s16 unk4; @@ -64,14 +80,6 @@ typedef struct unk80034B4C { s32 unk78; } unk80034B4C; -typedef struct unk8003564C { - s8 unk0; - s8 unk1; - s16 unk2; - s16 unk4; - s16 unk6; -} unk8003564C; - typedef struct unk80035E20 { u8 pad0[0x40]; s32 unk40; @@ -243,8 +251,8 @@ typedef struct Object_78_Banana { typedef struct Object_LevelName_78 { f32 radius; - s16 unk4; - s16 unk6; + s16 levelID; + s16 opacity; } Object_LevelName_78; // Unsure about the signed/unsigned with these arrays. diff --git a/src/objects.c b/src/objects.c index 8ace9506..9bc6c4eb 100644 --- a/src/objects.c +++ b/src/objects.c @@ -868,7 +868,7 @@ s32 init_object_shadow(Object *obj, ShadowData *shadow) { shadow->texture = (TextureHeader *) load_texture((s32) ((ObjectHeader *) objHeader)->unk34); objHeader = ((ObjectSegment *) obj)->header; } - shadow->scale = (f32) objHeader->unk4; + shadow->scale = objHeader->shadowScale; shadow->unk8 = -1; D_8011AE50 = (s32) shadow->texture; if (((ObjectSegment *) obj)->header->unk32 && shadow->texture == NULL) { @@ -2039,7 +2039,7 @@ void func_800155B8(void) { objsWithInteractives++; if (objInteract->unk11 != 2) { objInteract->obj = NULL; - objInteract->unk14 &= ~0x48; + objInteract->flags &= ~(INTERACT_FLAGS_COLLIDED | INTERACT_FLAGS_PUSHING); objInteract->distance = 0xFF; } } @@ -2055,18 +2055,18 @@ void func_800155B8(void) { D_8011AE6C[D_8011AE70] = obj; D_8011AE70++; } - if (objInteract->unk14 & 4) { + if (objInteract->flags & INTERACT_FLAGS_UNK_0004) { for (j = 0; j < objsWithInteractives; j++) { if (i != j) { obj2 = objList[j]; objInteract2 = obj2->interactObj; - if (objInteract2->unk14 & 3) { + if (objInteract2->flags & 3) { if (objInteract2->unk11 == 3) { func_80016748(obj, obj2); } else if (objInteract2->unk11 != 2) { xDiff = obj->segment.trans.x_position - obj2->segment.trans.x_position; zDiff = obj->segment.trans.z_position - obj2->segment.trans.z_position; - if (objInteract2->unk14 & 0x20) { + if (objInteract2->flags & INTERACT_FLAGS_UNK_0020) { var_f12 = 0x400000; //4194304.0f; } else { var_f12 = 0x40000; //262144.0f; @@ -2079,7 +2079,7 @@ void func_800155B8(void) { } } } - if (objInteract->unk14 & 0x100) { + if (objInteract->flags & INTERACT_FLAGS_UNK_0100) { for (j = 0; j < objsWithInteractives; j++) { if (i != j) { obj2 = objList[j]; @@ -2714,7 +2714,7 @@ s32 func_8001C524(f32 diffX, f32 diffY, f32 diffZ, s32 someFlag) { if (segment) { levelObj = &((segment->unk3C_a.level_entry)->ttDoor); var_a0 = 1; - if (someFlag && (sp64 != levelObj->unkE)) { + if (someFlag && (sp64 != levelObj->doorID)) { var_a0 = 0; } if ((someFlag == 2) && (levelObj->unk8 != 3)) { diff --git a/src/objects.h b/src/objects.h index 1fb05f0b..33a6972a 100644 --- a/src/objects.h +++ b/src/objects.h @@ -139,6 +139,26 @@ enum ObjectBehaviours { BHV_UNK_7F }; +enum ObjectInteractionFlags { + INTERACT_FLAGS_NONE, + INTERACT_FLAGS_SOLID = (1 << 0), + INTERACT_FLAGS_TANGIBLE = (1 << 1), + INTERACT_FLAGS_UNK_0004 = (1 << 2), + INTERACT_FLAGS_PUSHING = (1 << 3), + INTERACT_FLAGS_UNK_0010 = (1 << 4), + INTERACT_FLAGS_UNK_0020 = (1 << 5), + INTERACT_FLAGS_COLLIDED = (1 << 6), + INTERACT_FLAGS_UNK_0080 = (1 << 7), + INTERACT_FLAGS_UNK_0100 = (1 << 8), + INTERACT_FLAGS_UNK_0200 = (1 << 9), + INTERACT_FLAGS_UNK_0400 = (1 << 10), + INTERACT_FLAGS_UNK_0800 = (1 << 11), + INTERACT_FLAGS_UNK_1000 = (1 << 12), + INTERACT_FLAGS_UNK_2000 = (1 << 13), + INTERACT_FLAGS_UNK_4000 = (1 << 14), + INTERACT_FLAGS_UNK_8000 = (1 << 15), +}; + typedef struct RacerShieldGfx { s16 x_position; s16 y_position; diff --git a/src/racer.c b/src/racer.c index 9afd6dc3..abc718d3 100644 --- a/src/racer.c +++ b/src/racer.c @@ -200,7 +200,7 @@ s8 gRacerDialogueCamera; s8 gRacerInputBlocked; s8 gStartBoostTime; s16 gDialogueCameraAngle; -s8 D_8011D588[4]; +s8 gEggChallengeFlags[4]; s8 D_8011D58C[4]; GhostHeader *gGhostData[3]; s8 D_8011D59C; @@ -695,25 +695,18 @@ s32 roll_percent_chance(s32 chance) { GLOBAL_ASM("asm/non_matchings/racer/func_8004447C.s") -// Still don't know what this really is. -struct TempStruct2 { - Object *unk0[4]; - u8 pad10[0x1BF]; - s32 unk1CF; -}; - -void func_80045128(struct TempStruct2 *header) { +void func_80045128(Object **racerObjs) { Object_Racer *obj; s32 i; for (i = 0; i < 4; i++) { - obj = (Object_Racer *) header->unk0[i]->unk64; - D_8011D588[i] = obj->lap; - if (obj->unk1CF != 0) { - D_8011D588[i] |= 0x40; + obj = (Object_Racer *) racerObjs[i]->unk64; + gEggChallengeFlags[i] = obj->lap; + if (obj->eggHudCounter) { + gEggChallengeFlags[i] |= 0x40; } if (obj->held_obj != 0) { - D_8011D588[i] |= 0x80; + gEggChallengeFlags[i] |= 0x80; } } } @@ -853,13 +846,13 @@ void func_80046524(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r if (1) { } if (1) { } if (1) { } if (1) { } if (1) { } - if (racer->unk1F5 != 0) { + if (racer->zipperDirCorrection != 0) { gCurrentStickX = 0; racer->magnetTimer = 0; racer->steerAngle = 0; racer->spinout_timer = 0; racer->unk1E0 = 0; - var_v1 = racer->unk14C->segment.trans.y_rotation - (racer->steerVisualRotation & 0xFFFF); + var_v1 = racer->zipperObj->segment.trans.y_rotation - (racer->steerVisualRotation & 0xFFFF); if (var_v1 > 0x8000) { var_v1 -= 0xFFFF; } @@ -877,7 +870,7 @@ void func_80046524(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r if (racer->throttleReleased) { racer->boostType |= BOOST_SMALL_FAST; } - racer->unk1F5 = 0; + racer->zipperDirCorrection = 0; func_80072348(racer->playerIndex, 8U); } else { obj->segment.x_velocity = ((f64) obj->segment.x_velocity) * 0.75f; @@ -1136,7 +1129,7 @@ void func_80046524(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r } temp = 1.0f; racer->unk196 += (((s32) ((((f32) var_v1) * 1.75) * temp)) * updateRate) >> 6; - if (racer->unk1F5 == 0) { + if (racer->zipperDirCorrection == 0) { if ((gCurrentPlayerIndex == PLAYER_COMPUTER) && (racer->raceFinished == 0)) { var_f16 = racer->lateral_velocity * 0.25; temp_f0 = var_f16 * 0.35; @@ -1278,9 +1271,9 @@ void func_80046524(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r racer->buoyancy = 0.0f; } if ((racer->unk1E5 > 0) && (obj->segment.trans.y_position < (sp118 + var_f14))) { - obj->interactObj->unk14 |= 0x10; + obj->interactObj->flags |= 0x10; } else { - obj->interactObj->unk14 &= 0xFFEF; + obj->interactObj->flags &= 0xFFEF; } sp118 = obj->segment.trans.y_position - (sp118 + var_f14); if (racer->buoyancy > 0.0) { @@ -1812,7 +1805,7 @@ void update_camera_plane(f32 updateRate, Object* obj, Object_Racer* racer) { baseFloat2 = 110.0f; baseFloat1 = 42.0f; } - if (((!(gCurrentRacerInput & 0x10)) || racer->unk1E2 < 3) && !racer->unk1F5) { + if (((!(gCurrentRacerInput & 0x10)) || racer->unk1E2 < 3) && !racer->zipperDirCorrection) { angle = (-racer->steerVisualRotation - (racer->unk196 & 0xFFFF)) + 0x8000; if (angle > 0x8000) { angle -= 0xFFFF; @@ -2061,7 +2054,7 @@ void update_carpet(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r func_80006AC8(obj); } if (is_taj_challenge() && racer->vehicleID == VEHICLE_CARPET) { - obj->interactObj->unk14 = 0; + obj->interactObj->flags = INTERACT_FLAGS_NONE; } sp26 = obj->segment.animFrame; racer->vehicleID = VEHICLE_CARPET; @@ -2166,10 +2159,10 @@ void obj_init_racer(Object *obj, LevelObjectEntry_CharacterFlag *racer) { gDialogueCameraAngle = 0; gRacerInputBlocked = FALSE; } - obj->interactObj->unk14 = 5; + obj->interactObj->flags = INTERACT_FLAGS_SOLID | INTERACT_FLAGS_UNK_0004; obj->interactObj->unk11 = 0; - obj->interactObj->unk10 = 0xF; - obj->interactObj->unk12 = 0x14; + obj->interactObj->hitboxRadius = 15; + obj->interactObj->pushForce = 20; tempRacer->unk1EE = 0; if (!D_8011D582) { tempRacer->transparency = 255; @@ -2466,9 +2459,9 @@ void update_player_racer(Object *obj, s32 updateRate) { } } if (tempRacer->unk1E5 > 0 && obj->segment.trans.y_position < waterHeight + 5.0f) { - obj->interactObj->unk14 |= 0x10; + obj->interactObj->flags |= INTERACT_FLAGS_UNK_0010; } else { - obj->interactObj->unk14 &= 0xFFEF; + obj->interactObj->flags &= 0xFFEF; } } func_8002ACC8(0); @@ -4227,19 +4220,19 @@ void func_80055A84(Object *obj, Object_Racer *racer, UNUSED s32 updateRate) { f32 zTemp; s32 xRot; f32 angleX; - f32 *temp_v0; + f32 *racerSize; Vec3f tempPos; s32 i; - f32 sp40; + f32 radius; s8 surface; s8 shouldSquish; if (obj->segment.trans.y_position > gCurrentCourseHeight) { obj->segment.trans.y_position = gCurrentCourseHeight; } - temp_v0 =(f32 *) get_misc_asset(MISC_ASSET_UNK38); + racerSize = (f32 *) get_misc_asset(MISC_ASSET_RACER_HITBOX_SIZE); surface = -1; - sp40 = temp_v0[racer->vehicleIDPrev]; + radius = racerSize[racer->vehicleIDPrev]; tempPos.x = obj->segment.trans.x_position; tempPos.y = obj->segment.trans.y_position; tempPos.z = obj->segment.trans.z_position; @@ -4248,7 +4241,7 @@ void func_80055A84(Object *obj, Object_Racer *racer, UNUSED s32 updateRate) { sp74 = 0; flags = 0; if (racer->playerIndex != PLAYER_COMPUTER || racer->vehicleIDPrev < VEHICLE_TRICKY) { - flags = func_80017248(obj, 1, &sp74, &racer->unkD8, &tempPos.x, &sp40, &surface); + flags = func_80017248(obj, 1, &sp74, &racer->unkD8, &tempPos.x, &radius, &surface); } if (flags & 0x80) { D_8011D548 = tempPos.x - obj->segment.trans.x_position; @@ -4261,7 +4254,7 @@ void func_80055A84(Object *obj, Object_Racer *racer, UNUSED s32 updateRate) { } func_80031130(1, &racer->unkD8.x, &tempPos.x, racer->vehicleID); sp74 = 0; - racer->unk1E3 = func_80031600(&racer->unkD8.x, &tempPos.x, &sp40, &surface, 1, &sp74); + racer->unk1E3 = func_80031600(&racer->unkD8.x, &tempPos.x, &radius, &surface, TRUE, &sp74); racer->unk1E4 = flags; racer->unk1E3 |= flags; racer->unk1E2 = 0; @@ -4365,7 +4358,7 @@ void handle_racer_items(Object *obj, Object_Racer *racer, UNUSED s32 updateRate) heldObj->segment.y_velocity = obj->segment.y_velocity - 2.0; heldObj->segment.z_velocity = obj->segment.z_velocity * 0.7; heldObjData = (Vertex *) &heldObj->unk64->egg; - ((Object_64 *) heldObjData)->egg.unkB = 2; + ((Object_64 *) heldObjData)->egg.status = EGG_MOVING; racer->held_obj = NULL; racer->unk211 = 1; } @@ -6097,7 +6090,7 @@ void func_8005B818(Object *obj, Object_Racer *racer, s32 updateRate, f32 updateR sp11C = get_checkpoint_count(); if (sp11C != 0) { racer->unk1C9 = 0; - racer->unk1F5 = 0; + racer->zipperDirCorrection = 0; racer->attackType = ATTACK_NONE; racer->lateral_velocity = 0; sp94 = 20.0f; diff --git a/src/racer.h b/src/racer.h index 91e94d88..eb31ae32 100644 --- a/src/racer.h +++ b/src/racer.h @@ -210,6 +210,7 @@ void func_80042D20(Object *obj, Object_Racer *racer, s32 updateRate); void handle_racer_items(Object *obj, Object_Racer *racer, s32 updateRate); void drop_bananas(Object *obj, Object_Racer *racer, s32 number); void update_player_racer(Object *obj, s32 updateRate); +void func_80045128(Object **racerObjs); //Non Matching void set_ghost_position_and_rotation(Object *obj); diff --git a/src/vehicle_bluey.c b/src/vehicle_bluey.c index e9d9f431..f66b80bf 100644 --- a/src/vehicle_bluey.c +++ b/src/vehicle_bluey.c @@ -213,7 +213,7 @@ void update_bluey(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *ra racer->headAngleTarget = 0; } racer = (Object_Racer *) firstRacerObj->unk64; - if (obj == firstRacerObj->interactObj->obj && firstRacerObj->interactObj->unk14 & 8 && obj->segment.unk38.byte.unk3B == 1) { + if (obj == firstRacerObj->interactObj->obj && firstRacerObj->interactObj->flags & INTERACT_FLAGS_PUSHING && obj->segment.unk38.byte.unk3B == 1) { racer->attackType = ATTACK_SQUISHED; } if (racer->raceFinished) { diff --git a/src/vehicle_bubbler.c b/src/vehicle_bubbler.c index 391178a0..dc68066d 100644 --- a/src/vehicle_bubbler.c +++ b/src/vehicle_bubbler.c @@ -167,7 +167,7 @@ void update_bubbler(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer * } } racer = (Object_Racer *) firstRacerObj->unk64; - if (obj == firstRacerObj->interactObj->obj && firstRacerObj->interactObj->unk14 & 8 && obj->segment.unk38.byte.unk3B == 1) { + if (obj == firstRacerObj->interactObj->obj && firstRacerObj->interactObj->flags & INTERACT_FLAGS_PUSHING && obj->segment.unk38.byte.unk3B == 1) { racer->attackType = ATTACK_SQUISHED; } if (racer->raceFinished) { diff --git a/src/vehicle_rocket.c b/src/vehicle_rocket.c index 09266c4e..16e3119b 100644 --- a/src/vehicle_rocket.c +++ b/src/vehicle_rocket.c @@ -72,7 +72,7 @@ void update_rocket(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r if (sp2C == 0x64) { D_8011D610 = 0; } - racer->unk1F5 = 0; + racer->zipperDirCorrection = FALSE; if (racer->playerIndex == PLAYER_COMPUTER) { if (*startTimer != 100) { *startTimer -= 30; @@ -153,7 +153,7 @@ void update_rocket(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r } firstRacerObj = get_racer_object(0); racer = (Object_Racer*)firstRacerObj->unk64; - if (obj == firstRacerObj->interactObj->obj && firstRacerObj->interactObj->unk14 & 8 && obj->segment.unk38.byte.unk3B == 1) { + if (obj == firstRacerObj->interactObj->obj && firstRacerObj->interactObj->flags & INTERACT_FLAGS_PUSHING && obj->segment.unk38.byte.unk3B == 1) { racer->attackType = ATTACK_SQUISHED; } if (racer->raceFinished != 0) { diff --git a/src/vehicle_smokey.c b/src/vehicle_smokey.c index 9fd5c404..e8d4cefd 100644 --- a/src/vehicle_smokey.c +++ b/src/vehicle_smokey.c @@ -231,7 +231,7 @@ void update_smokey(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r } } racer = (Object_Racer *) firstRacerObj->unk64; - if (obj == firstRacerObj->interactObj->obj && firstRacerObj->interactObj->unk14 & 8 && obj->segment.unk38.byte.unk3B == 1) { + if (obj == firstRacerObj->interactObj->obj && firstRacerObj->interactObj->flags & INTERACT_FLAGS_PUSHING && obj->segment.unk38.byte.unk3B == 1) { racer->attackType = ATTACK_SQUISHED; } if (racer->raceFinished != FALSE) { diff --git a/src/vehicle_tricky.c b/src/vehicle_tricky.c index 474a6bfd..ff05ab5c 100644 --- a/src/vehicle_tricky.c +++ b/src/vehicle_tricky.c @@ -48,10 +48,10 @@ s8 D_8011D5CC; /******************************/ void func_8005C2F0(Object *object, unk8005C2F0 *arg1) { - object->interactObj->unk14 = 5; + object->interactObj->flags = INTERACT_FLAGS_SOLID | INTERACT_FLAGS_UNK_0004; object->interactObj->unk11 = 0; - object->interactObj->unk10 = 0x1E; - object->interactObj->unk12 = 0; + object->interactObj->hitboxRadius = 30; + object->interactObj->pushForce = 0; arg1->unkC = 0.0f; D_8011D5C0 = object->segment.trans.y_position; if (arg1->unk118 != 0) { @@ -198,7 +198,7 @@ void update_tricky(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r } func_8006F140(1); } - if (obj == firstRacerObj->interactObj->obj && firstRacerObj->interactObj->unk14 & 8 && obj->segment.unk38.byte.unk3B == 1) { + if (obj == firstRacerObj->interactObj->obj && firstRacerObj->interactObj->flags & INTERACT_FLAGS_PUSHING && obj->segment.unk38.byte.unk3B == 1) { racer->attackType = ATTACK_SQUISHED; } if (racer->raceFinished != FALSE) { diff --git a/src/vehicle_wizpig.c b/src/vehicle_wizpig.c index f35d81fa..8eb1ac76 100644 --- a/src/vehicle_wizpig.c +++ b/src/vehicle_wizpig.c @@ -70,7 +70,7 @@ void update_wizpig(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r if (sp28 == 0x64) { D_8011D600 = 0; } - racer->unk1F5 = 0; + racer->zipperDirCorrection = FALSE; if (racer->playerIndex == PLAYER_COMPUTER) { if (*startTimer != 100) { *startTimer -= 30; @@ -231,7 +231,7 @@ void update_wizpig(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r fade_when_near_camera(obj, racer, 0x28); firstRacerObj = get_racer_object(0); racer = (Object_Racer *) firstRacerObj->unk64; - if (obj == firstRacerObj->interactObj->obj && firstRacerObj->interactObj->unk14 & 8 && obj->segment.unk38.byte.unk3B == 1) { + if (obj == firstRacerObj->interactObj->obj && firstRacerObj->interactObj->flags & INTERACT_FLAGS_PUSHING && obj->segment.unk38.byte.unk3B == 1) { racer->attackType = ATTACK_SQUISHED; } if (racer->raceFinished) {