mirror of
https://github.com/HarbourMasters/SpaghettiKart
synced 2026-07-09 06:54:01 -04:00
load course dl textures from otr and move objects
This commit is contained in:
@@ -0,0 +1,526 @@
|
||||
#include <libultraship.h>
|
||||
#include "OBombKart.h"
|
||||
#include <vector>
|
||||
|
||||
#include "port/Game.h"
|
||||
#include "engine/Matrix.h"
|
||||
|
||||
extern "C" {
|
||||
#include "macros.h"
|
||||
#include "main.h"
|
||||
#include "actors.h"
|
||||
#include "math_util.h"
|
||||
#include "sounds.h"
|
||||
#include "update_objects.h"
|
||||
#include "render_player.h"
|
||||
#include "external.h"
|
||||
#include "bomb_kart.h"
|
||||
#include "collision.h"
|
||||
#include "code_80086E70.h"
|
||||
#include "render_objects.h"
|
||||
#include "code_80057C60.h"
|
||||
#include "defines.h"
|
||||
#include "code_80005FD0.h"
|
||||
#include "math_util_2.h"
|
||||
#include "collision.h"
|
||||
extern s8 gPlayerCount;
|
||||
}
|
||||
|
||||
OBombKart::OBombKart(Vec3f pos, TrackWaypoint* waypoint, uint16_t waypointIndex, uint16_t state, f32 unk_3C) {
|
||||
|
||||
Vec3f _pos = {0, 0, 0};
|
||||
|
||||
if (waypoint) { // Spawn kart on waypoint
|
||||
_pos[0] = waypoint->posX;
|
||||
_pos[1] = waypoint->posY;
|
||||
_pos[2] = waypoint->posZ;
|
||||
} else { // Spawn kart on a surface with the provided position
|
||||
|
||||
// Set height to the default value of 2000.0f unless Pos[1] is higher.
|
||||
// This allows placing these on very high surfaces.
|
||||
f32 height = (pos[1] > 2000.0f) ? pos[1] : 2000.0f;
|
||||
_pos[0] = pos[0];
|
||||
_pos[1] = spawn_actor_on_surface(pos[0], height, pos[2]);
|
||||
_pos[2] = pos[2];
|
||||
}
|
||||
|
||||
WaypointIndex = waypointIndex;
|
||||
Unk_3C = unk_3C;
|
||||
State = static_cast<States>(state);
|
||||
|
||||
Pos[0] = _pos[0];
|
||||
Pos[1] = _pos[1];
|
||||
Pos[2] = _pos[2];
|
||||
_spawnPos[0] = _pos[0];
|
||||
_spawnPos[1] = _pos[1];
|
||||
_spawnPos[2] = _pos[2];
|
||||
CenterY = _pos[1];
|
||||
WheelPos[0][0] = _pos[0];
|
||||
WheelPos[0][1] = _pos[1];
|
||||
WheelPos[0][2] = _pos[2];
|
||||
WheelPos[1][0] = _pos[0];
|
||||
WheelPos[1][1] = _pos[1];
|
||||
WheelPos[1][2] = _pos[2];
|
||||
WheelPos[2][0] = _pos[0];
|
||||
WheelPos[2][1] = _pos[1];
|
||||
WheelPos[2][2] = _pos[2];
|
||||
WheelPos[3][0] = _pos[0];
|
||||
WheelPos[3][1] = _pos[1];
|
||||
WheelPos[3][2] = _pos[2];
|
||||
check_bounding_collision(&_Collision, 2.0f, _pos[0], _pos[1], _pos[2]);
|
||||
}
|
||||
|
||||
void OBombKart::Spawn() {
|
||||
find_unused_obj_index(&ObjectIndex);
|
||||
}
|
||||
|
||||
void OBombKart::BeginPlay() {
|
||||
|
||||
}
|
||||
|
||||
void OBombKart::Tick() {
|
||||
f32 sp118;
|
||||
f32 var_f18;
|
||||
TrackWaypoint* temp_v0_2;
|
||||
f32 temp_f0_3;
|
||||
f32 sp108;
|
||||
f32 temp_f14;
|
||||
f32 temp_f16;
|
||||
f32 temp_f0;
|
||||
f32 temp_f0_4;
|
||||
u16 waypoint;
|
||||
f32 unk_3C;
|
||||
u16 someRot;
|
||||
f32 temp_f12;
|
||||
f32 temp_f12_3;
|
||||
f32 temp_f12_4;
|
||||
f32 temp_f14_2;
|
||||
f32 spAC;
|
||||
f32 temp_f16_2;
|
||||
f32 spA0;
|
||||
f32 temp_f2;
|
||||
f32 temp_f2_4;
|
||||
f32 sp94;
|
||||
f32 sp88;
|
||||
Vec3f newPos;
|
||||
States state;
|
||||
u16 bounceTimer;
|
||||
UNUSED u16 sp4C;
|
||||
u16 temp_t6;
|
||||
u16 temp_t7;
|
||||
u16 circleTimer;
|
||||
TrackWaypoint* temp_v0_4;
|
||||
Player* player;
|
||||
|
||||
state = State;
|
||||
|
||||
if (state == States::DISABLED) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (((Unk_4A != 1) || (GetCourse() == GetPodiumCeremony()))) {
|
||||
newPos[0] = Pos[0];
|
||||
newPos[1] = Pos[1];
|
||||
newPos[2] = Pos[2];
|
||||
waypoint = WaypointIndex;
|
||||
unk_3C = Unk_3C;
|
||||
someRot = SomeRot;
|
||||
bounceTimer = BounceTimer;
|
||||
circleTimer = CircleTimer;
|
||||
if ((state != States::DISABLED) && (state != States::EXPLODE)) {
|
||||
if (GetCourse() == GetPodiumCeremony()) {
|
||||
if (D_8016347E == 1) {
|
||||
player = gPlayerFour;
|
||||
temp_f0 = newPos[0] - player->pos[0];
|
||||
temp_f2 = newPos[2] - player->pos[1];
|
||||
temp_f12 = newPos[2] - player->pos[2];
|
||||
if ((((temp_f0 * temp_f0) + (temp_f2 * temp_f2)) + (temp_f12 * temp_f12)) < 25.0f) {
|
||||
circleTimer = 0;
|
||||
state = States::EXPLODE;
|
||||
player->soundEffects |= 0x400000;
|
||||
player->type &= ~0x2000;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
for (size_t i = 0; i < gPlayerCount; i++) {
|
||||
player = &gPlayers[i];
|
||||
if (!(player->effects & 0x80000000)) {
|
||||
temp_f0 = newPos[0] - player->pos[0];
|
||||
temp_f2 = newPos[1] - player->pos[1];
|
||||
temp_f12 = newPos[2] - player->pos[2];
|
||||
if ((((temp_f0 * temp_f0) + (temp_f2 * temp_f2)) + (temp_f12 * temp_f12)) < 25.0f) {
|
||||
state = States::EXPLODE;
|
||||
circleTimer = 0;
|
||||
if (GetCourse() == GetFrappeSnowland()) {
|
||||
player->soundEffects |= 0x01000000;
|
||||
} else {
|
||||
player->soundEffects |= 0x400000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
switch(state) {
|
||||
case States::CCW:
|
||||
circleTimer = (circleTimer + 356) % 360;
|
||||
temp_t6 = (circleTimer * 0xFFFF) / 360;
|
||||
sp118 = coss(temp_t6) * 25.0;
|
||||
temp_f0_3 = sins(temp_t6) * 25.0;
|
||||
temp_v0_2 = &D_80164550[0][waypoint];
|
||||
newPos[0] = temp_v0_2->posX + sp118;
|
||||
newPos[1] = CenterY + 3.5f;
|
||||
newPos[2] = temp_v0_2->posZ + temp_f0_3;
|
||||
D_80162FB0[0] = newPos[0];
|
||||
D_80162FB0[1] = newPos[1];
|
||||
D_80162FB0[2] = newPos[2];
|
||||
temp_t7 = (((circleTimer + 1) % 360) * 0xFFFF) / 360;
|
||||
sp118 = coss(temp_t7) * 25.0;
|
||||
temp_f0_3 = sins(temp_t7) * 25.0;
|
||||
D_80162FC0[0] = temp_v0_2->posX + sp118;
|
||||
D_80162FC0[1] = temp_v0_2->posY;
|
||||
D_80162FC0[2] = temp_v0_2->posZ + temp_f0_3;
|
||||
someRot = (get_angle_between_two_vectors(D_80162FB0, D_80162FC0) * 0xFFFF) / 65520;
|
||||
break;
|
||||
case States::CW:
|
||||
circleTimer = (circleTimer + 4) % 360;
|
||||
temp_t6 = (circleTimer * 0xFFFF) / 360;
|
||||
sp118 = coss(temp_t6) * 25.0;
|
||||
temp_f0_3 = sins(temp_t6) * 25.0;
|
||||
temp_v0_2 = &D_80164550[0][waypoint];
|
||||
newPos[0] = temp_v0_2->posX + sp118;
|
||||
newPos[1] = CenterY + 3.5f;
|
||||
newPos[2] = temp_v0_2->posZ + temp_f0_3;
|
||||
D_80162FB0[0] = newPos[0];
|
||||
D_80162FB0[1] = newPos[1];
|
||||
D_80162FB0[2] = newPos[2];
|
||||
temp_t7 = (((circleTimer + 1) % 360) * 0xFFFF) / 360;
|
||||
sp118 = coss(temp_t7) * 25.0;
|
||||
temp_f0_3 = sins(temp_t7) * 25.0;
|
||||
D_80162FC0[0] = temp_v0_2->posX + sp118;
|
||||
D_80162FC0[1] = temp_v0_2->posY;
|
||||
D_80162FC0[2] = temp_v0_2->posZ + temp_f0_3;
|
||||
someRot = (get_angle_between_two_vectors(D_80162FB0, D_80162FC0) * 0xFFFF) / 65520;
|
||||
break;
|
||||
case States::STATIONARY:
|
||||
newPos[1] = CenterY + 3.5f;
|
||||
someRot = 0;
|
||||
break;
|
||||
|
||||
case States::PODIUM_CEREMONY:
|
||||
if ((D_8016347C == 0) || (gNearestWaypointByPlayerId[3] < 5)) {
|
||||
break;
|
||||
} else {
|
||||
waypoint = func_8000D2B4(newPos[0], newPos[1], newPos[2], waypoint, 3);
|
||||
if ((waypoint < 0) || (gWaypointCountByPathIndex[3] < waypoint)) {
|
||||
waypoint = 0;
|
||||
}
|
||||
if (((s32) waypoint) < 0x1A) {
|
||||
temp_v0_2 = &D_80164550[3][(waypoint + 1) % gWaypointCountByPathIndex[3]];
|
||||
D_80162FB0[0] = temp_v0_2->posX;
|
||||
D_80162FB0[1] = temp_v0_2->posY;
|
||||
D_80162FB0[2] = temp_v0_2->posZ;
|
||||
temp_v0_4 = &D_80164550[3][(waypoint + 2) % gWaypointCountByPathIndex[3]];
|
||||
D_80162FC0[0] = temp_v0_4->posX;
|
||||
D_80162FC0[1] = temp_v0_4->posY;
|
||||
D_80162FC0[2] = temp_v0_4->posZ;
|
||||
someRot = (get_angle_between_two_vectors(D_80162FB0, D_80162FC0) * 0xFFFF) / 65520;
|
||||
} else {
|
||||
D_80162FB0[0] = newPos[0];
|
||||
D_80162FB0[1] = newPos[1];
|
||||
D_80162FB0[2] = newPos[2];
|
||||
D_80162FC0[0] = -2409.197f;
|
||||
D_80162FC0[1] = 0.0f;
|
||||
D_80162FC0[2] = -355.254f;
|
||||
someRot = (get_angle_between_two_vectors(D_80162FB0, D_80162FC0) * 0xFFFF) / 65520;
|
||||
}
|
||||
temp_f14 = ((D_80162FB0[0] + D_80162FC0[0]) * 0.5f) - newPos[0];
|
||||
temp_f16 = ((D_80162FB0[2] + D_80162FC0[2]) * 0.5f) - newPos[2];
|
||||
temp_f0_4 = sqrtf((temp_f14 * temp_f14) + (temp_f16 * temp_f16));
|
||||
if (temp_f0_4 > 0.01f) {
|
||||
newPos[0] += (Unk_3C * temp_f14) / temp_f0_4;
|
||||
newPos[2] += (Unk_3C * temp_f16) / temp_f0_4;
|
||||
} else {
|
||||
newPos[0] += temp_f14 / 5.0f;
|
||||
newPos[2] += temp_f16 / 5.0f;
|
||||
}
|
||||
newPos[1] = calculate_surface_height(newPos[0], 2000.0f, newPos[2], _Collision.meshIndexZX) + 3.5f;
|
||||
if (newPos[1] < (-1000.0)) {
|
||||
newPos[1] = Pos[1];
|
||||
}
|
||||
check_bounding_collision(&_Collision, 10.0f, newPos[0], newPos[1], newPos[2]);
|
||||
}
|
||||
break;
|
||||
case States::CHASE:
|
||||
if (!_target) {
|
||||
_target = OBombKart::FindTarget();
|
||||
} else {
|
||||
OBombKart::Chase(_target, newPos);
|
||||
}
|
||||
break;
|
||||
case States::EXPLODE:
|
||||
temp_v0_2 = &D_80164550[0][waypoint];
|
||||
D_80162FB0[0] = temp_v0_2->posX;
|
||||
D_80162FB0[1] = temp_v0_2->posY;
|
||||
D_80162FB0[2] = temp_v0_2->posZ;
|
||||
temp_v0_4 = &D_80164550[0][(waypoint + 1) % gWaypointCountByPathIndex[0]];
|
||||
D_80162FC0[0] = temp_v0_4->posX;
|
||||
D_80162FC0[1] = temp_v0_4->posY;
|
||||
D_80162FC0[2] = temp_v0_4->posZ;
|
||||
newPos[1] += 3.0f - (circleTimer * 0.3f);
|
||||
someRot = (get_angle_between_two_vectors(D_80162FB0, D_80162FC0) * 0xFFFF) / 65520;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (state == States::EXPLODE) {
|
||||
sp108 = 2.0f * circleTimer;
|
||||
sp118 = coss(0xFFFF - someRot) * circleTimer;
|
||||
var_f18 = sins(0xFFFF - someRot) * circleTimer;
|
||||
circleTimer++;
|
||||
temp_f2_4 = (newPos[1] - 2.3f) + (sp108 / 3.0f);
|
||||
spAC = temp_f2_4;
|
||||
spA0 = temp_f2_4;
|
||||
sp94 = temp_f2_4;
|
||||
sp88 = temp_f2_4;
|
||||
if (circleTimer >= 31) {
|
||||
state = States::DISABLED;
|
||||
}
|
||||
} else {
|
||||
sp118 = coss(0xFFFF - someRot) * 1.5f;
|
||||
var_f18 = sins(0xFFFF - someRot) * 1.5f;
|
||||
temp_f16_2 = newPos[1] - 2.3f;
|
||||
temp_f12_3 = (bounceTimer % 3) * 0.15f;
|
||||
temp_f14_2 = temp_f16_2 - temp_f12_3;
|
||||
temp_f12_4 = temp_f16_2 + temp_f12_3;
|
||||
spAC = temp_f14_2;
|
||||
sp94 = temp_f14_2;
|
||||
spA0 = temp_f12_4;
|
||||
sp88 = temp_f12_4;
|
||||
newPos[1] += sins((bounceTimer * 0x13FFEC) / 360);
|
||||
bounceTimer = (bounceTimer + 1) % 18;
|
||||
}
|
||||
|
||||
WheelPos[0][0] = (sp118 - var_f18) + newPos[0];
|
||||
WheelPos[0][1] = spAC;
|
||||
WheelPos[0][2] = (var_f18 + sp118) + newPos[2];
|
||||
WheelPos[1][0] = (var_f18 + sp118) + newPos[0];
|
||||
WheelPos[1][1] = spA0;
|
||||
WheelPos[1][2] = (var_f18 - sp118) + newPos[2];
|
||||
WheelPos[2][0] = ((-sp118) - var_f18) + newPos[0];
|
||||
WheelPos[2][1] = sp94;
|
||||
WheelPos[2][2] = ((-var_f18) + sp118) + newPos[2];
|
||||
WheelPos[3][0] = ((-sp118) + var_f18) + newPos[0];
|
||||
WheelPos[3][1] = sp88;
|
||||
WheelPos[3][2] = ((-var_f18) - sp118) + newPos[2];
|
||||
Pos[0] = newPos[0];
|
||||
Pos[1] = newPos[1];
|
||||
Pos[2] = newPos[2];
|
||||
WaypointIndex = waypoint;
|
||||
Unk_3C = unk_3C;
|
||||
SomeRot = someRot;
|
||||
State = state;
|
||||
BounceTimer = bounceTimer;
|
||||
CircleTimer = circleTimer;
|
||||
}
|
||||
}
|
||||
|
||||
void OBombKart::Draw(s32 cameraId) {
|
||||
|
||||
if (gModeSelection == BATTLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetCourse() == GetPodiumCeremony()) {
|
||||
// This isn't functionally equivallent.
|
||||
// Technicaly it should be if (kart[0].WaypointIndex < 16)
|
||||
if (WaypointIndex < 16) {
|
||||
return;
|
||||
} else {
|
||||
cameraId = PLAYER_FOUR;
|
||||
}
|
||||
}
|
||||
|
||||
Camera* camera;
|
||||
s32 temp_s4;
|
||||
s32 i;
|
||||
s32 state;
|
||||
|
||||
if (gGamestate == ENDING) {
|
||||
cameraId = 0;
|
||||
}
|
||||
camera = &camera1[cameraId];
|
||||
if (cameraId == PLAYER_ONE) {
|
||||
if (is_obj_flag_status_active(ObjectIndex, 0x00200000) != 0) {
|
||||
Unk_4A = 0;
|
||||
} else if (gGamestate != ENDING) {
|
||||
Unk_4A = 1;
|
||||
}
|
||||
set_object_flag_status_false(ObjectIndex, 0x00200000);
|
||||
}
|
||||
|
||||
// huh???
|
||||
state = State;
|
||||
if (State != States::DISABLED) {
|
||||
gObjectList[ObjectIndex].pos[0] = Pos[0];
|
||||
gObjectList[ObjectIndex].pos[1] = Pos[1];
|
||||
gObjectList[ObjectIndex].pos[2] = Pos[2];
|
||||
temp_s4 = func_8008A364(ObjectIndex, cameraId, 0x31C4U, 0x000001F4);
|
||||
if (is_obj_flag_status_active(ObjectIndex, VISIBLE) != 0) {
|
||||
set_object_flag_status_true(ObjectIndex, 0x00200000);
|
||||
D_80183E80[0] = 0;
|
||||
D_80183E80[1] = func_800418AC(Pos[0], Pos[2], camera->pos);
|
||||
D_80183E80[2] = 0x8000;
|
||||
func_800563DC(ObjectIndex, cameraId, 0x000000FF);
|
||||
OBombKart::SomeRender(camera->pos);
|
||||
if (((u32) temp_s4 < 0x4E21U) && (state != BOMB_STATE_EXPLODED)) {
|
||||
OBombKart::LoadMtx();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OBombKart::DrawBattle(s32 cameraId) {
|
||||
if (gModeSelection != BATTLE) {
|
||||
return;
|
||||
}
|
||||
Player* temp_v0;
|
||||
s32 temp_s1;
|
||||
s32 playerId;
|
||||
Object* object;
|
||||
|
||||
for (playerId = 0; playerId < gPlayerCount; playerId++) {
|
||||
object = &gObjectList[ObjectIndex];
|
||||
if (object->state != 0) {
|
||||
temp_s1 = object->primAlpha;
|
||||
temp_v0 = &gPlayerOne[playerId];
|
||||
object->pos[0] = temp_v0->pos[0];
|
||||
object->pos[1] = temp_v0->pos[1] - 2.0;
|
||||
object->pos[2] = temp_v0->pos[2];
|
||||
object->surfaceHeight = temp_v0->unk_074;
|
||||
func_800563DC(ObjectIndex, cameraId, temp_s1);
|
||||
func_8005669C(ObjectIndex, cameraId, temp_s1);
|
||||
func_800568A0(ObjectIndex, cameraId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OBombKart::SomeRender(Vec3f arg1) {
|
||||
D_80183E80[0] = 0;
|
||||
D_80183E80[2] = 0x8000;
|
||||
gSPDisplayList(gDisplayListHead++, (Gfx*)D_0D0079C8);
|
||||
load_texture_block_rgba16_mirror((u8*) D_0D02AA58, 0x00000010, 0x00000010);
|
||||
D_80183E80[1] = func_800418AC(WheelPos[0][0], WheelPos[0][2], arg1);
|
||||
func_800431B0(WheelPos[0], D_80183E80, 0.15f, (Vtx*)common_vtx_rectangle);
|
||||
D_80183E80[1] = func_800418AC(WheelPos[1][0], WheelPos[1][2], arg1);
|
||||
func_800431B0(WheelPos[1], D_80183E80, 0.15f, (Vtx*)common_vtx_rectangle);
|
||||
D_80183E80[1] = func_800418AC(WheelPos[2][0], WheelPos[2][2], arg1);
|
||||
func_800431B0(WheelPos[2], D_80183E80, 0.15f, (Vtx*)common_vtx_rectangle);
|
||||
D_80183E80[1] = func_800418AC(WheelPos[3][0], WheelPos[3][2], arg1);
|
||||
func_800431B0(WheelPos[3], D_80183E80, 0.15f, (Vtx*)common_vtx_rectangle);
|
||||
gSPTexture(gDisplayListHead++, 1, 1, 0, G_TX_RENDERTILE, G_OFF);
|
||||
}
|
||||
|
||||
void OBombKart::LoadMtx() {
|
||||
Mat4 mat;
|
||||
|
||||
D_80183E50[0] = Pos[0];
|
||||
D_80183E50[1] = CenterY + 1.0;
|
||||
D_80183E50[2] = Pos[2];
|
||||
set_transform_matrix(mat, _Collision.orientationVector, D_80183E50, 0U, 0.5f);
|
||||
//convert_to_fixed_point_matrix(&gGfxPool->mtxHud[gMatrixHudCount], mat);
|
||||
|
||||
AddHudMatrix(mat, G_MTX_LOAD | G_MTX_NOPUSH | G_MTX_MODELVIEW);
|
||||
|
||||
// gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&gGfxPool->mtxHud[gMatrixHudCount++]),
|
||||
// G_MTX_LOAD | G_MTX_NOPUSH | G_MTX_MODELVIEW);
|
||||
gSPDisplayList(gDisplayListHead++, (Gfx*)D_0D007B98);
|
||||
}
|
||||
|
||||
void OBombKart::Waypoint(s32 screenId) {
|
||||
s32 playerWaypoint;
|
||||
s32 bombWaypoint;
|
||||
s32 waypointDiff;
|
||||
|
||||
playerWaypoint = gNearestWaypointByPlayerId[screenId];
|
||||
playerHUD[screenId].unk_74 = 0;
|
||||
if ((State == States::EXPLODE) || (State == States::DISABLED)) { return; };
|
||||
bombWaypoint = WaypointIndex;
|
||||
waypointDiff = bombWaypoint - playerWaypoint;
|
||||
if ((waypointDiff < -5) || (waypointDiff > 0x1E)) { return; };
|
||||
playerHUD[screenId].unk_74 = 1;
|
||||
}
|
||||
|
||||
void OBombKart::Collision(s32 playerId, Player* player) {
|
||||
|
||||
}
|
||||
|
||||
Player* OBombKart::FindTarget() {
|
||||
for (size_t i = 0; i < NUM_PLAYERS; i++) {
|
||||
if (gPlayers[i].type & PLAYER_HUMAN) {
|
||||
if (is_within_distance_2d(Pos[0], Pos[2], gPlayers[i].pos[0], gPlayers[i].pos[2], 500)) {
|
||||
return &gPlayers[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void OBombKart::Chase(Player* player, Vec3f pos) {
|
||||
const f32 speed = 2.7f; // Speed the kart uses in a chase
|
||||
|
||||
if (!player) return; // Ensure player is valid
|
||||
|
||||
// Calculate the directional vector toward the player
|
||||
Vec3f direction;
|
||||
direction[0] = player->pos[0] - pos[0];
|
||||
direction[1] = player->pos[1] - pos[1];
|
||||
direction[2] = player->pos[2] - pos[2];
|
||||
|
||||
// Calculate the distance in the XZ plane
|
||||
f32 xz_dist = sqrtf((direction[0] * direction[0]) + (direction[2] * direction[2]));
|
||||
|
||||
// Reset distance
|
||||
if (xz_dist > 700.0f) {
|
||||
_target = NULL;
|
||||
pos[0] = _spawnPos[0];
|
||||
pos[1] = _spawnPos[1];
|
||||
pos[2] = _spawnPos[2];
|
||||
return;
|
||||
}
|
||||
|
||||
// Break off the chase if player has boo item
|
||||
if (player->effects & BOO_EFFECT) {
|
||||
_target = NULL;
|
||||
pos[0] = _spawnPos[0];
|
||||
pos[1] = _spawnPos[1];
|
||||
pos[2] = _spawnPos[2];
|
||||
return;
|
||||
}
|
||||
|
||||
if (xz_dist > 0.0f) {
|
||||
|
||||
// Normalize the direction vector in the XZ plane
|
||||
direction[0] /= xz_dist;
|
||||
direction[2] /= xz_dist;
|
||||
|
||||
// Scale the movement by a fixed step size
|
||||
pos[0] += direction[0] * speed;
|
||||
pos[2] += direction[2] * speed;
|
||||
}
|
||||
|
||||
Vec3f newPosition;
|
||||
newPosition[0] = pos[0];
|
||||
newPosition[1] = pos[1];
|
||||
newPosition[2] = pos[2];
|
||||
|
||||
newPosition[1] = calculate_surface_height(pos[0], 2000.0f, pos[2], _Collision.meshIndexZX) + 3.5f;
|
||||
|
||||
pos[0] = newPosition[0];
|
||||
pos[1] = newPosition[1];
|
||||
pos[2] = newPosition[2];
|
||||
|
||||
check_bounding_collision(&_Collision, 10.0f, pos[0], pos[1], pos[2]);
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
|
||||
#include <libultraship.h>
|
||||
#include "src/engine/vehicles/Vehicle.h"
|
||||
#include <vector>
|
||||
#include "engine/Matrix.h"
|
||||
|
||||
extern "C" {
|
||||
#include "macros.h"
|
||||
#include "main.h"
|
||||
#include "vehicles.h"
|
||||
#include "waypoints.h"
|
||||
#include "common_structs.h"
|
||||
#include "objects.h"
|
||||
}
|
||||
|
||||
/**
|
||||
* Used in VS mode
|
||||
*
|
||||
* This differs from the other vehicle classes in that it does not get added to the standard actor list
|
||||
* So this is sort of its own thing. Draw call in different place too.
|
||||
*/
|
||||
class OBombKart {
|
||||
private:
|
||||
enum States : uint16_t { // 0,1,3,5
|
||||
DISABLED,
|
||||
CCW,
|
||||
CW,
|
||||
STATIONARY,
|
||||
CHASE,
|
||||
EXPLODE,
|
||||
PODIUM_CEREMONY,
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
const char* Type;
|
||||
|
||||
Vec3f Pos;
|
||||
Vec3f WheelPos[4]; //! @todo Turn WheelPos into a struct
|
||||
f32 Unk_3C;
|
||||
u16 SomeRot; // Some angle
|
||||
u16 WaypointIndex; // The waypoint the kart circles
|
||||
States State = States::DISABLED;
|
||||
u16 BounceTimer = 0;
|
||||
u16 CircleTimer = 0;
|
||||
u16 Unk_4A = 0;
|
||||
s16 Unk_4C = 1;
|
||||
f32 CenterY; // Center of the circle
|
||||
s32 ObjectIndex = 0; // Index into gObjectList
|
||||
Collision _Collision;
|
||||
|
||||
// Set waypoint to NULL if using a spawn position and not a waypoint.
|
||||
explicit OBombKart(Vec3f pos, TrackWaypoint* waypoint, uint16_t waypointIndex, uint16_t state, f32 unk_3C);
|
||||
|
||||
void Spawn();
|
||||
void BeginPlay();
|
||||
void Tick();
|
||||
void Draw(s32 playerId);
|
||||
void DrawBattle(s32 cameraId);
|
||||
void Collision(s32 playerId, Player* player);
|
||||
void SomeRender(Vec3f arg1);
|
||||
void LoadMtx();
|
||||
void Waypoint(s32 screenId);
|
||||
private:
|
||||
Player* FindTarget();
|
||||
void Chase(Player*, Vec3f pos);
|
||||
|
||||
Vec3f _spawnPos;
|
||||
Player* _target = NULL;
|
||||
|
||||
|
||||
};
|
||||
@@ -0,0 +1,383 @@
|
||||
#include <libultraship.h>
|
||||
#include <libultra/gbi.h>
|
||||
#include "OPenguin.h"
|
||||
#include <vector>
|
||||
|
||||
#include "port/Game.h"
|
||||
|
||||
extern "C" {
|
||||
#include "macros.h"
|
||||
#include "main.h"
|
||||
#include "actors.h"
|
||||
#include "math_util.h"
|
||||
#include "sounds.h"
|
||||
#include "update_objects.h"
|
||||
#include "render_player.h"
|
||||
#include "external.h"
|
||||
#include "bomb_kart.h"
|
||||
#include "collision.h"
|
||||
#include "code_80086E70.h"
|
||||
#include "render_objects.h"
|
||||
#include "code_80057C60.h"
|
||||
#include "defines.h"
|
||||
#include "code_80005FD0.h"
|
||||
#include "math_util_2.h"
|
||||
#include "collision.h"
|
||||
#include "assets/bowsers_castle_data.h"
|
||||
#include "ceremony_and_credits.h"
|
||||
#include "objects.h"
|
||||
#include "update_objects.h"
|
||||
#include "render_objects.h"
|
||||
#include "course_offsets.h"
|
||||
#include "data/some_data.h"
|
||||
extern s8 gPlayerCount;
|
||||
}
|
||||
|
||||
OPenguin::OPenguin(s32 i, Vec3f pos, u16 direction, PenguinType type, Behaviour behaviour) {
|
||||
if (i >= 32) {
|
||||
printf("MAX penguin REACHED (32), skipping\n");
|
||||
return;
|
||||
}
|
||||
_idx = i;
|
||||
_type = type;
|
||||
_bhv = behaviour;
|
||||
|
||||
s32 objectIndex = indexObjectList1[i];
|
||||
init_object(objectIndex, 0);
|
||||
|
||||
Object *object = &gObjectList[objectIndex];
|
||||
object->origin_pos[0] = pos[0] * xOrientation;
|
||||
object->origin_pos[1] = pos[1];
|
||||
object->origin_pos[2] = pos[2];
|
||||
object->unk_0C6 = direction;
|
||||
|
||||
switch(type) {
|
||||
case PenguinType::CHICK:
|
||||
object->surfaceHeight = 5.0f;
|
||||
object->sizeScaling = 0.04f;
|
||||
object->boundingBoxSize = 4;
|
||||
break;
|
||||
case PenguinType::ADULT:
|
||||
object->surfaceHeight = -80.0f;
|
||||
object->sizeScaling = 0.08f;
|
||||
object->boundingBoxSize = 4;
|
||||
break;
|
||||
case PenguinType::CREDITS:
|
||||
object->surfaceHeight = -80.0f;
|
||||
object->sizeScaling = 0.08f;
|
||||
object->sizeScaling = 0.15f;
|
||||
break;
|
||||
case PenguinType::EMPEROR:
|
||||
object->sizeScaling = 0.2f;
|
||||
object->boundingBoxSize = 0x000C;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void OPenguin::Tick(void) {
|
||||
s32 objectIndex;
|
||||
|
||||
objectIndex = indexObjectList1[_idx];
|
||||
if (gObjectList[objectIndex].state != 0) {
|
||||
if (_type == PenguinType::EMPEROR) {
|
||||
OPenguin::EmperorPenguin(objectIndex);
|
||||
} else {
|
||||
OPenguin::OtherPenguin(objectIndex);
|
||||
}
|
||||
|
||||
OPenguin::Behaviours(objectIndex, _idx);
|
||||
}
|
||||
if (func_80072320(objectIndex, 1) != 0) {
|
||||
func_80089820(objectIndex, 1.75f, 1.5f, 0x1900A046U);
|
||||
} else if (func_80072320(objectIndex, 8) != 0) {
|
||||
func_80089820(objectIndex, 1.3f, 1.0f, 0x1900A046U);
|
||||
} else {
|
||||
func_80089820(objectIndex, 1.5f, 1.25f, 0x1900A046U);
|
||||
}
|
||||
if ((is_obj_flag_status_active(objectIndex, 0x02000000) != 0) &&
|
||||
(func_80072354(objectIndex, 0x00000020) != 0)) {
|
||||
func_800722A4(objectIndex, 0x00000060);
|
||||
set_object_flag_status_false(objectIndex, 0x02000000);
|
||||
}
|
||||
}
|
||||
|
||||
void OPenguin::Draw(s32 cameraId) {
|
||||
s32 objectIndex;
|
||||
s32 temp_s1;
|
||||
s32 drawDistance;
|
||||
u16 var_s1;
|
||||
u32 var_s3;
|
||||
|
||||
if (gPlayerCountSelection1 == 1) {
|
||||
var_s3 = 0x0003D090;
|
||||
} else if (gPlayerCountSelection1 == 2) {
|
||||
var_s3 = 0x00027100;
|
||||
} else {
|
||||
var_s3 = 0x00015F90;
|
||||
}
|
||||
|
||||
objectIndex = indexObjectList1[_idx];
|
||||
if (gObjectList[objectIndex].state >= 2) {
|
||||
if (gPlayerCountSelection1 == 1) {
|
||||
var_s1 = 0x4000;
|
||||
if (_idx == 0) {
|
||||
drawDistance = 0x000005DC;
|
||||
} else if (func_80072320(objectIndex, 8) != 0) {
|
||||
drawDistance = 0x00000320;
|
||||
} else {
|
||||
drawDistance = 0x000003E8;
|
||||
}
|
||||
} else {
|
||||
if (func_80072320(objectIndex, 8) != 0) {
|
||||
drawDistance = 0x000001F4;
|
||||
var_s1 = 0x4000;
|
||||
} else {
|
||||
drawDistance = 0x00000258;
|
||||
var_s1 = 0x5555;
|
||||
}
|
||||
}
|
||||
temp_s1 = func_8008A364(objectIndex, cameraId, var_s1, drawDistance);
|
||||
if (is_obj_flag_status_active(objectIndex, VISIBLE) != 0) {
|
||||
func_800557B4(objectIndex, (u32) temp_s1, var_s3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OPenguin::Behaviours(s32 objectIndex, s32 arg1) {
|
||||
Object* object;
|
||||
|
||||
object = &gObjectList[objectIndex];
|
||||
switch (_bhv) {
|
||||
case 1: // emperor
|
||||
func_80085080(objectIndex);
|
||||
break;
|
||||
case 2:
|
||||
func_8008502C(objectIndex, arg1);
|
||||
break;
|
||||
case 3:
|
||||
func_80084D2C(objectIndex, 0);
|
||||
break;
|
||||
case 4:
|
||||
func_80084D2C(objectIndex, 1);
|
||||
break;
|
||||
case 5:
|
||||
func_80084D2C(objectIndex, 2);
|
||||
break;
|
||||
case 6:
|
||||
func_80084D2C(objectIndex, 3);
|
||||
break;
|
||||
}
|
||||
if (func_80072320(objectIndex, 0x00000020) != 0) {
|
||||
if (func_80072320(objectIndex, 0x00000040) != 0) {
|
||||
func_800722CC(objectIndex, 0x00000040);
|
||||
object->unk_084[6] = 0;
|
||||
object->unk_084[7] = 0x0096;
|
||||
}
|
||||
if (object->unk_084[7] == 0) {
|
||||
func_800722CC(objectIndex, 0x00000020);
|
||||
} else {
|
||||
object->unk_084[7]--;
|
||||
object->orientation[0] = object->direction_angle[0];
|
||||
object->orientation[1] += 0x2000;
|
||||
object->orientation[2] = object->direction_angle[2];
|
||||
}
|
||||
} else {
|
||||
object->orientation[0] = object->direction_angle[0];
|
||||
object->orientation[1] = object->direction_angle[1];
|
||||
object->orientation[2] = object->direction_angle[2];
|
||||
}
|
||||
}
|
||||
|
||||
void OPenguin::EmperorPenguin(s32 objectIndex) {
|
||||
switch (gObjectList[objectIndex].state) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
OPenguin::InitEmperorPenguin(objectIndex);
|
||||
break;
|
||||
case 2:
|
||||
func_80072E54(objectIndex, 0, gObjectList[objectIndex].type, 1, 0, -1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OPenguin::InitEmperorPenguin(s32 objectIndex) {
|
||||
Object* object;
|
||||
|
||||
object = &gObjectList[objectIndex];
|
||||
object->unk_0D8 = 0;
|
||||
object->model = (Gfx*) d_course_sherbet_land_unk_data1;
|
||||
object->vertex = (Vtx*) d_course_sherbet_land_unk_data11;
|
||||
//object->sizeScaling = 0.2f;
|
||||
//object->boundingBoxSize = 0x000C;
|
||||
object->unk_09C = 1;
|
||||
set_obj_direction_angle(objectIndex, 0U, 0U, 0U);
|
||||
object->unk_0DD = 1;
|
||||
func_80086EF0(objectIndex);
|
||||
object->spline = D_800E672C[0];
|
||||
set_object_flag_status_true(objectIndex, 0x04000800);
|
||||
object->type = get_animation_length(d_course_sherbet_land_unk_data11, 0);
|
||||
object_next_state(objectIndex);
|
||||
}
|
||||
|
||||
void OPenguin::OtherPenguin(s32 objectIndex) {
|
||||
Object* object;
|
||||
|
||||
object = &gObjectList[objectIndex];
|
||||
switch (object->state) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
OPenguin::InitOtherPenguin(objectIndex);
|
||||
break;
|
||||
case 2:
|
||||
func_80072E54(objectIndex, 0, (s32) object->type, (s32) object->unk_09C, 0, -1);
|
||||
if (func_80072354(objectIndex, 0x00000020) != 0) {
|
||||
if (object->unk_084[6] == 0) {
|
||||
object->unk_084[6] = random_int(0x005AU) + 0x5A;
|
||||
func_800722A4(objectIndex, 0x00000080);
|
||||
} else {
|
||||
object->unk_084[6]--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
func_80072E54(objectIndex, 0, object->type, 1, 0, 0);
|
||||
break;
|
||||
case 4:
|
||||
func_800722CC(objectIndex, 2);
|
||||
object_next_state(objectIndex);
|
||||
break;
|
||||
}
|
||||
if (func_80072320(objectIndex, 0x00000020) != 0) {
|
||||
if (object->unk_084[6] == 0) {
|
||||
func_800722A4(objectIndex, 0x00000080);
|
||||
object->unk_084[6] = 0x0010;
|
||||
} else {
|
||||
object->unk_084[6]--;
|
||||
}
|
||||
}
|
||||
if (func_80072320(objectIndex, 0x00000080) != 0) {
|
||||
func_800722CC(objectIndex, 0x00000080);
|
||||
if (func_80072320(objectIndex, 0x00000010) != 0) {
|
||||
func_800C98B8(object->pos, object->velocity, SOUND_ARG_LOAD(0x19, 0x00, 0x70, 0x49));
|
||||
} else {
|
||||
func_800C98B8(object->pos, object->velocity, SOUND_ARG_LOAD(0x19, 0x00, 0x70, 0x17));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OPenguin::InitOtherPenguin(s32 objectIndex) {
|
||||
Object* object;
|
||||
|
||||
object = &gObjectList[objectIndex];
|
||||
object->unk_0D8 = 0;
|
||||
object->model = (Gfx*) d_course_sherbet_land_unk_data1;
|
||||
object->vertex = (Vtx*) d_course_sherbet_land_unk_data11;
|
||||
//object->boundingBoxSize = 4;
|
||||
object->unk_09C = 2;
|
||||
object->unk_04C = random_int(0x012CU);
|
||||
set_object_flag_status_true(objectIndex, 0x04000220);
|
||||
|
||||
switch(_bhv) {
|
||||
case Behaviour::CIRCLE:
|
||||
object->unk_01C[1] = Diameter;
|
||||
object->unk_0C4 = (_idx << 0xF) & 0xFFFF;
|
||||
//object->unk_0DD = 2;
|
||||
func_800722A4(objectIndex, 8);
|
||||
break;
|
||||
case Behaviour::SLIDE3:
|
||||
case Behaviour::SLIDE4:
|
||||
case Behaviour::SLIDE6:
|
||||
case Behaviour::STRUT:
|
||||
|
||||
if (gIsMirrorMode) {
|
||||
object->unk_0C6 = MirrorModeAngleOffset;
|
||||
}
|
||||
|
||||
set_obj_direction_angle(objectIndex, 0U, object->unk_0C6 + 0x8000, 0U);
|
||||
func_800722A4(objectIndex, 20);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((_idx > 0) && (_idx < 9)) {
|
||||
if ((_idx == 1) || (_idx == 2)) {
|
||||
//object->unk_0C6 = 0x0150;
|
||||
//object->unk_01C[1] = 100.0f;
|
||||
} else if ((_idx == 3) || (_idx == 4)) {
|
||||
//object->unk_0C6 = 0x0100;
|
||||
//object->unk_01C[1] = 80.0f;
|
||||
} else if ((_idx == 5) || (_idx == 6)) {
|
||||
//object->unk_0C6 = 0xFF00;
|
||||
//object->unk_01C[1] = 80.0f;
|
||||
} else if ((_idx == 7) || (_idx == 8)) {
|
||||
//object->unk_0C6 = 0x0150;
|
||||
//object->unk_01C[1] = 80.0f;
|
||||
}
|
||||
//object->unk_0C4 = (_idx << 0xF) & 0xFFFF;
|
||||
//object->surfaceHeight = -80.0f;
|
||||
//object->sizeScaling = 0.08f;
|
||||
//object->unk_0DD = 2;
|
||||
//func_800722A4(objectIndex, 8);
|
||||
} else if ((_idx > 8) && (_idx < 15)) {
|
||||
switch (_idx) {
|
||||
case 9:
|
||||
if (gGamestate != CREDITS_SEQUENCE) {
|
||||
} else {
|
||||
//object->sizeScaling = 0.15f;
|
||||
}
|
||||
//object->unk_0C6 = 0x9000;
|
||||
if (gIsMirrorMode != 0) {
|
||||
//object->unk_0C6 -= 0x4000;
|
||||
}
|
||||
//object->unk_0DD = 3;
|
||||
break;
|
||||
case 10:
|
||||
//object->unk_0C6 = 0x5000;
|
||||
if (gIsMirrorMode != 0) {
|
||||
//object->unk_0C6 += 0x8000;
|
||||
}
|
||||
//object->unk_0DD = 4;
|
||||
break;
|
||||
case 11:
|
||||
//object->unk_0C6 = 0xC000;
|
||||
//object->unk_0DD = 6;
|
||||
if (gIsMirrorMode != 0) {
|
||||
//object->unk_0C6 += 0x8000;
|
||||
}
|
||||
break;
|
||||
case 12:
|
||||
//object->unk_0C6 = 0x4000;
|
||||
//object->unk_0DD = 6;
|
||||
if (gIsMirrorMode != 0) {
|
||||
//object->unk_0C6 += 0x8000;
|
||||
}
|
||||
break;
|
||||
case 13:
|
||||
// object->unk_0C6 = 0x8000;
|
||||
//object->unk_0DD = 6;
|
||||
if (gIsMirrorMode != 0) {
|
||||
//object->unk_0C6 -= 0x4000;
|
||||
}
|
||||
break;
|
||||
case 14:
|
||||
//object->unk_0C6 = 0x9000;
|
||||
//object->unk_0DD = 6;
|
||||
if (gIsMirrorMode != 0) {
|
||||
//object->unk_0C6 -= 0x4000;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//set_obj_direction_angle(objectIndex, 0U, object->unk_0C6 + 0x8000, 0U);
|
||||
//object->surfaceHeight = 5.0f;
|
||||
//object->sizeScaling = 0.04f;
|
||||
//func_800722A4(objectIndex, 0x00000014);
|
||||
}
|
||||
func_80086EF0(objectIndex);
|
||||
object->unk_034 = 0.0f;
|
||||
object->type = get_animation_length(d_course_sherbet_land_unk_data11, 0);
|
||||
object_next_state(objectIndex);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
#pragma once
|
||||
|
||||
#include <libultraship.h>
|
||||
#include <vector>
|
||||
|
||||
extern "C" {
|
||||
#include "macros.h"
|
||||
#include "main.h"
|
||||
#include "vehicles.h"
|
||||
#include "waypoints.h"
|
||||
#include "common_structs.h"
|
||||
#include "objects.h"
|
||||
#include "course_offsets.h"
|
||||
}
|
||||
|
||||
//! @todo Make shadow size bigger if thwomp is scaled up
|
||||
//! @todo make adjustable properties for squishSize and boundingBoxSize
|
||||
|
||||
/**
|
||||
* Thwomp GameObject
|
||||
*
|
||||
* The game automatically places the actor on the ground so you do not need to provide a Y coordinate value.
|
||||
*
|
||||
* @arg direction the rotational direction the thwomp is facing.
|
||||
* @arg behaviour the behaviour of the thwomp, uses values 1-6.
|
||||
* @arg primAlpha unknown
|
||||
* @arg boundingBoxSize optional. The size of the bounding box for the thwomp. Default value is 12
|
||||
*/
|
||||
class OPenguin {
|
||||
public:
|
||||
enum PenguinType : uint32_t {
|
||||
CHICK,
|
||||
ADULT,
|
||||
CREDITS,
|
||||
EMPEROR
|
||||
};
|
||||
|
||||
enum Behaviour : uint16_t {
|
||||
DISABLED,
|
||||
STRUT, // Emperor penguin
|
||||
CIRCLE, // Waddle in a circle
|
||||
SLIDE3,
|
||||
SLIDE4,
|
||||
UNK, // unused
|
||||
SLIDE6,
|
||||
};
|
||||
|
||||
public:
|
||||
f32 Diameter = 0.0f; // Waddle in a circle around the spawn point at this diameter.
|
||||
uint16_t MirrorModeAngleOffset;
|
||||
|
||||
explicit OPenguin(s32 i, Vec3f pos, u16 direction, PenguinType type, Behaviour behaviour);
|
||||
|
||||
void Tick();
|
||||
void Draw(s32 playerId);
|
||||
private:
|
||||
void Behaviours(s32 objectIndex, s32 arg1);
|
||||
void EmperorPenguin(s32 objectIndex);
|
||||
void InitEmperorPenguin(s32 objectIndex);
|
||||
void OtherPenguin(s32 objectIndex);
|
||||
void InitOtherPenguin(s32 objectIndex);
|
||||
|
||||
s32 _idx;
|
||||
PenguinType _type;
|
||||
Behaviour _bhv;
|
||||
|
||||
|
||||
};
|
||||
@@ -0,0 +1,669 @@
|
||||
#include <libultraship.h>
|
||||
#include <libultra/gbi.h>
|
||||
#include "OThwomp.h"
|
||||
#include <vector>
|
||||
|
||||
#include "port/Game.h"
|
||||
|
||||
extern "C" {
|
||||
#include "macros.h"
|
||||
#include "main.h"
|
||||
#include "actors.h"
|
||||
#include "math_util.h"
|
||||
#include "sounds.h"
|
||||
#include "update_objects.h"
|
||||
#include "render_player.h"
|
||||
#include "external.h"
|
||||
#include "bomb_kart.h"
|
||||
#include "collision.h"
|
||||
#include "code_80086E70.h"
|
||||
#include "render_objects.h"
|
||||
#include "code_80057C60.h"
|
||||
#include "defines.h"
|
||||
#include "code_80005FD0.h"
|
||||
#include "math_util_2.h"
|
||||
#include "collision.h"
|
||||
#include "assets/bowsers_castle_data.h"
|
||||
#include "ceremony_and_credits.h"
|
||||
#include "objects.h"
|
||||
#include "update_objects.h"
|
||||
#include "render_objects.h"
|
||||
extern s8 gPlayerCount;
|
||||
}
|
||||
|
||||
OThwomp::OThwomp(s32 i, s16 x, s16 z, s16 direction, f32 scale, s16 behaviour, s16 primAlpha, u16 boundingBoxSize) {
|
||||
if (i >= 32) {
|
||||
printf("MAX THWOMPS REACHED (32), skipping\n");
|
||||
return;
|
||||
}
|
||||
_idx = i;
|
||||
_faceDirection = direction;
|
||||
_boundingBoxSize = boundingBoxSize;
|
||||
State = (States)behaviour;
|
||||
s32 objectId = indexObjectList1[i];
|
||||
init_object(objectId, 0);
|
||||
gObjectList[objectId].origin_pos[0] = x * xOrientation;
|
||||
gObjectList[objectId].origin_pos[2] = z;
|
||||
gObjectList[objectId].unk_0D5 = behaviour;
|
||||
gObjectList[objectId].primAlpha = primAlpha;
|
||||
gObjectList[objectId].boundingBoxSize = boundingBoxSize + 5;
|
||||
|
||||
if (scale == 0.0f) {
|
||||
scale = 1.0f;
|
||||
}
|
||||
|
||||
gObjectList[objectId].sizeScaling = scale;
|
||||
}
|
||||
|
||||
void OThwomp::Tick() { // func_80081210
|
||||
Player* player;
|
||||
s32 objectIndex;
|
||||
s32 var_s2_3;
|
||||
s32 var_s4;
|
||||
|
||||
objectIndex = indexObjectList1[_idx];
|
||||
func_800722CC(objectIndex, 0x00000010);
|
||||
func_8008A4CC(objectIndex);
|
||||
|
||||
OThwomp::func_8007F8D8();
|
||||
|
||||
objectIndex = indexObjectList1[_idx];
|
||||
if (gObjectList[objectIndex].state != 0) {
|
||||
switch (State) {
|
||||
case STATIONARY:
|
||||
OThwomp::StationaryBehaviour(objectIndex);
|
||||
break;
|
||||
case MOVE_AND_ROTATE:
|
||||
OThwomp::MoveAndRotateBehaviour(objectIndex);
|
||||
break;
|
||||
case MOVE_FAR:
|
||||
OThwomp::MoveFarBehaviour(objectIndex);
|
||||
break;
|
||||
case STATIONARY_FAST:
|
||||
OThwomp::StationaryFastBehaviour(objectIndex);
|
||||
break;
|
||||
case JAILED:
|
||||
OThwomp::JailedBehaviour(objectIndex);
|
||||
break;
|
||||
case SLIDE:
|
||||
OThwomp::SlidingBehaviour(objectIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
player = gPlayerOne;
|
||||
for (var_s4 = 0; var_s4 < NUM_PLAYERS; var_s4++, player++) {
|
||||
player->tyres[FRONT_LEFT].unk_14 &= ~3;
|
||||
player->unk_046 &= ~0x0006;
|
||||
|
||||
objectIndex = indexObjectList1[_idx];
|
||||
if (!(player->effects & BOO_EFFECT)) {
|
||||
OThwomp::func_80080B28(objectIndex, var_s4);
|
||||
}
|
||||
if (is_obj_flag_status_active(objectIndex, 0x00020000) != 0) {
|
||||
func_80080A14(objectIndex, player);
|
||||
}
|
||||
if (is_obj_flag_status_active(objectIndex, 0x00010000) != 0) {
|
||||
func_80080A4C(objectIndex, var_s4);
|
||||
}
|
||||
|
||||
}
|
||||
func_8007542C(3);
|
||||
|
||||
objectIndex = indexObjectList1[_idx];
|
||||
if (func_80072320(objectIndex, 0x00000020) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
func_800722CC(objectIndex, 0x00000020);
|
||||
func_80080FEC(objectIndex);
|
||||
|
||||
for (var_s4 = 0; var_s4 < gObjectParticle2_SIZE; var_s4++) {
|
||||
objectIndex = gObjectParticle2[var_s4];
|
||||
if (objectIndex == DELETED_OBJECT_ID) {
|
||||
return;
|
||||
}
|
||||
if (gObjectList[objectIndex].state == 0) {
|
||||
return;
|
||||
}
|
||||
func_800810F4(objectIndex);
|
||||
if (gObjectList[objectIndex].state != 0) {
|
||||
return;
|
||||
}
|
||||
delete_object_wrapper(&gObjectParticle2[var_s4]);
|
||||
}
|
||||
}
|
||||
|
||||
void OThwomp::func_8007F8D8() {
|
||||
Player* player;
|
||||
s32 objectIndex;
|
||||
s32 var_s0;
|
||||
s32 someIndex;
|
||||
s32 var_s4;
|
||||
Object* object;
|
||||
|
||||
player = gPlayerOne;
|
||||
var_s4 = 1;
|
||||
|
||||
objectIndex = indexObjectList1[_idx];
|
||||
object = &gObjectList[objectIndex];
|
||||
if (object->unk_0D5 == 3) {
|
||||
var_s0 = 0;
|
||||
if ((object->state >= 2) && (func_80072354(objectIndex, 8) != 0)) {
|
||||
var_s0 = 1;
|
||||
}
|
||||
var_s4 *= var_s0;
|
||||
}
|
||||
|
||||
if (var_s4 != 0) {
|
||||
for (var_s0 = 0; var_s0 < 4; var_s0++, player++) {
|
||||
if ((player->type & PLAYER_EXISTS) && !(player->type & PLAYER_KART_AI)) {
|
||||
if (OThwomp::func_8007F75C(var_s0) != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s32 OThwomp::func_8007F75C(s32 playerId) {
|
||||
s32 someIndex;
|
||||
s32 objectIndex;
|
||||
s32 temp_s7;
|
||||
s32 var_s6;
|
||||
s32 waypoint;
|
||||
|
||||
waypoint = gNearestWaypointByPlayerId[playerId];
|
||||
var_s6 = 0;
|
||||
if ((waypoint >= 0xAA) && (waypoint < 0xB5)) {
|
||||
temp_s7 = random_int(0x0032U) + 0x32;
|
||||
objectIndex = indexObjectList1[_idx];
|
||||
if (gObjectList[objectIndex].unk_0D5 == 3) {
|
||||
var_s6 = 1;
|
||||
func_8007F660(objectIndex, playerId, temp_s7);
|
||||
}
|
||||
|
||||
} else if ((waypoint >= 0xD7) && (waypoint < 0xE2)) {
|
||||
objectIndex = indexObjectList1[_idx];
|
||||
if (gObjectList[objectIndex].unk_0D5 == 3) {
|
||||
var_s6 = 1;
|
||||
func_8007F6C4(objectIndex, playerId);
|
||||
}
|
||||
}
|
||||
return var_s6;
|
||||
}
|
||||
|
||||
void OThwomp::func_80080B28(s32 objectIndex, s32 playerId) {
|
||||
f32 temp_f0;
|
||||
Player* temp_s0;
|
||||
|
||||
temp_s0 = &gPlayerOne[playerId];
|
||||
if (is_obj_flag_status_active(objectIndex, 0x00000200) != 0) {
|
||||
if (!(temp_s0->soundEffects & 0x100)) {
|
||||
temp_f0 = func_80088F54(objectIndex, temp_s0);
|
||||
if ((temp_f0 <= 9.0) && !(temp_s0->effects & 0x04000000) &&
|
||||
(has_collided_horizontally_with_player(objectIndex, temp_s0) != 0)) {
|
||||
if ((temp_s0->type & 0x8000) && !(temp_s0->type & 0x100)) {
|
||||
if (!(temp_s0->effects & 0x200)) {
|
||||
func_80089474(objectIndex, playerId, 1.4f, 1.1f, SOUND_ARG_LOAD(0x19, 0x00, 0xA0, 0x4C));
|
||||
} else if (func_80072354(objectIndex, 0x00000040) != 0) {
|
||||
if (temp_s0->type & 0x1000) {
|
||||
func_800C98B8(temp_s0->pos, temp_s0->velocity, SOUND_ARG_LOAD(0x19, 0x01, 0xA2, 0x4A));
|
||||
} else {
|
||||
func_800C9060((u8) playerId, SOUND_ARG_LOAD(0x19, 0x01, 0xA2, 0x4A));
|
||||
}
|
||||
func_80080DE4(objectIndex);
|
||||
func_80075304(gObjectList[objectIndex].pos, 3, 3, D_8018D3C4);
|
||||
set_object_flag_status_false(objectIndex, 0x00000200);
|
||||
func_800722A4(objectIndex, 0x00000040);
|
||||
func_80086F60(objectIndex);
|
||||
func_800726CC(objectIndex, 0x000000C8);
|
||||
}
|
||||
}
|
||||
} else if ((temp_f0 <= 17.5) && (func_80072320(objectIndex, 1) != 0) &&
|
||||
(is_within_horizontal_distance_of_player(objectIndex, temp_s0, (temp_s0->unk_094 * 0.5) + _boundingBoxSize) !=
|
||||
0)) {
|
||||
if ((temp_s0->type & 0x8000) && !(temp_s0->type & 0x100)) {
|
||||
if (is_obj_flag_status_active(objectIndex, 0x04000000) != 0) {
|
||||
func_80072180();
|
||||
}
|
||||
func_800722A4(objectIndex, 2);
|
||||
temp_s0->unk_040 = (s16) objectIndex;
|
||||
temp_s0->unk_046 |= 2;
|
||||
temp_s0->soundEffects |= 0x100;
|
||||
func_80088FF0(temp_s0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
func_80088FF0(temp_s0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OThwomp::Draw(s32 cameraId) {
|
||||
s32 objectIndex = 0;
|
||||
s32 i;
|
||||
UNUSED s32 stackPadding0;
|
||||
s16 minusone, plusone;
|
||||
Camera* camera;
|
||||
Object* object;
|
||||
|
||||
camera = &camera1[cameraId];
|
||||
if (cameraId == PLAYER_ONE) {
|
||||
objectIndex = indexObjectList1[_idx];
|
||||
set_object_flag_status_false(objectIndex, 0x00070000);
|
||||
func_800722CC(objectIndex, 0x00000110);
|
||||
}
|
||||
|
||||
translate_thwomp_lights(objectIndex);
|
||||
|
||||
objectIndex = indexObjectList1[_idx];
|
||||
minusone = gObjectList[objectIndex].unk_0DF - 1;
|
||||
plusone = gObjectList[objectIndex].unk_0DF + 1;
|
||||
|
||||
if (gGamestate != CREDITS_SEQUENCE) {
|
||||
OThwomp::DrawModel(objectIndex);
|
||||
}
|
||||
|
||||
gSPDisplayList(gDisplayListHead++, (Gfx*)D_0D0079C8);
|
||||
gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIA, G_CC_MODULATEIA);
|
||||
gSPNumLights(gDisplayListHead++, 1);
|
||||
gSPLight(gDisplayListHead++, &D_800E4668.l[0], LIGHT_1);
|
||||
gSPLight(gDisplayListHead++, &D_800E4668.a, LIGHT_2);
|
||||
gSPClearGeometryMode(gDisplayListHead++, G_CULL_BOTH);
|
||||
gSPSetGeometryMode(gDisplayListHead++, G_SHADE | G_LIGHTING | G_SHADING_SMOOTH);
|
||||
load_texture_block_rgba16_mirror((u8*)d_course_bowsers_castle_thwomp_side, 0x00000020, 0x00000020);
|
||||
for (i = 0; i < gObjectParticle3_SIZE; i++) {
|
||||
objectIndex = gObjectParticle3[i];
|
||||
if (objectIndex != NULL_OBJECT_ID) {
|
||||
object = &gObjectList[objectIndex];
|
||||
if ((object->state > 0) && (State == MOVE_FAR) && (gMatrixHudCount <= MTX_HUD_POOL_SIZE_MAX)) {
|
||||
rsp_set_matrix_transformation(object->pos, object->orientation, object->sizeScaling);
|
||||
gSPVertex(gDisplayListHead++, (uintptr_t)D_0D005C00, 3, 0);
|
||||
gSPDisplayList(gDisplayListHead++, (Gfx*)D_0D006930);
|
||||
}
|
||||
}
|
||||
}
|
||||
gSPSetGeometryMode(gDisplayListHead++, G_CULL_BACK);
|
||||
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
|
||||
gSPTexture(gDisplayListHead++, 0x0001, 0x0001, 0, G_TX_RENDERTILE, G_OFF);
|
||||
gSPDisplayList(gDisplayListHead++, (Gfx*)D_0D007AE0);
|
||||
load_texture_block_ia8_nomirror(D_8018D490, 0x00000020, 0x00000020);
|
||||
func_8004B3C8(0);
|
||||
D_80183E80[0] = 0;
|
||||
D_80183E80[2] = 0x8000;
|
||||
for (i = 0; i < gObjectParticle2_SIZE; i++) {
|
||||
objectIndex = gObjectParticle2[i];
|
||||
if (objectIndex != NULL_OBJECT_ID) {
|
||||
object = &gObjectList[objectIndex];
|
||||
if ((object->state >= 2) && (State == MOVE_AND_ROTATE) && (gMatrixHudCount <= MTX_HUD_POOL_SIZE_MAX)) {
|
||||
func_8004B138(0x000000FF, 0x000000FF, 0x000000FF, (s32) object->primAlpha);
|
||||
D_80183E80[1] = func_800418AC(object->pos[0], object->pos[2], camera->pos);
|
||||
func_800431B0(object->pos, D_80183E80, object->sizeScaling, (Vtx*)D_0D005AE0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OThwomp::DrawModel(s32 objectIndex) {
|
||||
if ((gObjectList[objectIndex].state >= 2) && (func_80072354(objectIndex, 0x00000040) != 0)) {
|
||||
func_8004A7AC(objectIndex, 1.75f);
|
||||
rsp_set_matrix_transformation(gObjectList[objectIndex].pos, gObjectList[objectIndex].orientation,
|
||||
gObjectList[objectIndex].sizeScaling);
|
||||
thwomp_lights(objectIndex);
|
||||
gSPDisplayList(gDisplayListHead++, (Gfx*)D_0D007828);
|
||||
gDPSetTextureLUT(gDisplayListHead++, G_TT_RGBA16);
|
||||
gDPLoadTLUT_pal256(gDisplayListHead++, d_course_bowsers_castle_thwomp_tlut);
|
||||
rsp_load_texture_mask((u8*)gObjectList[objectIndex].activeTexture, 0x00000010, 0x00000040, 4);
|
||||
gSPDisplayList(gDisplayListHead++, gObjectList[objectIndex].model);
|
||||
}
|
||||
}
|
||||
|
||||
/** Behaviours **/
|
||||
|
||||
void OThwomp::StationaryBehaviour(s32 objectIndex) { // func_8007ED6C
|
||||
UNUSED s32 stackPadding[4];
|
||||
switch (gObjectList[objectIndex].state) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
OThwomp::func_8007EC30(objectIndex);
|
||||
break;
|
||||
case 2:
|
||||
set_and_run_timer_object(objectIndex, 0x0000003C);
|
||||
break;
|
||||
case 3:
|
||||
func_80072568(objectIndex, 0x00000032);
|
||||
break;
|
||||
case 4:
|
||||
if (func_8007E59C(objectIndex) != 0) {
|
||||
func_800725E8(objectIndex, 0x0000012C, 2);
|
||||
} else {
|
||||
func_800726CC(objectIndex, 2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
func_8007E63C(objectIndex);
|
||||
object_calculate_new_pos_offset(objectIndex);
|
||||
gObjectList[objectIndex].direction_angle[1] = gObjectList[objectIndex].orientation[1];
|
||||
func_80073514(objectIndex);
|
||||
}
|
||||
|
||||
// Stationary
|
||||
void OThwomp::func_8007EC30(s32 objectIndex) {
|
||||
Object* object;
|
||||
|
||||
object = &gObjectList[objectIndex];
|
||||
object->surfaceHeight = 0.0f;
|
||||
object->origin_pos[1] = 0.0f;
|
||||
set_obj_origin_offset(objectIndex, 0.0f, 0.0f, 0.0f);
|
||||
if (gIsMirrorMode != 0) {
|
||||
set_obj_direction_angle(objectIndex, 0U, -_faceDirection, 0U);
|
||||
set_obj_orientation(objectIndex, 0U, -_faceDirection, 0U);
|
||||
} else {
|
||||
set_obj_direction_angle(objectIndex, 0U, _faceDirection, 0U);
|
||||
set_obj_orientation(objectIndex, 0U, _faceDirection, 0U);
|
||||
}
|
||||
init_texture_object(objectIndex, (uint8_t*) d_course_bowsers_castle_thwomp_tlut, (const char**) d_course_bowsers_castle_thwomp_faces,
|
||||
0x10U, (u16) 0x00000040);
|
||||
object->model = (Gfx*)d_course_bowsers_castle_dl_thwomp;
|
||||
object->unk_01C[1] = 30.0f;
|
||||
set_object_flag_status_true(objectIndex, 0x05000220);
|
||||
object->type = 0;
|
||||
object->unk_0DF = 6;
|
||||
func_800724DC(objectIndex);
|
||||
object_next_state(objectIndex);
|
||||
}
|
||||
|
||||
void OThwomp::MoveAndRotateBehaviour(s32 objectIndex) { // func_8007F5A8
|
||||
|
||||
switch (gObjectList[objectIndex].state) { /* irregular */
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
OThwomp::func_8007EE5C(objectIndex);
|
||||
break;
|
||||
case 3:
|
||||
func_80072568(objectIndex, 0x00000032);
|
||||
break;
|
||||
case 4:
|
||||
func_80086FD4(objectIndex);
|
||||
object_next_state(objectIndex);
|
||||
break;
|
||||
}
|
||||
func_8007E63C(objectIndex);
|
||||
func_8007F544(objectIndex);
|
||||
object_calculate_new_pos_offset(objectIndex);
|
||||
func_80073514(objectIndex);
|
||||
}
|
||||
|
||||
// MoveAndRotateBehaviour
|
||||
void OThwomp::func_8007EE5C(s32 objectIndex) {
|
||||
Object* object;
|
||||
|
||||
init_texture_object(objectIndex, (u8*)d_course_bowsers_castle_thwomp_tlut, (const char**) d_course_bowsers_castle_thwomp_faces,
|
||||
0x10U, (u16) 0x00000040);
|
||||
object = &gObjectList[objectIndex];
|
||||
object->model = (Gfx*)d_course_bowsers_castle_dl_thwomp;
|
||||
set_object_flag_status_true(objectIndex, 0x04000220);
|
||||
object->type = 0;
|
||||
object->unk_0DF = 6;
|
||||
func_80086E70(objectIndex);
|
||||
object->surfaceHeight = 0.0f;
|
||||
object->origin_pos[1] = 0.0f;
|
||||
set_obj_origin_offset(objectIndex, 0.0f, 20.0f, 0.0f);
|
||||
object->unk_01C[1] = 20.0f;
|
||||
if (gIsMirrorMode != 0) {
|
||||
set_obj_direction_angle(objectIndex, 0U, -_faceDirection, 0U);
|
||||
set_obj_orientation(objectIndex, 0U, -_faceDirection, 0U);
|
||||
} else {
|
||||
set_obj_direction_angle(objectIndex, 0U, _faceDirection, 0U);
|
||||
set_obj_orientation(objectIndex, 0U, _faceDirection, 0U);
|
||||
}
|
||||
object->unk_0AE = 1;
|
||||
if (object->primAlpha == 0) {
|
||||
object->unk_0DD = 1;
|
||||
} else {
|
||||
object->unk_0DD = 2;
|
||||
}
|
||||
object_next_state(objectIndex);
|
||||
}
|
||||
|
||||
void OThwomp::MoveFarBehaviour(s32 objectIndex) { // func_8007FFC0
|
||||
switch (gObjectList[objectIndex].state) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
OThwomp::func_8007FA08(objectIndex);
|
||||
break;
|
||||
case 3:
|
||||
func_80072568(objectIndex, 0x00000032);
|
||||
break;
|
||||
case 4:
|
||||
object_next_state(objectIndex);
|
||||
func_80086FD4(objectIndex);
|
||||
break;
|
||||
}
|
||||
func_8007E63C(objectIndex);
|
||||
func_8007FF5C(objectIndex);
|
||||
object_calculate_new_pos_offset(objectIndex);
|
||||
func_80073514(objectIndex);
|
||||
}
|
||||
|
||||
// MoveFarBehaviour
|
||||
void OThwomp::func_8007FA08(s32 objectIndex) {
|
||||
Object* object;
|
||||
|
||||
init_texture_object(objectIndex, (u8*)d_course_bowsers_castle_thwomp_tlut, (const char**) d_course_bowsers_castle_thwomp_faces,
|
||||
0x10U, (u16) 0x00000040);
|
||||
object = &gObjectList[objectIndex];
|
||||
object->model = (Gfx*)d_course_bowsers_castle_dl_thwomp;
|
||||
set_object_flag_status_true(objectIndex, 0x04000220);
|
||||
object->type = 0;
|
||||
object->surfaceHeight = 0.0f;
|
||||
object->origin_pos[1] = 0.0f;
|
||||
set_obj_origin_offset(objectIndex, 0.0f, 0.0f, 0.0f);
|
||||
set_obj_direction_angle(objectIndex, 0U, 0U, 0U);
|
||||
if (gIsMirrorMode != 0) {
|
||||
set_obj_orientation(objectIndex, 0U, 0xC000U, 0U);
|
||||
} else {
|
||||
set_obj_orientation(objectIndex, 0U, 0x4000U, 0U);
|
||||
}
|
||||
object->velocity[0] = 0.0f;
|
||||
object->direction_angle[1] = object->orientation[1];
|
||||
object->unk_0DD = 1;
|
||||
object->unk_0DF = 8;
|
||||
object->offset[1] = 15.0f;
|
||||
object->unk_01C[1] = 15.0f;
|
||||
object_next_state(objectIndex);
|
||||
}
|
||||
|
||||
void OThwomp::StationaryFastBehaviour(s32 objectIndex) { // func_800801FC
|
||||
Object* object;
|
||||
|
||||
object = &gObjectList[objectIndex];
|
||||
switch (object->state) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
OThwomp::func_80080078(objectIndex);
|
||||
break;
|
||||
case 2:
|
||||
set_and_run_timer_object(objectIndex, object->timer);
|
||||
break;
|
||||
case 3:
|
||||
func_80072568(objectIndex, 0x00000032);
|
||||
break;
|
||||
case 4:
|
||||
object->timer = 0x0000003C;
|
||||
func_800726CC(objectIndex, 2);
|
||||
break;
|
||||
}
|
||||
func_8007E63C(objectIndex);
|
||||
object_calculate_new_pos_offset(objectIndex);
|
||||
func_80073514(objectIndex);
|
||||
}
|
||||
|
||||
// StationaryFastBehaviour
|
||||
void OThwomp::func_80080078(s32 objectIndex) { // func_80080078
|
||||
Object* object;
|
||||
|
||||
init_texture_object(objectIndex, (u8*)d_course_bowsers_castle_thwomp_tlut, (const char**) d_course_bowsers_castle_thwomp_faces,
|
||||
0x10U, (u16) 0x00000040);
|
||||
object = &gObjectList[objectIndex];
|
||||
object->model = (Gfx*)d_course_bowsers_castle_dl_thwomp;
|
||||
set_object_flag_status_true(objectIndex, 0x04000220);
|
||||
object->type = 2;
|
||||
object->unk_0DF = 8;
|
||||
set_obj_direction_angle(objectIndex, 0U, 0U, 0U);
|
||||
object->surfaceHeight = 0.0f;
|
||||
object->origin_pos[1] = 0.0f;
|
||||
set_obj_origin_offset(objectIndex, 0.0f, 0.0f, 0.0f);
|
||||
object->unk_01C[1] = 30.0f;
|
||||
if (gIsMirrorMode != 0) {
|
||||
set_obj_orientation(objectIndex, 0U, -_faceDirection, 0U);
|
||||
} else {
|
||||
set_obj_orientation(objectIndex, 0U, _faceDirection, 0U);
|
||||
}
|
||||
switch (object->primAlpha) { /* irregular */
|
||||
case 0:
|
||||
object->timer = 2;
|
||||
break;
|
||||
case 1:
|
||||
object->timer = 0x0000003C;
|
||||
break;
|
||||
case 2:
|
||||
object->timer = 0x00000078;
|
||||
break;
|
||||
case 3:
|
||||
object->timer = 0x000000B4;
|
||||
break;
|
||||
}
|
||||
func_800724DC(objectIndex);
|
||||
object_next_state(objectIndex);
|
||||
}
|
||||
|
||||
void OThwomp::JailedBehaviour(s32 objectIndex) { // func_80080408
|
||||
switch (gObjectList[objectIndex].state) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
OThwomp::func_800802C0(objectIndex);
|
||||
break;
|
||||
case 2:
|
||||
func_8008A6DC(objectIndex, 100.0f);
|
||||
if (is_obj_flag_status_active(objectIndex, VISIBLE) != 0) {
|
||||
func_800C98B8(gObjectList[objectIndex].pos, gObjectList[objectIndex].velocity,
|
||||
SOUND_ARG_LOAD(0x19, 0x01, 0x80, 0x45));
|
||||
object_next_state(objectIndex);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (func_800730BC(objectIndex, 3, 5, 1, 6, 6) != 0) {
|
||||
gObjectList[objectIndex].textureListIndex = 0;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (set_and_run_timer_object(objectIndex, 0x0000012C) != 0) {
|
||||
func_800726CC(objectIndex, 2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
object_calculate_new_pos_offset(objectIndex);
|
||||
func_80073514(objectIndex);
|
||||
}
|
||||
|
||||
// JailedBehaviour
|
||||
void OThwomp::func_800802C0(s32 objectIndex) {
|
||||
Object* object;
|
||||
|
||||
object = &gObjectList[objectIndex];
|
||||
object->unk_0D8 = 0;
|
||||
init_texture_object(objectIndex, (u8*)d_course_bowsers_castle_thwomp_tlut, (const char**) d_course_bowsers_castle_thwomp_faces,
|
||||
0x10U, (u16) 0x00000040);
|
||||
object->model = (Gfx*)d_course_bowsers_castle_dl_thwomp;
|
||||
object->textureListIndex = 0;
|
||||
//object->sizeScaling = 1.5f;
|
||||
set_object_flag_status_true(objectIndex, 0x05000220);
|
||||
object->type = 1;
|
||||
object->unk_0DF = 6;
|
||||
set_obj_origin_offset(objectIndex, 0.0f, 0.0f, 0.0f);
|
||||
set_obj_direction_angle(objectIndex, 0U, 0U, 0U);
|
||||
object->surfaceHeight = 0.0f;
|
||||
object->origin_pos[1] = 0.0f;
|
||||
object->offset[1] = 10.0f;
|
||||
object->unk_01C[1] = 10.0f;
|
||||
if (gIsMirrorMode != 0) {
|
||||
set_obj_orientation(objectIndex, 0U, 0x4000U, 0U);
|
||||
} else {
|
||||
set_obj_orientation(objectIndex, 0U, 0xC000U, 0U);
|
||||
}
|
||||
object->offset[0] = 0.0f;
|
||||
object->offset[2] = 0.0f;
|
||||
func_800724DC(objectIndex);
|
||||
object_next_state(objectIndex);
|
||||
}
|
||||
|
||||
void OThwomp::SlidingBehaviour(s32 objectIndex) { // func_800808CC
|
||||
switch (gObjectList[objectIndex].state) { /* irregular */
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
OThwomp::func_80080524(objectIndex);
|
||||
break;
|
||||
case 2:
|
||||
func_800730BC(objectIndex, 3, 5, 1, 6, -1);
|
||||
break;
|
||||
}
|
||||
if (gObjectList[objectIndex].state >= 2) {
|
||||
func_8007E63C(objectIndex);
|
||||
func_8008085C(objectIndex);
|
||||
func_80073514(objectIndex);
|
||||
if (gGamestate != 9) {
|
||||
if ((D_8018D40C == 0) && (gObjectList[objectIndex].state == 2)) {
|
||||
func_800C98B8(gObjectList[objectIndex].pos, gObjectList[objectIndex].velocity,
|
||||
SOUND_ARG_LOAD(0x19, 0x03, 0x60, 0x45));
|
||||
}
|
||||
} else if ((gCutsceneShotTimer < 0xBF) && (((s16) gCutsceneShotTimer % 88) == 0x0000001E)) {
|
||||
func_800C98B8(gObjectList[objectIndex].pos, gObjectList[objectIndex].velocity,
|
||||
SOUND_ARG_LOAD(0x19, 0x03, 0x60, 0x45));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SlidingBehaviour
|
||||
void OThwomp::func_80080524(s32 objectIndex) {
|
||||
Object* object;
|
||||
|
||||
init_texture_object(objectIndex, (u8*)d_course_bowsers_castle_thwomp_tlut, (const char**) d_course_bowsers_castle_thwomp_faces,
|
||||
0x10U, (u16) 0x00000040);
|
||||
object = &gObjectList[objectIndex];
|
||||
object->model = (Gfx*)d_course_bowsers_castle_dl_thwomp;
|
||||
object->textureListIndex = 0;
|
||||
set_object_flag_status_true(objectIndex, 0x04000220);
|
||||
object->type = 0;
|
||||
object->unk_0DF = 0x0A;
|
||||
func_80086E70(objectIndex);
|
||||
set_obj_origin_offset(objectIndex, 0.0f, 0.0f, 0.0f);
|
||||
object->surfaceHeight = 70.0f;
|
||||
object->origin_pos[1] = 70.0f;
|
||||
object->unk_01C[1] = 0.0f;
|
||||
set_obj_direction_angle(objectIndex, 0U, 0U, 0U);
|
||||
if ((gIsMirrorMode != 0) || (gGamestate == CREDITS_SEQUENCE)) {
|
||||
set_obj_orientation(objectIndex, 0U, -_faceDirection, 0U);
|
||||
} else {
|
||||
set_obj_orientation(objectIndex, 0U, _faceDirection, 0U);
|
||||
}
|
||||
switch (object->primAlpha) { /* irregular */
|
||||
case 0:
|
||||
object->unk_0DD = 2;
|
||||
object->velocity[2] = -1.0f;
|
||||
break;
|
||||
case 1:
|
||||
object->unk_0DD = 2;
|
||||
object->velocity[2] = -1.5f;
|
||||
break;
|
||||
}
|
||||
func_800722A4(objectIndex, 0x00000080);
|
||||
object_next_state(objectIndex);
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
|
||||
#include <libultraship.h>
|
||||
#include <vector>
|
||||
|
||||
extern "C" {
|
||||
#include "macros.h"
|
||||
#include "main.h"
|
||||
#include "vehicles.h"
|
||||
#include "waypoints.h"
|
||||
#include "common_structs.h"
|
||||
#include "objects.h"
|
||||
}
|
||||
|
||||
//! @todo Make shadow size bigger if thwomp is scaled up
|
||||
//! @todo make adjustable properties for squishSize and boundingBoxSize
|
||||
|
||||
/**
|
||||
* Thwomp GameObject
|
||||
*
|
||||
* The game automatically places the actor on the ground so you do not need to provide a Y coordinate value.
|
||||
*
|
||||
* @arg direction the rotational direction the thwomp is facing.
|
||||
* @arg behaviour the behaviour of the thwomp, uses values 1-6.
|
||||
* @arg primAlpha unknown
|
||||
* @arg boundingBoxSize optional. The size of the bounding box for the thwomp. Default value is 12
|
||||
*/
|
||||
class OThwomp {
|
||||
private:
|
||||
enum States : uint16_t {
|
||||
DISABLED,
|
||||
STATIONARY,
|
||||
MOVE_AND_ROTATE,
|
||||
MOVE_FAR, // Requires enough space to work
|
||||
STATIONARY_FAST,
|
||||
SLIDE, // Moves sideways left / right
|
||||
JAILED // Has no collision
|
||||
};
|
||||
|
||||
public:
|
||||
States State = States::DISABLED;
|
||||
|
||||
explicit OThwomp(s32 i, s16 x, s16 z, s16 direction, f32 scale, s16 behaviour, s16 primAlpha, u16 boundingBoxSize);
|
||||
|
||||
void Tick();
|
||||
void func_80080B28(s32 objectIndex, s32 playerId);
|
||||
void Draw(s32 playerId);
|
||||
void DrawModel(s32);
|
||||
s32 func_8007F75C(s32 playerId);
|
||||
void func_8007F8D8();
|
||||
|
||||
void StationaryBehaviour(s32 objectIndex);
|
||||
void func_8007EC30(s32 objectIndex);
|
||||
|
||||
void MoveAndRotateBehaviour(s32 objectIndex);
|
||||
void func_8007EE5C(s32 objectIndex);
|
||||
|
||||
void MoveFarBehaviour(s32 objectIndex);
|
||||
void func_8007FA08(s32 objectIndex);
|
||||
|
||||
void StationaryFastBehaviour(s32 objectIndex);
|
||||
void func_80080078(s32 objectIndex);
|
||||
|
||||
void JailedBehaviour(s32 objectIndex);
|
||||
void func_800802C0(s32 objectIndex);
|
||||
|
||||
void SlidingBehaviour(s32 objectIndex);
|
||||
void func_80080524(s32 objectIndex);
|
||||
private:
|
||||
s32 _idx;
|
||||
s16 _faceDirection;
|
||||
//! @todo Write this better. This effects the squish size and the bounding box size.
|
||||
// We should probably return to the programmer the pointer to the actor so they can do thwomp->squishSize = value.
|
||||
u16 _boundingBoxSize;
|
||||
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user