Implement Thwomps

This commit is contained in:
MegaMech
2024-11-23 22:18:17 -07:00
parent fc92794854
commit fd59569ef5
10 changed files with 795 additions and 32 deletions
+5 -3
View File
@@ -702,6 +702,7 @@ void render_object_for_player(s32 cameraId) {
CourseManager_RenderCourseObjects(cameraId);
CourseManager_TrainSmokeDraw(cameraId);
CourseManager_DrawThwomps(cameraId);
// switch (gCurrentCourseId) {
// case COURSE_MARIO_RACEWAY:
@@ -1289,7 +1290,8 @@ void func_80059AC8(void) {
func_80059A88(PLAYER_FOUR);
break;
}
func_8005A71C();
CourseManager_TickThwomps(); // func_8005A71C();
}
}
@@ -1569,9 +1571,9 @@ void func_8005A3C0(void) {
}
void func_8005A71C(void) {
if (GetCourse() == GetBowsersCastle()) {
//if (GetCourse() == GetBowsersCastle()) {
func_80081210();
}
//}
}
void update_object(void) {
+7 -1
View File
@@ -46,6 +46,7 @@ static size_t busses;
static size_t tankerTrucks;
static size_t cars;
static size_t boats;
static size_t thwomps;
/**
* Note that you can only remove the tender if there are no carriages
@@ -82,7 +83,7 @@ void World::AddCar(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoin
}
void World::ClearVehicles(void) {
trains = trucks = busses = tankerTrucks = cars = boats = 0;
trains = trucks = busses = tankerTrucks = cars = boats = thwomps = 0;
Vehicles.clear();
}
@@ -96,6 +97,11 @@ void World::AddBombKart(Vec3f pos, TrackWaypoint* waypoint, uint16_t waypointInd
BombKarts.push_back(std::make_unique<OBombKart>(pos, waypoint, waypointIndex, state, unk_3C));
}
void World::AddThwomp(f32 x, f32 z, s16 direction, f32 scale, s16 behaviour, s16 primAlpha) {
Thwomps.push_back(std::make_unique<OThwomp>(thwomps, x, z, direction, scale, behaviour, primAlpha));
thwomps++;
}
u32 World::GetCupIndex() {
return this->CupIndex;
}
+7 -2
View File
@@ -9,6 +9,7 @@
#include "vehicles/OBombKart.h"
#include "vehicles/Train.h"
#include "TrainCrossing.h"
#include "vehicles/OThwomp.h"
#include <memory>
#include "Actor.h"
@@ -24,6 +25,7 @@ class AVehicle;
class ATrain;
class ACar;
class TrainCrossing;
class OThwomp;
class World {
@@ -123,8 +125,8 @@ public:
std::vector<Cup*> Cups;
size_t CupIndex = 1;
std::vector<std::unique_ptr<GameObject>> GameObjects;
std::vector<AActor*> Actors;
std::vector<std::unique_ptr<GameObject>> GameObjects;
/** Actors */
void AddBoat(f32 speed, uint32_t waypoint);
@@ -137,8 +139,11 @@ public:
void ClearVehicles(void);
/** Objects **/
void AddBombKart(Vec3f pos, TrackWaypoint* waypoint, uint16_t waypointIndex, uint16_t state, f32 unk_3C);
std::vector<std::unique_ptr<OBombKart>> BombKarts;
void AddBombKart(Vec3f pos, TrackWaypoint* waypoint, uint16_t waypointIndex, uint16_t state, f32 unk_3C);
std::vector<std::unique_ptr<OThwomp>> Thwomps;
void AddThwomp(f32 x, f32 z, s16 direction, f32 scale, s16 behaviour, s16 primAlpha);
TrainCrossing* AddCrossing(Vec3f position, u32 waypointMin, u32 waypointMax, f32 approachRadius, f32 exitRadius);
std::vector<std::shared_ptr<TrainCrossing>> Crossings;
+38 -20
View File
@@ -149,29 +149,47 @@ void BowsersCastle::InitCourseObjects() {
size_t objectId;
size_t i;
gNumActiveThwomps = NUM_THWOMPS_100CC_EXTRA;
gThowmpSpawnList = gThwompSpawns100CCExtra;
switch (gCCSelection) { /* switch 1; irregular */
case CC_100: /* switch 1 */
case CC_EXTRA: /* switch 1 */
switch (gCCSelection) {
case CC_100:
case CC_EXTRA:
gWorldInstance.AddThwomp(0x0320, 0xf92a, 0x8000, 1.0f, 1, 0);
gWorldInstance.AddThwomp(0x044c, 0xf92a, 0x8000, 1.0f, 1, 1);
gWorldInstance.AddThwomp(0x02bc, 0xf95c, 0x8000, 1.0f, 2, 0);
gWorldInstance.AddThwomp(0x04b0, 0xf8f8, 0x8000, 1.0f, 2, 1);
gWorldInstance.AddThwomp(0x04b0, 0xf5ba, 0x8000, 1.0f, 3, 0);
gWorldInstance.AddThwomp(0x04b0, 0xf592, 0x8000, 1.0f, 3, 1);
gWorldInstance.AddThwomp(0x091a, 0xf5bf, 0x8000, 1.0f, 4, 0);
gWorldInstance.AddThwomp(0x091a, 0xf597, 0x8000, 1.0f, 4, 1);
gWorldInstance.AddThwomp(0x0596, 0xf92f, 0x8000, 1.5f, 6, 0);
gWorldInstance.AddThwomp(0x082a, 0xf9f2, 0x8000, 1.0f, 5, 0);
gWorldInstance.AddThwomp(0x073a, 0xf9f2, 0x8000, 1.0f, 5, 1);
break;
case CC_50: /* switch 1 */
gNumActiveThwomps = NUM_THWOMPS_50CC;
gThowmpSpawnList = gThomwpSpawns50CC;
case CC_50:
gWorldInstance.AddThwomp(0x3B6, 0xF92A, 0x8000, 1.0f, 1, 0);
gWorldInstance.AddThwomp(0x0352, 0xf95c, 0x8000, 1.0f, 2, 0);
gWorldInstance.AddThwomp(0x04b0, 0xf5ba, 0x8000, 1.0f, 3, 0);
gWorldInstance.AddThwomp(0x04b0, 0xf592, 0x8000, 1.0f, 3, 1);
gWorldInstance.AddThwomp(0x091a, 0xf5b0, 0x8000, 1.0f, 4, 0);
gWorldInstance.AddThwomp(0x0596, 0xf92f, 0x8000, 1.5f, 6, 0);
gWorldInstance.AddThwomp(0x082a, 0xf9f2, 0x8000, 1.0f, 5, 0);
gWorldInstance.AddThwomp(0x073a, 0xf9f2, 0x8000, 1.0f, 5, 1);
break;
case CC_150: /* switch 1 */
gNumActiveThwomps = NUM_THWOMPS_150CC;
gThowmpSpawnList = gThomwpSpawns150CC;
case CC_150:
gWorldInstance.AddThwomp(0x0320, 0xf92a, 0x8000, 1.0f, 1, 0);
gWorldInstance.AddThwomp(0x044c, 0xf92a, 0x8000, 1.0f, 1, 1);
gWorldInstance.AddThwomp(0x02bc, 0xf95c, 0x8000, 1.0f, 2, 0);
gWorldInstance.AddThwomp(0x04b0, 0xf8f8, 0x8000, 1.0f, 2, 1);
gWorldInstance.AddThwomp(0x04b0, 0xf5ba, 0x8000, 1.0f, 3, 0);
gWorldInstance.AddThwomp(0x04b0, 0xf592, 0x8000, 1.0f, 3, 1);
gWorldInstance.AddThwomp(0x091a, 0xf5c9, 0x8000, 1.0f, 4, 0);
gWorldInstance.AddThwomp(0x091a, 0xf5ab, 0x8000, 1.0f, 4, 1);
gWorldInstance.AddThwomp(0x091a, 0xf58d, 0x8000, 1.0f, 4, 2);
gWorldInstance.AddThwomp(0x0596, 0xf92f, 0x8000, 1.5f, 6, 0);
gWorldInstance.AddThwomp(0x082a, 0xf9f2, 0x8000, 1.0f, 5, 0);
gWorldInstance.AddThwomp(0x073a, 0xf9f2, 0x8000, 1.0f, 5, 1);
break;
}
for (i = 0; i < gNumActiveThwomps; i++) {
objectId = indexObjectList1[i];
init_object(objectId, 0);
gObjectList[objectId].origin_pos[0] = gThowmpSpawnList[i].startX * xOrientation;
gObjectList[objectId].origin_pos[2] = gThowmpSpawnList[i].startZ;
gObjectList[objectId].unk_0D5 = gThowmpSpawnList[i].unk_4;
gObjectList[objectId].primAlpha = gThowmpSpawnList[i].unk_6;
}
// Handle the big statue's fire breath
objectId = indexObjectList2[0];
init_object(objectId, 0);
@@ -201,7 +219,7 @@ void BowsersCastle::UpdateCourseObjects() {
}
void BowsersCastle::RenderCourseObjects(s32 cameraId) {
render_object_thwomps(cameraId);
//render_object_thwomps(cameraId);
render_object_bowser_flame(cameraId);
}
+639
View File
@@ -0,0 +1,639 @@
#include <libultraship.h>
#include <libultra/gbi.h>
#include "engine/vehicles/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, f32 x, f32 z, s16 direction, f32 scale, s16 behaviour, s16 primAlpha) {
if (i >= 32) {
printf("MAX THWOMPS REACHED (32), skipping\n");
return;
}
_idx = i;
_faceDirection = direction;
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;
if (scale == 0) {
scale = 1;
}
gObjectList[objectId].sizeScaling = scale;
}
void OThwomp::Tick() { // func_80081210
Player* player;
s32 objectIndex;
s32 var_s2_3;
s32 var_s4;
D_80165834[0] += 0x100;
D_80165834[1] += 0x200;
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)) {
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;
}
Lights1 thwompLight = gdSPDefLights1(85, 85, 85, 255, 255, 255, -66, 82, -55);
void OThwomp::Draw(s32 cameraId) {
s32 objectIndex = 0;
s32 i;
UNUSED s32 stackPadding0;
s16 minusone, plusone;
Camera* camera;
Object* object;
// Lights1 *thwompLightl = (Lights1 *) LOAD_ASSET(thwompLight);
camera = &camera1[cameraId];
if (cameraId == PLAYER_ONE) {
objectIndex = indexObjectList1[_idx];
set_object_flag_status_false(objectIndex, 0x00070000);
func_800722CC(objectIndex, 0x00000110);
}
func_800534A4(objectIndex);
objectIndex = indexObjectList1[_idx];
minusone = gObjectList[objectIndex].unk_0DF - 1;
plusone = gObjectList[objectIndex].unk_0DF + 1;
//! @todo Fix this quick hack fix to allow thwomps to render in custom courses
OThwomp::DrawModel(objectIndex);
if (GetCourse() != GetBowsersCastle()) {
} else {
if (gGamestate != CREDITS_SEQUENCE) {
if ((D_8018CF68[cameraId] >= minusone) && (plusone >= D_8018CF68[cameraId]) &&
(is_object_visible_on_camera(objectIndex, camera, 0x8000) != 0)) {
OThwomp::DrawModel(objectIndex);
}
} else { // CREDITS_SEQUENCE
OThwomp::DrawModel(objectIndex);
}
}
gSPDisplayList(gDisplayListHead++, (Gfx*)D_0D0079C8);
gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIA, G_CC_MODULATEIA);
gSPNumLights(gDisplayListHead++, 1);
gSPLight(gDisplayListHead++, &thwompLight.l[0], LIGHT_1);
gSPLight(gDisplayListHead++, &thwompLight.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);
func_800534E8(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);
}
}
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->boundingBoxSize = 0x000C;
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;
object->boundingBoxSize = 0x000C;
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;
object->boundingBoxSize = 0x000C;
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;
object->boundingBoxSize = 0x000C;
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->boundingBoxSize = 0x000C;
//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->boundingBoxSize = 0x000C;
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);
}
+66
View File
@@ -0,0 +1,66 @@
#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"
}
/**
* 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 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, f32 x, f32 z, s16 direction, f32 scale, s16 behaviour, s16 primAlpha);
void Tick();
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;
};
+23
View File
@@ -26,11 +26,13 @@
#include "engine/courses/DoubleDeck.h"
#include "engine/courses/DKJungle.h"
#include "engine/courses/BigDonut.h"
#include "engine/courses/Prison.h"
#include "engine/courses/TestCourse.h"
#include "engine/courses/PodiumCeremony.h"
#include "engine/TrainCrossing.h"
#include "engine/vehicles/OBombKart.h"
#include "Smoke.h"
@@ -72,6 +74,7 @@ DoubleDeck* gDoubleDeck;
DKJungle* gDkJungle;
BigDonut* gBigDonut;
PodiumCeremony* gPodiumCeremony;
PrisonCourse* gPrisonCourse;
TestCourse* gTestCourse;
Cup* gMushroomCup;
@@ -103,6 +106,7 @@ void CustomEngineInit() {
gDkJungle = new DKJungle();
gBigDonut = new BigDonut();
gPodiumCeremony = new PodiumCeremony();
gPrisonCourse = new PrisonCourse();
gTestCourse = new TestCourse();
/* Add all courses to the global course list */
@@ -126,6 +130,7 @@ void CustomEngineInit() {
gWorldInstance.AddCourse(gDoubleDeck);
gWorldInstance.AddCourse(gDkJungle);
gWorldInstance.AddCourse(gBigDonut);
gWorldInstance.AddCourse(gPrisonCourse);
gWorldInstance.AddCourse(gTestCourse);
gMushroomCup = new Cup("mk:mushroom_cup", "mushroom cup", std::vector<Course*>{ gLuigiRaceway, gMooMooFarm, gKoopaTroopaBeach, gKalimariDesert });
@@ -293,6 +298,8 @@ extern "C" {
void CourseManager_ClearVehicles(void) {
gWorldInstance.ClearVehicles();
gWorldInstance.BombKarts.clear();
gWorldInstance.Thwomps.clear();
}
void CourseManager_CrossingTrigger() {
@@ -466,6 +473,22 @@ extern "C" {
}
}
void CourseManager_TickThwomps() {
for (auto& thwomp : gWorldInstance.Thwomps) {
if (thwomp) {
thwomp->Tick();
}
}
}
void CourseManager_DrawThwomps(s32 cameraId) {
for (auto& thwomp : gWorldInstance.Thwomps) {
if (thwomp) {
thwomp->Draw(cameraId);
}
}
}
size_t GetCupCursorPosition() {
return gWorldInstance.CurrentCup->CursorPosition;
}
+4
View File
@@ -94,6 +94,10 @@ void CourseManager_ClearVehicles(void);
void CourseManager_DrawVehicles(s32 playerId);
void CourseManager_DrawThwomps(s32 cameraId);
void CourseManager_TickThwomps();
void CourseManager_CrossingTrigger();
void CourseManager_VehiclesCollision(s32 playerId, Player* player);
+4 -4
View File
@@ -2175,7 +2175,7 @@ void update_flame_particle(void) {
}
}
void init_object_smoke_paticle(s32 objectIndex, Vec3f arg1, s16 arg2) {
void init_object_smoke_particle(s32 objectIndex, Vec3f arg1, s16 arg2) {
Object* object;
init_object(objectIndex, (s32) arg2);
@@ -2196,7 +2196,7 @@ void init_smoke_particle(Vec3f arg0, UNUSED f32 arg1, s16 arg2) {
objectIndex = add_unused_obj_index(gObjectParticle4, &gNextFreeObjectParticle4, gObjectParticle4_SIZE);
if (objectIndex != NULL_OBJECT_ID) {
init_object_smoke_paticle(objectIndex, arg0, arg2);
init_object_smoke_particle(objectIndex, arg0, arg2);
}
}
@@ -2255,7 +2255,7 @@ void func_80076F2C(void) {
}
}
void init_object_smoke_particle(s32 objectIndex, s32 flameIndex) {
void init_object_smoke_particle2(s32 objectIndex, s32 flameIndex) {
init_object(objectIndex, 3);
gObjectList[objectIndex].unk_0D5 = 0xB;
@@ -2279,7 +2279,7 @@ void init_smoke_particles(s32 arg0) {
objectIndex = add_unused_obj_index(gObjectParticle4, &gNextFreeObjectParticle4, gObjectParticle4_SIZE);
if (objectIndex != NULL_OBJECT_ID) {
init_object_smoke_particle(objectIndex, arg0);
init_object_smoke_particle2(objectIndex, arg0);
}
}
+2 -2
View File
@@ -152,13 +152,13 @@ void func_800769D8(s32);
void func_80076AEC(s32);
void func_80076B7C(void);
void update_flame_particle(void);
void init_object_smoke_paticle(s32, Vec3f, s16);
void init_object_smoke_particle(s32, Vec3f, s16);
void init_smoke_particle(Vec3f, f32, s16);
void func_80076DC4(s32);
void func_80076E14(s32);
void func_80076ED8(s32);
void func_80076F2C(void);
void init_object_smoke_particle(s32, s32);
void init_object_smoke_particle2(s32, s32);
void init_smoke_particles(s32);
void func_800773D8(f32*, s32);
void func_80077428(s32);