Impl new intro (#193)

* Update menus

* Update CMakeLists.txt

* Add Ship

* Impl hm ship actors

* Update HM course

* Impl new intro

* Finish intro scene

* Rename

* Start Editor Work

* raycast works

* Fix ScreenRayTrace in widescreen

* Basic Actor Picking

* wip

* Editor use vtx collision

* gizmo work

* otr works for object picking

* Impl objects for editor

* actor init

* Update

* Add all axis move (freemove)

* Docking Windows works here

* Setup imgui layout for editor

* Editor Snap to Ground works

* Basic Scene Explorer Works

* Editor get actor names

* Impl editor object names

* impl Editor Play and Pause buttons

* Editor translate works while paused

* Fix freecam lighting

* Added adjustable track properties to editor

* Editor matrix, icons, rotation, impl light

* Setup Track Properties 1

* Editor tooling wip

* Load modded o2rs

* Don't enable hud if editor is enabled

* Updates

* SceneManager nearly working

* Fix mario kart 64 intro logo sizing

* Fix Rotator

* Finish new matrix translation code

* Cleanup headers

* Cleanup

* Cleanup 2

* Cleanup 3

* Prevent divize by zero crash

* Add visible circle for translate in all axis

* Editor scaling/rot works properly now

* Scale All_Axis evenly

* Fixes to includes to work on Linux.

* Removed overfilled arguments in gfx_create_framebuffer()

* Added missing function definitions to Game.h

* Editor sun face the camera

* Add rotation model to gizmo

* Add new handles

* Failed attempt at transforming collision

* Impl water volume

* Import fast64 paths

* water surface

* Scene Setup 1

* Custom Track O2R almost working needs testing

* Custom Track Load path O2r

* Render custom track. Wip collision

* Add missing function

* Debug Spawning Custom O2R Track

* Import courses working now

* Fix memory leak

* Remove New Track Button

* Engine.cpp more consistent with sf64

* Fix Editor Enable Button

* Editor Accurate mouse click drag objects

* Editor selects closest object and cleanup

* Gizmo rot and scale collision working

* Remove constexpr from IRotator

* Impl properties for location/rot/scale

* Better Properties display, swap rot handles

* Fix content browser dock and editor now disabled by default

* Remove GameInfoWindow, Multiplayer Button, and FPS Slider

* Disable Editor when its disabled

* Add new logo to hm intro

* Fix pause menu item box cursor

* Remove minimap from Course::from_json and to_json

* Impl Import Minimap

* Fix custom minimap rendering

* minimap uses extension .png

* Refactor minimap

* Freecam only for player 1

* GrandPrix Balloons work in custom track

* Track Id is now std::string and outside of Props

* Moved editor assets to be included in ship.o2r

* Fixed GenerateO2R to package the correct folder and save to the correct filename

* Linux specific changes.

* Added "#include <stdio.h>" that required them
* Changed how the "ship.o2r" file is loaded to allow it to load the file from within appimages.
* Changed the Linuxdeploy version to avoid errors later when the Github Actions creates appimages(same fix applied to other ports.)

* Revert "Moved editor assets to be included in ship.o2r"

This reverts commit 05704c01f7.

* Added back files(this time without LUS changes)

* Changed workflow file to use correct filename for assets file.

* Missed a few spots in the workflow file.

* Added .desktop file and made corrections to the main workflow.

* Added the rest of upstream CMakeLists.txt

* disabled USE_NETWORKING

* New InverseMatrix

* Renamed both .o2r files to be more accurate to its contents.

* Reverted CmakeList.txt

---------

Co-authored-by: MegaMech <7255464+MegaMech@users.noreply.github.com>
Co-authored-by: sitton76 <58642183+sitton76@users.noreply.github.com>
This commit is contained in:
MegaMech
2025-05-14 18:30:32 -06:00
committed by GitHub
parent 70f049cb6c
commit 32632cacdb
374 changed files with 43640 additions and 11666 deletions
+27 -2
View File
@@ -1,16 +1,41 @@
#include <libultraship.h>
#include "Matrix.h"
#include "Actor.h"
extern "C" {
#include "math_util.h"
}
AActor::AActor() {}
// Virtual functions to be overridden by derived classes
void AActor::Tick() { }
void AActor::Draw(Camera *camera) { }
void AActor::Draw(Camera *camera) {
if (Model) {
Mat4 mtx;
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
ApplyMatrixTransformations(mtx, *(FVector*)Pos, *(IRotator*)Rot, Scale);
if (render_set_position(mtx, 0) != 0) {
gSPDisplayList(gDisplayListHead++, Model);
}
}
}
void AActor::Collision(Player* player, AActor* actor) {}
void AActor::VehicleCollision(s32 playerId, Player* player){}
void AActor::Destroy() {
// Set uuid to zero.
memset(uuid, 0, sizeof(uuid));
}
bool AActor::IsMod() { return false; }
bool AActor::IsMod() { return false; }
void AActor::SetLocation(FVector pos) {
Pos[0] = pos.x;
Pos[1] = pos.y;
Pos[2] = pos.z;
}
FVector AActor::GetLocation() const {
return FVector(Pos[0], Pos[1], Pos[2]);
}
+7
View File
@@ -1,6 +1,7 @@
#pragma once
#include <libultraship.h>
#include "CoreMath.h"
extern "C" {
#include "macros.h"
@@ -24,6 +25,10 @@ public:
/* 0x24 */ Vec3f Velocity = {0, 0, 0};
/* 0x30 */ Collision Unk30;
uint8_t uuid[16];
const char* Name = "";
FVector Scale = {1, 1, 1};
Gfx* Model = NULL;
virtual ~AActor() = default; // Virtual destructor for proper cleanup in derived classes
@@ -33,6 +38,8 @@ public:
virtual void Draw(Camera*);
virtual void Collision(Player* player, AActor* actor);
virtual void VehicleCollision(s32 playerId, Player* player);
void SetLocation(FVector pos);
FVector GetLocation() const;
virtual void Destroy();
virtual bool IsMod();
+39
View File
@@ -0,0 +1,39 @@
#pragma once
#include "actors/MarioSign.h"
#include "actors/WarioSign.h"
#include "actors/Cloud.h"
#include "actors/Finishline.h"
#include "actors/SpaghettiShip.h"
#include "actors/Starship.h"
#include "actors/Ship.h"
#include "actors/Tree.h"
#include "vehicles/Train.h"
#include "vehicles/Boat.h"
#include "vehicles/Bus.h"
#include "vehicles/Truck.h"
#include "vehicles/Car.h"
#include "vehicles/Truck.h"
#include "vehicles/TankerTruck.h"
#include "objects/Bat.h"
#include "objects/BombKart.h"
#include "objects/Boos.h"
#include "objects/CheepCheep.h"
#include "objects/Crab.h"
#include "objects/ChainChomp.h"
#include "objects/Flagpole.h"
#include "objects/Hedgehog.h"
#include "objects/HotAirBalloon.h"
#include "objects/Lakitu.h"
#include "objects/Mole.h"
#include "objects/Penguin.h"
#include "objects/Seagull.h"
#include "objects/Thwomp.h"
#include "objects/Seagull.h"
#include "objects/TrashBin.h"
#include "objects/Trophy.h"
#include "objects/Snowman.h"
#include "objects/Podium.h"
#include "objects/GrandPrixBalloons.h"
+127 -18
View File
@@ -10,16 +10,55 @@
*
*/
/**
*
* Applies pos, rot, and scale
*
*/
struct FVector {
float x, y, z;
#ifdef __cplusplus
FVector& operator=(const FVector& other) {
x = other.x;
y = other.y;
z = other.z;
return *this;
// Operator to add two FVector objects
FVector operator+(const FVector& other) const {
return FVector(x + other.x, y + other.y, z + other.z);
}
// Operator to subtract two FVector objects
FVector operator-(const FVector& other) const {
return FVector(x - other.x, y - other.y, z - other.z);
}
// Operator to multiply a FVector by a scalar (float)
FVector operator*(float scalar) const {
return FVector(x * scalar, y * scalar, z * scalar);
}
float Dot(const FVector& other) const {
return x * other.x + y * other.y + z * other.z;
}
FVector Cross(const FVector& other) const {
return FVector(
y * other.z - z * other.y,
z * other.x - x * other.z,
x * other.y - y * other.x
);
}
float Magnitude() const {
return std::sqrt(x * x + y * y + z * z);
}
FVector Normalize() const {
float len = std::sqrt(x * x + y * y + z * z);
if (len > 0.0001f) {
return FVector(
x / len, y / len, z / len
);
}
return FVector(0, 0, 0);
}
FVector() : x(0), y(0), z(0) {}
@@ -27,6 +66,16 @@ struct FVector {
#endif // __cplusplus
};
struct FVector4 {
float x, y, z, w;
#ifdef __cplusplus
FVector4() : x(0), y(0), z(0), w(0) {}
FVector4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
#endif // __cplusplus
};
/**
* For providing X and Z when you do not need Y
* Some actors set themselves on the surface automatically
@@ -50,35 +99,95 @@ struct FVector2D {
// Sets integer X Z coordinates
typedef struct IVector2D {
int32_t X, Z;
int32_t X, Y;
#ifdef __cplusplus
IVector2D() : X(0), Z(0) {} // Default constructor
IVector2D() : X(0), Y(0) {} // Default constructor
IVector2D(int32_t x, int32_t z) : X(x), Z(z) {} // Constructor to initialize with values
IVector2D(int32_t x, int32_t y) : X(x), Y(y) {} // Constructor to initialize with values
IVector2D& operator=(const IVector2D& other) {
X = other.X;
Z = other.Z;
Y = other.Y;
return *this;
}
#endif // __cplusplus
} IVector2D;
struct FRotation {
float pitch, yaw, roll;
/**
* This struct immediately converts float pitch/yaw/roll in degrees to n64 int16_t binary angles 0-0xFFFF == 0-360 degrees
* ToDegrees() Receive an FRotator of float degrees back.
* Set() Set an n64 int16_t binary angles 0-0xFFFF
*/
struct IRotator {
uint16_t pitch, yaw, roll;
#ifdef __cplusplus
FRotation& operator=(const FRotation& other) {
IRotator& operator=(const IRotator& other) {
pitch = other.pitch;
yaw = other.yaw;
roll = other.roll;
yaw = other.yaw;
roll = other.roll;
return *this;
}
FRotation() : pitch(0), yaw(0), roll(0) {}
FRotation(float p, float y, float r) : pitch(p), yaw(y), roll(r) {}
[[nodiscard]] void Set(uint16_t p, uint16_t y, uint16_t r) {
pitch = p;
yaw = y;
roll = r;
}
IRotator() : pitch(0), yaw(0), roll(0) {}
IRotator(float p, float y, float r) {
pitch = p * (UINT16_MAX / 360);
yaw = y * (UINT16_MAX / 360);
roll = r * (UINT16_MAX / 360);
}
// Convert to radians as FVector
[[nodiscard]] FVector ToRadians() const {
float scale = 2.0f * M_PI / 65536.0f;
return FVector(
pitch * scale,
yaw * scale,
roll * scale
);
}
#endif // __cplusplus
};
/**
* Use IRotator unless you want to do some math in degrees.
* Always use ToBinary() or Rotator when sending into matrices or apply translation functions
* Convert from IRotator to FRotator float degrees by doing FRotator(myIRotator);
*/
struct FRotator {
float pitch, yaw, roll;
#ifdef __cplusplus
FRotator& operator=(const FRotator& other) {
pitch = other.pitch;
yaw = other.yaw;
roll = other.roll;
return *this;
}
// Convert to binary rotator 0 --> INT16_MAX
[[nodiscard]] IRotator ToBinary() const {
return IRotator(
static_cast<uint16_t>(pitch * (UINT16_MAX / 360)),
static_cast<uint16_t>(yaw * (UINT16_MAX / 360)),
static_cast<uint16_t>(roll * (UINT16_MAX / 360))
);
}
FRotator() : pitch(0), yaw(0), roll(0) {}
FRotator(float p, float y, float r) : pitch(p), yaw(y), roll(r) {}
FRotator(IRotator rot) {
pitch = static_cast<float>(rot.pitch * (360 / UINT16_MAX));
yaw = static_cast<float>(rot.yaw * (360 / UINT16_MAX));
roll = static_cast<float>(rot.roll * (360 / UINT16_MAX));
}
#endif // __cplusplus
};
@@ -118,4 +227,4 @@ struct IPathSpan {
#endif // __cplusplus
};
#endif // CORE_MATH_H
#endif // CORE_MATH_H
+1 -1
View File
@@ -1,7 +1,7 @@
#include "Cup.h"
#include "courses/Course.h"
Cup::Cup(const char* id, const char* name, std::vector<Course*> courses) {
Cup::Cup(std::string id, const char* name, std::vector<Course*> courses) {
Id = id;
Name = name;
Courses = courses;
+2 -2
View File
@@ -9,13 +9,13 @@ class Course; // <-- Forward declare
class Cup {
public:
const char* Id;
std::string Id;
const char* Name;
u8 *Thumbnail;
size_t CursorPosition = 0; // Course index in cup
std::vector<Course*> Courses;
explicit Cup(const char* id, const char* name, std::vector<Course*> courses);
explicit Cup(std::string id, const char* name, std::vector<Course*> courses);
virtual void ShuffleCourses();
+16 -2
View File
@@ -4,6 +4,7 @@
void RunGarbageCollector() {
//CleanActors();
CleanObjects();
CleanStaticMeshActors();
}
void CleanActors() {
@@ -18,14 +19,27 @@ void CleanActors() {
// }
}
void CleanStaticMeshActors() {
for (auto actor = gWorldInstance.StaticMeshActors.begin(); actor != gWorldInstance.StaticMeshActors.end();) {
StaticMeshActor* act = *actor; // Get a mutable copy
if (act->bPendingDestroy) {
delete act;
actor = gWorldInstance.StaticMeshActors.erase(actor); // Remove from container
continue;
} else {
actor++;
}
}
}
void CleanObjects() {
for (auto object = gWorldInstance.Objects.begin(); object != gWorldInstance.Objects.end();) {
OObject* obj = *object; // Get a mutable copy
if (obj->PendingDestroy) {
if (obj->bPendingDestroy) {
delete obj;
object = gWorldInstance.Objects.erase(object); // Remove from container
continue;
}
object++;
}
}
}
+1
View File
@@ -8,4 +8,5 @@
void RunGarbageCollector();
void CleanActors();
void CleanStaticMeshActors();
void CleanObjects();
+183
View File
@@ -0,0 +1,183 @@
#include <libultra/gbi.h>
#include <libultra/gu.h>
#include "HM_Intro.h"
#include "port/Game.h"
extern "C" {
#include "main.h"
#include "memory.h"
#include "math_util.h"
#include "courses/harbour/track.h"
#include "courses/harbour/powered.h"
#include "courses/harbour/ship2_model.h"
#include "courses/harbour/ship3_model.h"
#include "collision.h"
#include "menu_items.h"
#include "external.h"
#include "menus.h"
extern Gfx ship1_spag1_mesh[];
}
HarbourMastersIntro::HarbourMastersIntro() {
}
void HarbourMastersIntro::HM_InitIntro() {
_camera.Pos.x = 0;
_camera.Pos.y = 0;
_camera.Pos.z = 0;
// The camera setup was broken when this was first made. And then it was fixed.
// That's why this file has weird coordinates as the objects were positioned in-front of the camera view
// Instead of moving the camera to the right spot in the scene.
_camera.LookAt.x = 0;
_camera.LookAt.y = 0;
_camera.LookAt.z = -2500;
_cameraSpeed = 0.0f;
_cameraMaxSpeed = 16.0f;
_cameraAcceleration = 1.0f;
_pos = FVector(-1000, -205, -800); // -1000, -210, -800
_rot = IRotator(-5, 100, 0);
_scale = {0.7f, 0.7f, 0.7f};
_ship2Pos = FVector(300, -210, -1960);
_ship2Rot = IRotator(0, 45, 0);
_shipPos = FVector(20, -210, -1650);
_shipRot = IRotator(0, 45, 0);
_posHM64 = FVector(0, -500, -1000);
_rotHM64 = IRotator(0, -90, -4); // -0x2100
_hPos = FVector(-2000, 100, -4900);
_hRot = IRotator(0, -45.0f, 0);
_hScale = {2.0f, 2.0f, 2.0f};
lusPos = FVector(0, -400, -614); // 12, 190, -1000
lusRot = IRotator(0, 0, 0);
lusScale = FVector(1, 1, 1);
ground_f3d_material_013_lights = gdSPDefLights1(
0x7F, 0x30, 0x80,
0x60, 20, 10, 0x49, 0x49, 0x49
);
gEditor.AddObject("lus", &lusPos, &lusRot, &lusScale, nullptr, 1, Editor::GameObject::CollisionType::BOUNDING_BOX, 10, &DespawnValue, -1);
}
void HarbourMastersIntro::HM_TickIntro() {
_water += 1;
if (_water > 255) {
_water = 0;
}
HarbourMastersIntro::SpagBob(_pos, _rot, 2.5f, 0.18f, 1.5f, 0.05f, 1.7f, 0.06f);
HarbourMastersIntro::Bob(_shipPos, _shipRot, 1.2f, 0.06f, 1.6f, -0.04f, 1.1f, -0.04f);
HarbourMastersIntro::Bob(_ship2Pos, _ship2Rot, 1.2f, 0.06f, 1.6f, -0.04f, 1.1f, -0.04f);
_pos.x += 9;
if (lusPos.y < -60) {
lusPos.y += 3;
}
//_camera.Pos.x -= 1;
// SWITCH TO NEXT MENU LOGO_INTRO_MENU
if (_pos.x >= 1100) {
gMenuFadeType = 0;
gMenuSelection = LOGO_INTRO_MENU;
gFadeModeSelection = FADE_MODE_LOGO;
}
find_and_set_tile_size((uintptr_t) ((void*)mat_water_water1), 0, _water);
find_and_set_tile_size((uintptr_t) ((void*)mat_water_water2), _water, 0);;
}
void HarbourMastersIntro::Bob(FVector& pos, IRotator& rot, f32 bobAmp, f32 bobSpeed, f32 tiltAmp, f32 tiltSpeed, f32 rollAmp, f32 rollSpeed) {
float time = (float)gGlobalTimer;
pos.y = -210 + bobAmp * sin(time * bobSpeed);
rot.pitch = (tiltAmp * sin(time * tiltSpeed)) * (UINT16_MAX / 360);
rot.roll = (rollAmp * sin(time * rollSpeed)) * (UINT16_MAX / 360);
}
void HarbourMastersIntro::SpagBob(FVector& pos, IRotator& rot, f32 bobAmp, f32 bobSpeed, f32 tiltAmp, f32 tiltSpeed, f32 rollAmp, f32 rollSpeed) {
float time = (float)gGlobalTimer;
pos.y = -205 + bobAmp * sin(time * bobSpeed);
rot.pitch = (-5 + tiltAmp * sin(time * tiltSpeed)) * (UINT16_MAX / 360);
rot.roll = (rollAmp * sin(time * rollSpeed)) * (UINT16_MAX / 360);
}
void HarbourMastersIntro::HM_DrawIntro() {
HarbourMastersIntro::Setup();
gSPMatrix(gDisplayListHead++, &gGfxPool->mtxScreen, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
gSPMatrix(gDisplayListHead++, &gGfxPool->mtxLookAt[0], G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
gDPSetRenderMode(gDisplayListHead++, G_RM_AA_ZB_OPA_SURF, G_RM_AA_ZB_OPA_SURF2);
gDPSetEnvColor(gDisplayListHead++, 0x00, 0x00, 0x00, 0x00);
Mat4 mtx_spaghettiShip;
ApplyMatrixTransformations(mtx_spaghettiShip, _pos, _rot, _scale);
render_set_position(mtx_spaghettiShip, 0);
gSPDisplayList(gDisplayListHead++, ship1_spag1_mesh);
Mat4 mtx_ship2;
ApplyMatrixTransformations(mtx_ship2, _ship2Pos, _ship2Rot, _scale);
render_set_position(mtx_ship2, 0);
gSPDisplayList(gDisplayListHead++, ship2_SoH_mesh);
Mat4 mtx_ship3;
ApplyMatrixTransformations(mtx_ship3, _shipPos, _shipRot, _scale);
render_set_position(mtx_ship3, 0);
gSPDisplayList(gDisplayListHead++, ship3_2Ship_mesh);
Mat4 mtx_geo;
ApplyMatrixTransformations(mtx_geo, _hPos, _hRot, _hScale);
render_set_position(mtx_geo, 0);
gSPDisplayList(gDisplayListHead++, ground_map_mesh);
//gSPDisplayList(gDisplayListHead++, powered_Text_mesh); // Replaced by poweredbylus
gSPDisplayList(gDisplayListHead++, castle_map_002_mesh);
gSPDisplayList(gDisplayListHead++, road_map_001_mesh);
gSPDisplayList(gDisplayListHead++, water_water1_mesh);
Mat4 lusMtx;
ApplyMatrixTransformations(lusMtx, lusPos, lusRot, lusScale);
render_set_position(lusMtx, 0);
gSPDisplayList(gDisplayListHead++, (Gfx*)"__OTR__hmintro/poweredbylus");
HarbourMastersIntro::Sync();
}
void HarbourMastersIntro::Setup() {
u16 perspNorm;
move_segment_table_to_dmem();
gDPSetTexturePersp(gDisplayListHead++, G_TP_PERSP);
guPerspective(&gGfxPool->mtxScreen, &perspNorm, 45.0f, 1.3333334f, 100.0f, 12800.0f, 1.0f);
gSPPerspNormalize(gDisplayListHead++, perspNorm);
guLookAt(&gGfxPool->mtxLookAt[0], _camera.Pos.x, _camera.Pos.y, _camera.Pos.z, _camera.LookAt.x, _camera.LookAt.y, _camera.LookAt.z, 0.0f, 1.0f, 0.0f);
gDPSetCycleType(gDisplayListHead++, G_CYC_FILL);
gDPSetRenderMode(gDisplayListHead++, G_RM_OPA_SURF, G_RM_OPA_SURF2);
gSPClearGeometryMode(gDisplayListHead++, G_ZBUFFER | G_CULL_BACK | G_LIGHTING);
gDPSetFillColor(gDisplayListHead++, 0x00010001);
gDPFillRectangle(gDisplayListHead++, 0, 0, 319, 239);
gSPSetGeometryMode(gDisplayListHead++, G_ZBUFFER | G_CULL_BACK | G_LIGHTING);
gDPSetRenderMode(gDisplayListHead++, G_RM_AA_ZB_OPA_SURF, G_RM_AA_ZB_OPA_SURF2);
gDPSetCycleType(gDisplayListHead++, G_CYC_1CYCLE);
gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE);
gSPSetGeometryMode(gDisplayListHead++, G_SHADE | G_CULL_BACK | G_LIGHTING | G_SHADING_SMOOTH);
gDPPipeSync(gDisplayListHead++);
}
void HarbourMastersIntro::Sync() {
gDPPipeSync(gDisplayListHead++);
gDPSetTexturePersp(gDisplayListHead++, G_TP_NONE);
gDPSetTextureFilter(gDisplayListHead++, G_TF_BILERP);
}
+78
View File
@@ -0,0 +1,78 @@
#ifndef _HM_INTRO_H
#define _HM_INTRO_H
#include <libultraship.h>
#include <libultra/gbi.h>
#include "CoreMath.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "common_structs.h"
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
class HarbourMastersIntro {
public:
HarbourMastersIntro();
void HM_InitIntro();
void HM_TickIntro();
void HM_DrawIntro();
private:
void Setup();
void Sync();
void Bob(FVector& pos, IRotator& rot, f32 bobAmp, f32 bobSpeed, f32 tiltAmp, f32 tiltSpeed, f32 rollAmp, f32 rollSpeed);
void SpagBob(FVector& pos, IRotator& rot, f32 bobAmp, f32 bobSpeed, f32 tiltAmp, f32 tiltSpeed, f32 rollAmp, f32 rollSpeed);
void MoveCloserToCamera(float moveSpeed);
struct HMCamera {
FVector Pos;
FVector LookAt;
};
HMCamera _camera;
f32 _cameraSpeed;
f32 _cameraMaxSpeed;
f32 _cameraAcceleration;
FVector _pos;
IRotator _rot;
FVector _scale;
FVector _shipPos;
IRotator _shipRot;
FVector _ship2Pos;
IRotator _ship2Rot;
s32 _water = 0;
FVector _posHM64;
IRotator _rotHM64;
FVector _hPos;
IRotator _hRot;
FVector _hScale;
FVector lusPos;
IRotator lusRot;
FVector lusScale;
int32_t DespawnValue = 0;
};
extern "C" {
#endif
void HM_InitIntro(void);
void HM_TickIntro(void);
void HM_DrawIntro(void);
#ifdef __cplusplus
}
#endif
#endif // _HM_INTRO_H
+74 -1
View File
@@ -4,6 +4,8 @@
extern "C" {
#include "common_structs.h"
#include "math_util.h"
#include "math_util_2.h"
}
void AddMatrix(std::vector<Mtx>& stack, Mat4 mtx, s32 flags) {
@@ -26,7 +28,7 @@ Mtx* GetMatrix(std::vector<Mtx>& stack) {
}
/**
* Use GetMatrix first
* Use GetMatrix() first
*/
void AddMatrixFixed(std::vector<Mtx>& stack, s32 flags) {
// Load the matrix
@@ -58,6 +60,76 @@ Mtx* SetTextMatrix(f32 arg1, f32 arg2, f32 arg3, f32 arg4) {
return mtx;
}
void ApplyMatrixTransformations(Mat4 mtx, FVector pos, IRotator rot, FVector scale) {
f32 sine1, cosine1;
f32 sine2, cosine2;
f32 sine3, cosine3;
// Compute the sine and cosine of the orientation (Euler angles)
sine1 = sins(rot.pitch);
cosine1 = coss(rot.pitch);
sine2 = sins(rot.yaw);
cosine2 = coss(rot.yaw);
sine3 = sins(rot.roll);
cosine3 = coss(rot.roll);
// Compute the rotation matrix
mtx[0][0] = (cosine2 * cosine3) + ((sine1 * sine2) * sine3);
mtx[1][0] = (-cosine2 * sine3) + ((sine1 * sine2) * cosine3);
mtx[2][0] = cosine1 * sine2;
mtx[3][0] = pos.x;
mtx[0][1] = cosine1 * sine3;
mtx[1][1] = cosine1 * cosine3;
mtx[2][1] = -sine1;
mtx[3][1] = pos.y;
mtx[0][2] = (-sine2 * cosine3) + ((sine1 * cosine2) * sine3);
mtx[1][2] = (sine2 * sine3) + ((sine1 * cosine2) * cosine3);
mtx[2][2] = cosine1 * cosine2;
mtx[3][2] = pos.z;
// Apply scaling
mtx[0][0] *= scale.x;
mtx[1][0] *= scale.x;
mtx[2][0] *= scale.x;
mtx[0][1] *= scale.y;
mtx[1][1] *= scale.y;
mtx[2][1] *= scale.y;
mtx[0][2] *= scale.z;
mtx[1][2] *= scale.z;
mtx[2][2] *= scale.z;
// Set the last row and column for the homogeneous coordinate system
mtx[0][3] = 0.0f;
mtx[1][3] = 0.0f;
mtx[2][3] = 0.0f;
mtx[3][3] = 1.0f;
}
void AddLocalRotation(Mat4 mat, IRotator rot) {
f32 sin_pitch = sins(rot.pitch);
f32 cos_pitch = coss(rot.pitch);
f32 sin_yaw = sins(rot.yaw);
f32 cos_yaw = coss(rot.yaw);
f32 sin_roll = sins(rot.roll);
f32 cos_roll = coss(rot.roll);
// Modify only the rotation part (keep translation intact)
mat[0][0] = (cos_yaw * cos_roll) + (sin_pitch * sin_yaw * sin_roll);
mat[0][1] = (cos_pitch * sin_roll);
mat[0][2] = (-sin_yaw * cos_roll) + (sin_pitch * cos_yaw * sin_roll);
mat[1][0] = (-cos_yaw * sin_roll) + (sin_pitch * sin_yaw * cos_roll);
mat[1][1] = (cos_pitch * cos_roll);
mat[1][2] = (sin_yaw * sin_roll) + (sin_pitch * cos_yaw * cos_roll);
mat[2][0] = (cos_pitch * sin_yaw);
mat[2][1] = -sin_pitch;
mat[2][2] = (cos_pitch * cos_yaw);
}
// API
extern "C" {
@@ -122,3 +194,4 @@ extern "C" {
gWorldInstance.Mtx.Objects.clear();
}
}
+3
View File
@@ -4,9 +4,12 @@
#include <libultraship.h>
#include "common_structs.h"
#include "CoreMath.h"
#ifdef __cplusplus
extern "C" {
void ApplyMatrixTransformations(Mat4 mtx, FVector pos, IRotator rot, FVector scale);
void AddLocalRotation(Mat4 mat, IRotator rot);
#endif
void ClearMatrixPools(void);
void AddHudMatrix(Mat4 mtx, s32 flags);
+59
View File
@@ -0,0 +1,59 @@
// #include <vector>
// #include <functional>
// #include <iostream>
// #include <map>
// #include "Registry.h"
// #include "Course.h"
// #include "port/Game.h"
// template <class T> Registry<T>::Registry() {
// }
// template <class T> void Registry<T>::Add(std::string id, std::function<T*()> fn) {
// // need to handle duplicate registration
// ContentVault[id] = fn;
// }
// template <class T>
// void Registry<T>::AddArgs(std::string id) {
// ArgsVault[id] = [](Args&&... args) -> T* {
// return new T(std::forward<Args>(args)...);
// };
// }
// template <class T>
// T* Registry<T>::Get(std::string id) {
// auto it = ContentVault.find(id);
// if (it != ContentVault.end()) {
// return it->second();
// }
// return nullptr;
// }
// // Available Registries
// Registry<Course> Courses;
// Registry<Cup> Cups;
// Registry<AActor> Actors;
// void AddCourse(std::string id, Course* course) {
// Courses.Add(id, [course]() { return course; });
// course->Id = id;
// }
// void AddCup(std::string id, Cup* cup) {
// Cups.Add(id, [cup]() { return cup; });
// //cup->Id = id;
// }
// void AddActor(std::string id, AActor* actor) {
// Actors.Add(id, [actor]() { return actor; });
// }
// void AddStockContent() {
// AddActor("mk:banana", new AMarioSign({0, 0, 0}));
// }
// template class Registry<Course>;
// template class Registry<Cup>;
// template class Registry<AActor>;
+33
View File
@@ -0,0 +1,33 @@
// #pragma once
// #include "Course.h"
// #include "Cup.h"
// #include <unordered_map>
// #include "AllActors.h"
// #include "Actor.h"
// #include "objects/Object.h"
// class AActor; // <-- Forward delare
// template <class T> class Registry {
// public:
// Registry();
// void Add(std::string name, std::function<T*()>);
// template <typename... Args>
// void AddArgs(std::string id);
// T* Get(std::string id);
// private:
// std::unordered_map<std::string, std::function<T*()>> ContentVault;
// std::map<std::string, std::function<T*(Args&&...)>> ArgsVault;
// };
// void AddCourse(std::string id, Course* course);
// void AddCup(std::string id, Cup* cup);
// void AddActor(std::string id, AActor* actor);
// void AddStockContent();
// extern Registry<Course> Courses;
// extern Registry<Cup> Cups;
// extern Registry<AActor> Actors;
+29
View File
@@ -0,0 +1,29 @@
#include "StaticMeshActor.h"
#include <libultra/gbi.h>
#include "Matrix.h"
extern "C" {
#include "main.h"
#include "math_util.h"
#include "math_util_2.h"
}
StaticMeshActor::StaticMeshActor(std::string name, FVector pos, IRotator rot, FVector scale, std::string model, int32_t* collision) : Name(name), Pos(pos), Rot(rot), Scale(scale), Model(""), Collision(collision) {
}
void StaticMeshActor::Draw() {
Mat4 mtx;
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
if (!Model.empty()) {
ApplyMatrixTransformations(mtx, Pos, Rot, Scale);
if (render_set_position(mtx, 0) != 0) {
gSPDisplayList(gDisplayListHead++, (Gfx*)Model.c_str());
}
}
}
void StaticMeshActor::Destroy() {
bPendingDestroy = true;
}
+61
View File
@@ -0,0 +1,61 @@
#pragma once
#include <libultraship.h>
#include <libultra/gbi.h>
#include "CoreMath.h"
#include <nlohmann/json.hpp>
// todo: Make this class AStaticMeshActor : public AActor
class StaticMeshActor {
public:
std::string Name;
FVector Pos;
IRotator Rot;
FVector Scale;
std::string Model;
int32_t* Collision;
bool bPendingDestroy = false;
StaticMeshActor(std::string name, FVector pos, IRotator rot, FVector scale, std::string model, int32_t* collision);
nlohmann::json to_json() const {
nlohmann::json j;
// Serialize each field of the class
j["Name"] = Name;
j["Position"] = {Pos.x, Pos.y, Pos.z}; // Assuming FVector has x, y, z fields
j["Rotation"] = {Rot.pitch, Rot.yaw, Rot.roll}; // Assuming IRotator has pitch, yaw, roll fields
j["Scale"] = {Scale.x, Scale.y, Scale.z}; // Assuming FVector has x, y, z fields
j["Model"] = Model;
// If Collision is not null, serialize it
if (Collision != nullptr) {
j["Collision"] = *Collision; // Serialize the value that Collision points to
} else {
j["Collision"] = nullptr; // Handle the case where Collision is nullptr
}
return j;
}
void from_json(const nlohmann::json& j) {
Name = j.at("Name").get<std::string>();
Pos = FVector(j.at("Position")[0].get<float>(), j.at("Position")[1].get<float>(), j.at("Position")[2].get<float>());
Rot.Set(j.at("Rotation")[0].get<uint16_t>(), j.at("Rotation")[1].get<uint16_t>(), j.at("Rotation")[2].get<uint16_t>());
Scale = FVector(j.at("Scale")[0].get<float>(), j.at("Scale")[1].get<float>(), j.at("Scale")[2].get<float>());
// Deserialize the Model string
Model = j.at("Model").get<std::string>();
// Check if Collision is present in the JSON and deserialize it
//if (j.contains("Collision") && !j["Collision"].is_null()) {
// If Collision is a valid value, allocate memory for it and assign the value
// Collision = new int32_t(j.at("Collision").get<int32_t>());
//} else {
// If Collision is not present or is null, set it to nullptr
Collision = nullptr;
//}
}
virtual void Draw();
virtual void Destroy();
};
+78 -6
View File
@@ -6,14 +6,19 @@
#include "TrainCrossing.h"
#include <memory>
#include "objects/Object.h"
#include "port/Game.h"
#include "editor/GameObject.h"
extern "C" {
#include "camera.h"
#include "objects.h"
#include "main.h"
#include "defines.h"
#include "audio/external.h"
#include "menus.h"
#include "camera.h"
#include "objects.h"
#include "main.h"
#include "defines.h"
#include "audio/external.h"
#include "menus.h"
#include "common_data.h"
#include "mario_raceway_data.h"
}
World::World() {}
@@ -112,15 +117,34 @@ void World::PreviousCourse() {
AActor* World::AddActor(AActor* actor) {
Actors.push_back(actor);
if (actor->Model != NULL) {
gEditor.AddObject(actor->Name, (FVector*) &actor->Pos, (IRotator*)&actor->Rot, &actor->Scale,
(Gfx*) LOAD_ASSET_RAW(actor->Model), 1.0f, Editor::GameObject::CollisionType::VTX_INTERSECT,
0.0f, (int32_t*) &actor->Type, 0);
} else {
gEditor.AddObject(actor->Name, (FVector*) &actor->Pos, (IRotator*)&actor->Rot, &actor->Scale, nullptr, 1.0f, Editor::GameObject::CollisionType::VTX_INTERSECT, 0.0f, (int32_t*)&actor->Type, 0);
}
return Actors.back();
}
struct Actor* World::AddBaseActor() {
Actors.push_back(new AActor());
AActor* actor = Actors.back();
// Skip C++ vtable to access variables in C
return reinterpret_cast<struct Actor*>(reinterpret_cast<char*>(Actors.back()) + sizeof(void*));
}
void World::AddEditorObject(Actor* actor, const char* name) {
if (actor->model != NULL) {
gEditor.AddObject(name, (FVector*) &actor->pos, (IRotator*)&actor->rot, nullptr, (Gfx*)LOAD_ASSET_RAW(actor->model), 1.0f, Editor::GameObject::CollisionType::VTX_INTERSECT, 0.0f, (int32_t*)&actor->type, 0);
} else {
gEditor.AddObject(name, (FVector*) &actor->pos, (IRotator*)&actor->rot, nullptr, nullptr, 1.0f, Editor::GameObject::CollisionType::VTX_INTERSECT, 0.0f, (int32_t*)&actor->type, 0);
}
}
/**
* Converts a C struct Actor* to its C++ AActor class
*/
@@ -153,8 +177,44 @@ void World::TickActors() {
}
}
StaticMeshActor* World::AddStaticMeshActor(std::string name, FVector pos, IRotator rot, FVector scale, std::string model, int32_t* collision) {
StaticMeshActors.push_back(new StaticMeshActor(name, pos, rot, scale, model, collision));
auto actor = StaticMeshActors.back();
auto gameObj = gEditor.AddObject(actor->Name.c_str(), &actor->Pos, &actor->Rot, &actor->Scale, (Gfx*) LOAD_ASSET_RAW(actor->Model.c_str()), 1.0f,
Editor::GameObject::CollisionType::VTX_INTERSECT, 0.0f, (int32_t*) &actor->bPendingDestroy, (int32_t) true);
return actor;
}
void World::DrawStaticMeshActors() {
for (const auto& actor: StaticMeshActors) {
actor->Draw();
}
}
void World::DeleteStaticMeshActors() {
for (auto it = StaticMeshActors.begin(); it != StaticMeshActors.end();) {
if ((*it)->bPendingDestroy) {
delete *it; // Deallocate memory for the actor
it = StaticMeshActors.erase(it); // Remove the pointer from the vector
} else {
++it; // Only increment the iterator if we didn't erase an element
}
}
}
OObject* World::AddObject(OObject* object) {
Objects.push_back(object);
if (object->_objectIndex != -1) {
Object* cObj = &gObjectList[object->_objectIndex];
if (cObj->model != NULL) {
gEditor.AddObject(object->Name, (FVector*) &cObj->origin_pos[0], (IRotator*)&cObj->orientation, nullptr, (Gfx*)LOAD_ASSET_RAW(cObj->model), 1.0f, Editor::GameObject::CollisionType::VTX_INTERSECT, 0.0f, &object->_objectIndex, -1);
} else {
gEditor.AddObject(object->Name, (FVector*) &cObj->origin_pos[0], (IRotator*)&cObj->orientation, nullptr, nullptr, 1.0f, Editor::GameObject::CollisionType::VTX_INTERSECT, 0.0f, &object->_objectIndex, -1);
}
}
return Objects.back();
}
@@ -209,3 +269,15 @@ Object* World::GetObjectByIndex(size_t index) {
//}
return nullptr; // Or handle the error as needed
}
void World::ClearWorld(void) {
World::DeleteStaticMeshActors();
CM_CleanWorld();
// for (size_t i = 0; i < ARRAY_COUNT(gCollisionMesh); i++) {
// }
// gCollisionMesh
// Paths
}
+15 -2
View File
@@ -18,20 +18,26 @@
#include <memory>
#include <unordered_map>
#include "Actor.h"
#include "StaticMeshActor.h"
#include "particles/ParticleEmitter.h"
#include "editor/Editor.h"
#include "editor/GameObject.h"
extern "C" {
#include "camera.h"
#include "objects.h"
};
class OObject;
class Cup; // <-- Forward declaration
class OObject;
class Course;
class StaticMeshActor;
class AVehicle;
class OBombKart;
class TrainCrossing;
class OLakitu;
class GameObject; // <-- Editor
class World {
typedef struct {
@@ -49,12 +55,17 @@ public:
AActor* AddActor(AActor* actor);
struct Actor* AddBaseActor();
void AddEditorObject(Actor* actor, const char* name);
AActor* GetActor(size_t index);
void TickActors();
AActor* ConvertActorToAActor(Actor* actor);
Actor* ConvertAActorToActor(AActor* actor);
void DrawStaticMeshActors();
StaticMeshActor* AddStaticMeshActor(std::string name, FVector pos, IRotator rot, FVector scale, std::string model, int32_t* collision);
void DeleteStaticMeshActors();
OObject* AddObject(OObject* object);
void TickObjects();
@@ -76,6 +87,7 @@ public:
void SetCourseFromCup();
World* GetWorld(void);
void ClearWorld(void);
// These are only for browsing through the course list
@@ -85,7 +97,6 @@ public:
Matrix Mtx;
// Holds all available courses
Course* CurrentCourse;
Cup* CurrentCup;
@@ -93,6 +104,7 @@ public:
std::vector<Cup*> Cups;
size_t CupIndex = 1;
std::vector<StaticMeshActor*> StaticMeshActors;
std::vector<AActor*> Actors;
std::vector<OObject*> Objects;
std::vector<ParticleEmitter*> Emitters;
@@ -105,6 +117,7 @@ public:
TrainCrossing* AddCrossing(Vec3f position, u32 waypointMin, u32 waypointMax, f32 approachRadius, f32 exitRadius);
std::vector<std::shared_ptr<TrainCrossing>> Crossings;
// Holds all available courses
std::vector<Course*> Courses;
size_t CourseIndex = 0; // For browsing courses.
private:
@@ -1,6 +1,6 @@
#include <libultraship.h>
#include "ABanana.h"
#include "Banana.h"
#include "engine/Actor.h"
extern "C" {
@@ -11,6 +11,7 @@ void render_actor_banana(Camera*, float[4][4], struct BananaActor*);
}
ABanana::ABanana(uint16_t playerId, const float pos[3], const s16 rot[3], const float velocity[3]) {
Name = "Banana";
// Initialize the BananaActor's position, rotation, and velocity
std::copy(pos, pos + 3, Pos);
//std::copy(rot, rot + 3, this->a.rot);
@@ -10,7 +10,6 @@ public:
// Constructor
ABanana(uint16_t playerId, const float pos[3], const s16 rot[3], const float velocity[3]);
virtual ~ABanana() override = default;
// Virtual functions to be overridden by derived classes
+1
View File
@@ -13,6 +13,7 @@ Vtx gBowserStatueVtx[717];
Gfx gBowserStatueGfx[162];
ABowserStatue::ABowserStatue(FVector pos, ABowserStatue::Behaviour behaviour) {
Name = "Bowser Statue";
Pos = pos;
ABowserStatue::Behaviour _behaviour = behaviour;
}
@@ -1,6 +1,6 @@
#include <libultraship.h>
#include "ACloud.h"
#include "Cloud.h"
#include "engine/Actor.h"
#include "World.h"
@@ -14,10 +14,11 @@ extern f32 gKartHopInitialVelocityTable[];
extern f32 gKartGravityTable[];
}
ACloud::ACloud(Vec3f pos) {
Pos[0] = pos[0];
Pos[1] = pos[1];
Pos[2] = pos[2];
ACloud::ACloud(FVector pos) {
Name = "Cloud";
Pos[0] = pos.x;
Pos[1] = pos.y;
Pos[2] = pos.z;
Rot[0] = 0;
Rot[1] = 0;
Rot[2] = 0;
@@ -2,6 +2,7 @@
#include <libultraship.h>
#include "engine/Actor.h"
#include "CoreMath.h"
extern "C" {
#include "macros.h"
@@ -15,7 +16,7 @@ public:
// Constructor
ACloud(Vec3f pos);
ACloud(FVector pos);
virtual ~ACloud() override = default;
@@ -2,7 +2,7 @@
#include <libultra/gbi.h>
#include "CoreMath.h"
#include "AFinishline.h"
#include "Finishline.h"
#include "engine/Actor.h"
#include "World.h"
#include "assets/common_data.h"
@@ -18,6 +18,7 @@ extern f32 gKartGravityTable[];
}
AFinishline::AFinishline(std::optional<FVector> pos) {
Name = "Finishline";
if (pos.has_value()) {
// Set spawn point to the provided position
+56
View File
@@ -0,0 +1,56 @@
#include "MarioSign.h"
#include <libultra/gbi.h>
#include <assets/mario_raceway_data.h>
extern "C" {
#include "common_structs.h"
#include "math_util.h"
#include "main.h"
#include "actor_types.h"
}
AMarioSign::AMarioSign(FVector pos) {
Type = ACTOR_MARIO_SIGN;
Name = "Mario Sign";
Pos[0] = pos.x;
Pos[1] = pos.y;
Pos[2] = pos.z;
Flags |= 0x4000;
}
void AMarioSign::Tick() {
if ((Flags & 0x800) == 0) {
if ((Flags & 0x400) != 0) {
Pos[1] += 4.0f;
if (Pos[1] > 800.0f) {
Flags |= 0x800;
Rot[1] += 1820;
}
} else {
Rot[1] += 182;
}
}
}
void AMarioSign::Draw(Camera *camera) {
Mat4 sp40;
f32 unk;
if (Flags & 0x800) {
return;
}
unk = is_within_render_distance(camera->pos, Pos, camera->rot[1], 0, gCameraZoom[camera - camera1], 16000000.0f);
if (CVarGetInteger("gNoCulling", 0) == 1) {
unk = MAX(unk, 0.0f);
}
if (!(unk < 0.0f)) {
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
mtxf_pos_rotation_xyz(sp40, Pos, Rot);
if (render_set_position(sp40, 0) != 0) {
gSPDisplayList(gDisplayListHead++, (Gfx*)d_course_mario_raceway_dl_sign);
}
}
}
+19
View File
@@ -0,0 +1,19 @@
#pragma once
#include <libultraship.h>
#include "engine/Actor.h"
#include "CoreMath.h"
extern "C" {
#include "common_structs.h"
}
class AMarioSign : public AActor {
public:
virtual ~AMarioSign() = default;
explicit AMarioSign(FVector pos);
virtual void Tick() override;
virtual void Draw(Camera*) override;
};
+20 -25
View File
@@ -1,6 +1,8 @@
#include "Ship.h"
#include <libultra/gbi.h>
#include "CoreMath.h"
#include "Matrix.h"
extern "C" {
#include "common_structs.h"
@@ -14,48 +16,41 @@ extern "C" {
AShip::AShip(FVector pos, AShip::Skin skin) {
Spawn = pos;
Spawn.y += 10;
Pos[0] = pos.x;
Pos[1] = pos.y;
Pos[2] = pos.z;
Scale = FVector(0.4, 0.4, 0.4);
switch(skin) {
case GHOSTSHIP:
Name = "Ghostship";
_skin = ghostship_Plane_mesh;
break;
case SHIP2:
Name = "Ship_1";
_skin = ship2_SoH_mesh;
break;
case SHIP3:
Name = "Ship_2";
_skin = ship3_2Ship_mesh;
break;
}
Model = _skin;
}
void AShip::Tick() {
static float angle = 0.0f; // Keeps track of the ship's rotation around the circle
float radius = 150.0f; // The radius of the circular path
float speed = 0.01f; // Speed of rotation
// static float angle = 0.0f; // Keeps track of the ship's rotation around the circle
// float radius = 150.0f; // The radius of the circular path
// float speed = 0.01f; // Speed of rotation
angle += speed; // Increment the angle to move in a circle
// angle += speed; // Increment the angle to move in a circle
// Update the position based on a circular path
Pos.x = Spawn.x + radius * cosf(angle);
Pos.z = Spawn.z + radius * sinf(angle);
// // Update the position based on a circular path
// Pos.x = Spawn.x + radius * cosf(angle);
// Pos.z = Spawn.z + radius * sinf(angle);
// Rotate to face forward along the circle
Rot.yaw = -static_cast<int16_t>(angle * (32768.0f / M_PI / 2.0f));
}
void AShip::Draw(Camera *camera) {
Mat4 shipMtx;
Vec3f hullPos = {Pos.x, Pos.y, Pos.z};
Vec3s hullRot = {Rot.pitch, Rot.yaw, Rot.roll};
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
mtxf_pos_rotation_xyz(shipMtx, hullPos, hullRot);
mtxf_scale(shipMtx, 0.4);
if (render_set_position(shipMtx, 0) != 0) {
gSPDisplayList(gDisplayListHead++, _skin);
}
// // Rotate to face forward along the circle
// Rot.yaw = -static_cast<int16_t>(angle * (32768.0f / M_PI / 2.0f));
}
bool AShip::IsMod() { return true; }
+3 -3
View File
@@ -23,12 +23,12 @@ public:
virtual ~AShip() = default;
virtual void Tick() override;
virtual void Draw(Camera*) override;
virtual bool IsMod() override;
FVector Spawn;
FVector Pos;
FRotation Rot = {0, 0, 0};
//FVector Pos;
///IRotator Rot = {0, 0, 0};
//FVector Scale = {0.4, 0.4, 0.4};
private:
Gfx* _skin;
};
+19 -18
View File
@@ -1,6 +1,7 @@
#include "SpaghettiShip.h"
#include <libultra/gbi.h>
#include "Matrix.h"
extern "C" {
#include "common_structs.h"
@@ -10,8 +11,13 @@ extern "C" {
}
ASpaghettiShip::ASpaghettiShip(FVector pos) {
Name = "Spaghetti Ship";
Pos[0] = pos.x;
Pos[1] = pos.y;
Pos[2] = pos.z;
Spawn = pos;
Spawn.y += 10;
Scale = {0.4, 0.4, 0.4};
}
void ASpaghettiShip::Tick() {
@@ -22,12 +28,11 @@ void ASpaghettiShip::Tick() {
angle += speed; // Increment the angle to move in a circle
// Update the position based on a circular path
Pos.x = Spawn.x + radius * cosf(angle);
Pos.z = Spawn.z + radius * sinf(angle);
Pos[0] = Spawn.x + radius * cosf(angle);
Pos[2] = Spawn.z + radius * sinf(angle);
// Rotate to face forward along the circle
Rot.yaw = -static_cast<int16_t>(angle * (32768.0f / M_PI / 2.0f));
Rot[1] = -static_cast<int16_t>(angle * (32768.0f / M_PI / 2.0f));
WheelRot.pitch += 500;
}
@@ -36,30 +41,27 @@ void ASpaghettiShip::Draw(Camera *camera) {
Mat4 shipMtx;
Mat4 objectMtx;
Mat4 resultMtx;
Vec3f hullPos = {Pos.x, Pos.y, Pos.z};
Vec3s hullRot = {Rot.pitch, Rot.yaw, Rot.roll};
Vec3f hullPos = {Pos[0], Pos[1], Pos[2]};
Vec3s hullRot = {Rot[0], Rot[1], Rot[2]};
Vec3s rot = {WheelRot.pitch, WheelRot.yaw, WheelRot.roll};
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
// empty/null mtx as a base
mtxf_pos_rotation_xyz(shipMtx, hullPos, hullRot);
mtxf_scale(shipMtx, 0.4);
ApplyMatrixTransformations(shipMtx, *(FVector*)Pos, *(IRotator*)Rot, Scale);
if (render_set_position(shipMtx, 0) != 0) {}
// Render the ships hull
Vec3f hullPos2 = {0, 0, 0};
mtxf_translate(objectMtx, hullPos2);
ApplyMatrixTransformations(objectMtx, {0, 0, 0}, {0, 0, 0}, {1, 1, 1});
mtxf_multiplication(resultMtx, shipMtx, objectMtx);
if (render_set_position(resultMtx, 3) != 0) {
gSPDisplayList(gDisplayListHead++, ship1_Spaghetti_mesh);
gSPDisplayList(gDisplayListHead++, ship1_spag1_mesh);
}
// Front tyre
Vec3f pos = {0, 0, 110};
mtxf_rotate_x(shipMtx, WheelRot.pitch);
mtxf_translate(objectMtx, pos);
ApplyMatrixTransformations(objectMtx, FVector(0, 0, 110), IRotator(0, 0, 0), FVector(1, 1, 1));
mtxf_identity(shipMtx);
AddLocalRotation(shipMtx, WheelRot);
mtxf_multiplication(resultMtx, shipMtx, objectMtx);
if (render_set_position(resultMtx, 3) != 0) {
gSPDisplayList(gDisplayListHead++, wheels_Spaghetti_002_mesh);
@@ -67,9 +69,8 @@ void ASpaghettiShip::Draw(Camera *camera) {
}
// Back tyre
Vec3f pos2 = {0, 0, -165};
mtxf_rotate_x(shipMtx, WheelRot.pitch);
mtxf_translate(objectMtx, pos2);
AddLocalRotation(shipMtx, WheelRot);
ApplyMatrixTransformations(objectMtx, FVector(0, 0, -165), {0, 0, 0}, {1, 1, 1});
mtxf_multiplication(resultMtx, shipMtx, objectMtx);
if (render_set_position(resultMtx, 3) != 0) {
gSPDisplayList(gDisplayListHead++, wheels_Spaghetti_002_mesh);
+1 -5
View File
@@ -20,9 +20,5 @@ public:
virtual bool IsMod() override;
FVector Spawn;
FVector Pos;
FRotation Rot = {0, 0, 0};
FRotation WheelRot = {0, 0, 0};
private:
f32 scale;
IRotator WheelRot = {0, 0, 0};
};
+12 -19
View File
@@ -1,6 +1,7 @@
#include "Starship.h"
#include <libultra/gbi.h>
#include "Matrix.h"
extern "C" {
#include "common_structs.h"
@@ -10,7 +11,11 @@ extern "C" {
}
AStarship::AStarship(FVector pos) {
Name = "Starship";
Spawn = pos;
SetLocation(pos);
Scale = FVector(1.5, 1.5, 1.5);
Model = starship_Cube_mesh;
}
void AStarship::Tick() {
@@ -21,29 +26,17 @@ void AStarship::Tick() {
angle += speed;
// Move relative to the initial position
Pos.x = Spawn.x + radius * cosf(angle);
Pos.z = Spawn.z + radius * sinf(angle);
FVector pos = GetLocation();
pos.x = Spawn.x + radius * cosf(angle);
pos.z = Spawn.z + radius * sinf(angle);
SetLocation(pos);
// Keep y from changing (or adjust it if necessary)
Pos.y = Spawn.y;
//Pos.y = Spawn.y;
// Rotate to face forward along the circle
Rot.yaw = angle * (180.0f / M_PI) + 90.0f;
}
void AStarship::Draw(Camera *camera) {
Mat4 shipMtx;
Vec3f hullPos = {Pos.x, Pos.y, Pos.z};
Vec3s hullRot = {Rot.pitch, Rot.yaw, Rot.roll};
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
mtxf_pos_rotation_xyz(shipMtx, hullPos, hullRot);
mtxf_scale(shipMtx, 1.5);
if (render_set_position(shipMtx, 0) != 0) {
gSPDisplayList(gDisplayListHead++, starship_Cube_mesh);
}
Rot[1] = angle * (180.0f / M_PI) + 90.0f;
}
bool AStarship::IsMod() { return true; }
-3
View File
@@ -16,10 +16,7 @@ public:
virtual ~AStarship() = default;
virtual void Tick() override;
virtual void Draw(Camera*) override;
virtual bool IsMod() override;
FVector Spawn;
FVector Pos;
FRotation Rot = {0, 0, 0};
};
@@ -1,4 +1,4 @@
#include "ATree.h"
#include "Tree.h"
#include <libultra/gbi.h>
@@ -10,6 +10,7 @@ extern "C" {
}
ATree::ATree(Vec3f pos, Gfx* displaylist, f32 drawDistance, f32 minDrawDistance, const char* tlut = nullptr) {
Name = "Tree";
Pos[0] = pos[0];
Pos[1] = pos[1];
Pos[2] = pos[2];
@@ -1,4 +1,4 @@
#include "AWarioSign.h"
#include "WarioSign.h"
#include <libultra/gbi.h>
#include <assets/wario_stadium_data.h>
@@ -7,12 +7,15 @@ extern "C" {
#include "common_structs.h"
#include "math_util.h"
#include "main.h"
#include "actor_types.h"
}
AWarioSign::AWarioSign(Vec3f pos) {
Pos[0] = pos[0];
Pos[1] = pos[1];
Pos[2] = pos[2];
AWarioSign::AWarioSign(FVector pos) {
Type = ACTOR_WARIO_SIGN;
Name = "Wario Sign";
Pos[0] = pos.x;
Pos[1] = pos.y;
Pos[2] = pos.z;
}
void AWarioSign::Tick() {
@@ -27,7 +30,6 @@ void AWarioSign::Draw(Camera *camera) {
if (CVarGetInteger("gNoCulling", 0) == 1) {
unk = MAX(unk, 0.0f);
}
if (!(unk < 0.0f)) {
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
@@ -2,6 +2,7 @@
#include <libultraship.h>
#include "engine/Actor.h"
#include "CoreMath.h"
extern "C" {
#include "common_structs.h"
@@ -10,9 +11,8 @@ extern "C" {
class AWarioSign : public AActor {
public:
virtual ~AWarioSign() = default;
explicit AWarioSign(Vec3f pos);
explicit AWarioSign(FVector pos);
virtual void Tick() override;
virtual void Draw(Camera*) override;
+25 -33
View File
@@ -5,7 +5,7 @@
#include "BansheeBoardwalk.h"
#include "World.h"
#include "engine/actors/AFinishline.h"
#include "engine/actors/Finishline.h"
#include "engine/objects/BombKart.h"
#include "engine/objects/CheepCheep.h"
#include "engine/objects/TrashBin.h"
@@ -35,6 +35,7 @@ extern "C" {
#include "collision.h"
#include "memory.h"
#include "course_offsets.h"
#include "course.h"
extern const char *banshee_boardwalk_dls[];
}
@@ -69,17 +70,26 @@ BansheeBoardwalk::BansheeBoardwalk() {
this->gfx = d_course_banshee_boardwalk_packed_dls;
this->gfxSize = 3689;
Props.textures = banshee_boardwalk_textures;
Props.MinimapTexture = gTextureCourseOutlineBansheeBoardwalk;
Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
Props.Minimap.Texture = gTextureCourseOutlineBansheeBoardwalk;
Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
Props.Minimap.Pos[0].X = 262;
Props.Minimap.Pos[0].Y = 170;
Props.Minimap.PlayerX = 55;
Props.Minimap.PlayerY = 39;
Props.Minimap.PlayerScaleFactor = 0.016f;
Props.Minimap.FinishlineX = 0;
Props.Minimap.FinishlineY = 0;
Id = "mk:banshee_boardwalk";
Props.SetText(Props.Name, "banshee boardwalk", sizeof(Props.Name));
Props.SetText(Props.DebugName, "ghost", sizeof(Props.DebugName));
Props.SetText(Props.CourseLength, "747m", sizeof(Props.CourseLength));
Props.Id = "mk:banshee_boardwalk";
Props.Name = "banshee boardwalk";
Props.DebugName = "ghost";
Props.CourseLength = "747m";
Props.AIBehaviour = D_0D009058;
Props.AIMaximumSeparation = 40.0f;
Props.AIMinimumSeparation = 0.4f;
Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 2.0f;
@@ -119,8 +129,6 @@ BansheeBoardwalk::BansheeBoardwalk() {
Props.Clouds = NULL; // no clouds
Props.CloudList = NULL;
Props.MinimapFinishlineX = 0;
Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {0, 0, 0};
Props.Skybox.BottomRight = {0, 0, 0};
@@ -131,6 +139,8 @@ BansheeBoardwalk::BansheeBoardwalk() {
Props.Skybox.FloorBottomLeft = {0, 0, 0};
Props.Skybox.FloorTopLeft = {0, 0, 0};
Props.Sequence = MusicSeq::MUSIC_SEQ_BANSHEE_BOARDWALK;
Props.WaterLevel = -80.0f;
}
void BansheeBoardwalk::Load() {
@@ -140,10 +150,9 @@ void BansheeBoardwalk::Load() {
D_801625EC = 0;
D_801625F4 = 0;
D_801625F0 = 0;
parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_banshee_boardwalk_track_sections));
parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_banshee_boardwalk_track_sections));
func_80295C6C();
find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000878), 128, 0, 0, 0);
D_8015F8E4 = -80.0f;
}
void BansheeBoardwalk::LoadTextures() {
@@ -163,19 +172,19 @@ void BansheeBoardwalk::BeginPlay() {
}
if (gIsMirrorMode) {
gWorldInstance.AddObject(new OTrashBin(FVector(1765.0f, 45.0f, 195.0f), FRotation(0, 180.0f, 0), 1.0f, bhv));
gWorldInstance.AddObject(new OTrashBin(FVector(1765.0f, 45.0f, 195.0f), IRotator(0, 180, 0), 1.0f, bhv));
} else {
gWorldInstance.AddObject(new OTrashBin(FVector(-1765.0f, 45.0f, 70.0f), FRotation(0, 0, 0), 1.0f, bhv));
gWorldInstance.AddObject(new OTrashBin(FVector(-1765.0f, 45.0f, 70.0f), IRotator(0, 0, 0), 1.0f, bhv));
}
if ((gGamestate != CREDITS_SEQUENCE) && (gModeSelection != TIME_TRIALS)) {
gWorldInstance.AddObject(new OBat(FVector(0,0,0), FRotation(0, 0, 90.0f)));
gWorldInstance.AddObject(new OBat(FVector(0,0,0), IRotator(0, 0, 90)));
gWorldInstance.AddObject(new OBoos(5, IPathSpan(180, 190), IPathSpan(200, 210), IPathSpan(280, 290)));
gWorldInstance.AddObject(new OBoos(5, IPathSpan(490, 500), IPathSpan(510, 520), IPathSpan(620, 630)));
}
if (gModeSelection == VERSUS) {
Vec3f pos = {0, 0, 0};
FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][110], 110, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][190], 190, 1, 0.8333333f));
@@ -187,15 +196,6 @@ void BansheeBoardwalk::BeginPlay() {
}
}
// Likely sets minimap boundaries
void BansheeBoardwalk::MinimapSettings() {
D_80165880 = dma_textures((const char*)gTextureGhosts, 0x4CC2, 0xD980);
D_8018D2A0 = 0.016f;
D_8018D2C0[0] = 0x0106;
D_8018D2E0 = 55;
D_8018D2E8 = 39;
}
void BansheeBoardwalk::InitCourseObjects() {
size_t objectId = 0;
if (gGamestate != CREDITS_SEQUENCE) {
@@ -253,12 +253,6 @@ void BansheeBoardwalk::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
// Positions the finishline on the minimap
void BansheeBoardwalk::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
void BansheeBoardwalk::Render(struct UnkStruct_800DC5EC* arg0) {
Camera* camera = arg0->camera;
Mat4 spCC;
@@ -322,8 +316,6 @@ void BansheeBoardwalk::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_banshee_boardwalk_dl_B308));
}
void BansheeBoardwalk::Collision() {}
void BansheeBoardwalk::ScrollingTextures() {
D_802B87BC++;
-3
View File
@@ -28,17 +28,14 @@ public:
virtual void LoadTextures() override;
virtual void BeginPlay() override;
//virtual void InitClouds() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void UpdateCourseObjects() override;
virtual void RenderCourseObjects(s32 cameraId) override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void ScrollingTextures() override;
virtual void Waypoints(Player*, int8_t) override;
virtual void DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) override;
+18 -37
View File
@@ -43,16 +43,24 @@ BigDonut::BigDonut() {
this->gfx = d_course_big_donut_packed_dls;
this->gfxSize = 528;
Props.textures = big_donut_textures;
Props.MinimapTexture = gTextureCourseOutlineBigDonut;
Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
Props.Minimap.Texture = gTextureCourseOutlineBigDonut;
Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
Props.Minimap.Pos[0].X = 257;
Props.Minimap.Pos[0].Y = 170;
Props.Minimap.PlayerX = 32;
Props.Minimap.PlayerY = 31;
Props.Minimap.PlayerScaleFactor = 0.0257f;
Props.Minimap.FinishlineX = 0;
Props.Minimap.FinishlineY = 0;
Props.SetText(Props.Name, "big donut", sizeof(Props.Name));
Props.SetText(Props.DebugName, "doughnut", sizeof(Props.DebugName));
Props.SetText(Props.CourseLength, "", sizeof(Props.CourseLength));
Props.Name = "big donut";
Props.DebugName = "doughnut";
Props.CourseLength = "";
Props.AIBehaviour = D_0D008F18;
Props.AIMaximumSeparation = -1.0f;
Props.AIMinimumSeparation = 0.5f;
Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 40;
Props.PathSizes = {1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0};
@@ -89,8 +97,6 @@ BigDonut::BigDonut() {
Props.Clouds = NULL; // no clouds
Props.CloudList = NULL;
Props.MinimapFinishlineX = 0;
Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {0, 0, 0};
Props.Skybox.BottomRight = {0, 0, 0};
@@ -101,6 +107,8 @@ BigDonut::BigDonut() {
Props.Skybox.FloorBottomLeft = {0, 0, 0};
Props.Skybox.FloorTopLeft = {0, 0, 0};
Props.Sequence = MusicSeq::MUSIC_SEQ_BATTLE_ARENAS;
Props.WaterLevel = 100.0f;
}
void BigDonut::Load() {
@@ -117,17 +125,13 @@ void BigDonut::Load() {
// d_course_big_donut_packed_dl_230
generate_collision_mesh_with_default_section_id((Gfx*) segmented_gfx_to_virtual((void*)0x07000230), 6);
func_80295C6C();
D_8015F8E4 = 100.0f;
}
void BigDonut::LoadTextures() {
}
void BigDonut::BeginPlay() {
spawn_all_item_boxes((ActorSpawnData*)LOAD_ASSET_RAW(d_course_big_donut_item_box_spawns));
if (gModeSelection == VERSUS) {
Vec3f pos = {0, 0, 0};
FVector pos = {0, 0, 0};
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][20], 20, 0, 1.0f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][40], 40, 0, 1.0f));
@@ -139,31 +143,10 @@ void BigDonut::BeginPlay() {
}
}
// Likely sets minimap boundaries
void BigDonut::MinimapSettings() {
D_8018D2A0 = 0.0257f;
D_8018D2E0 = 32;
D_8018D2E8 = 31;
}
void BigDonut::InitCourseObjects() {}
void BigDonut::SomeSounds() {}
void BigDonut::WhatDoesThisDo(Player* player, int8_t playerId) {}
void BigDonut::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
// Positions the finishline on the minimap
void BigDonut::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
void BigDonut::Render(struct UnkStruct_800DC5EC* arg0) {
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
func_802B5D64(D_800DC610, D_802B87D4, 0, 1);
set_track_light_direction(D_800DC610, D_802B87D4, 0, 1);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
@@ -185,8 +168,6 @@ void BigDonut::Render(struct UnkStruct_800DC5EC* arg0) {
void BigDonut::RenderCredits() {}
void BigDonut::Collision() {}
void BigDonut::Waypoints(Player* player, int8_t playerId) {
player->nearestWaypointId = 0;
}
+1 -13
View File
@@ -17,26 +17,14 @@ extern "C" {
class BigDonut : public Course {
public:
virtual ~BigDonut() = default; // Virtual destructor for proper cleanup in derived classes
virtual ~BigDonut() = default;
// Constructor
explicit BigDonut();
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void LoadTextures() override;
virtual void BeginPlay() override;
//virtual void InitClouds() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void Waypoints(Player* player, int8_t playerId) override;
virtual void Destroy() override;
};
+16 -41
View File
@@ -45,17 +45,24 @@ BlockFort::BlockFort() {
this->gfx = d_course_block_fort_packed_dls;
this->gfxSize = 699;
Props.textures = block_fort_textures;
Props.MinimapTexture = gTextureCourseOutlineBlockFort;
Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
Props.Minimap.Texture = gTextureCourseOutlineBlockFort;
Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
Props.Minimap.Pos[0].X = 257;
Props.Minimap.Pos[0].Y = 170;
Props.Minimap.PlayerX = 32;
Props.Minimap.PlayerY = 32;
Props.Minimap.PlayerScaleFactor = 0.0335f;
Props.Minimap.FinishlineX = 0;
Props.Minimap.FinishlineY = 0;
Props.SetText(Props.Name, "block fort", sizeof(Props.Name));
Props.SetText(Props.DebugName, "block", sizeof(Props.DebugName));
Props.SetText(Props.CourseLength, "", sizeof(Props.CourseLength));
Props.Name = "block fort";
Props.DebugName = "block";
Props.CourseLength = "";
Props.AIBehaviour = D_0D008F18;
Props.AIMaximumSeparation = -1.0f;
Props.AIMinimumSeparation = 0.1f;
Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 2.0f;
@@ -95,8 +102,6 @@ BlockFort::BlockFort() {
Props.Clouds = NULL; // no clouds
Props.CloudList = NULL;
Props.MinimapFinishlineX = 0;
Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {128, 184, 248};
Props.Skybox.BottomRight = {216, 232, 248};
@@ -114,17 +119,14 @@ void BlockFort::Load() {
generate_collision_mesh_with_default_section_id((Gfx*) segmented_gfx_to_virtual((void*)0x070015C0), 1);
func_80295C6C();
D_8015F8E4 = gCourseMinY - 10.0f;
}
void BlockFort::LoadTextures() {
Props.WaterLevel = gCourseMinY - 10.0f;
}
void BlockFort::BeginPlay() {
spawn_all_item_boxes((ActorSpawnData*)LOAD_ASSET_RAW(d_course_block_fort_item_box_spawns));
if (gModeSelection == VERSUS) {
Vec3f pos = {0, 0, 0};
FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][20], 20, 0, 1.0f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][40], 40, 0, 1.0f));
@@ -136,29 +138,8 @@ void BlockFort::BeginPlay() {
}
}
// Likely sets minimap boundaries
void BlockFort::MinimapSettings() {
D_8018D2A0 = 0.0335f;
D_8018D2E0 = 32;
D_8018D2E8 = 32;
}
void BlockFort::InitCourseObjects() {}
void BlockFort::SomeSounds() {}
void BlockFort::WhatDoesThisDo(Player* player, int8_t playerId) {}
void BlockFort::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
// Positions the finishline on the minimap
void BlockFort::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
void BlockFort::Render(struct UnkStruct_800DC5EC* arg0) {
func_802B5D64(D_800DC610, D_802B87D4, 0, 1);
set_track_light_direction(D_800DC610, D_802B87D4, 0, 1);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
@@ -166,12 +147,6 @@ void BlockFort::Render(struct UnkStruct_800DC5EC* arg0) {
gSPDisplayList(gDisplayListHead++, (segmented_gfx_to_virtual((void*)0x070015C0)));
}
void BlockFort::RenderCredits() {}
void BlockFort::Collision() {}
void BlockFort::Waypoints(Player* player, int8_t playerId) {
player->nearestWaypointId = 0;
}
void BlockFort::Destroy() { }
-11
View File
@@ -25,18 +25,7 @@ public:
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void LoadTextures() override;
virtual void BeginPlay() override;
//virtual void InitClouds() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void Waypoints(Player*, int8_t) override;
virtual void Destroy() override;
};
+43 -29
View File
@@ -5,7 +5,7 @@
#include "BowsersCastle.h"
#include "World.h"
#include "engine/actors/AFinishline.h"
#include "engine/actors/Finishline.h"
#include "engine/objects/BombKart.h"
#include "engine/objects/Thwomp.h"
#include "bowsers_castle_data.h"
@@ -31,6 +31,7 @@ extern "C" {
#include "collision.h"
#include "code_8003DC40.h"
#include "memory.h"
#include "course.h"
extern const char *bowsers_castle_dls[];
}
@@ -71,17 +72,26 @@ BowsersCastle::BowsersCastle() {
this->gfx = d_course_bowsers_castle_packed_dls;
this->gfxSize = 4900;
Props.textures = bowsers_castle_textures;
Props.MinimapTexture = gTextureCourseOutlineBowsersCastle;
Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
Props.Minimap.Texture = gTextureCourseOutlineBowsersCastle;
Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
Props.Minimap.Pos[0].X = 265;
Props.Minimap.Pos[0].Y = 170;
Props.Minimap.PlayerX = 12;
Props.Minimap.PlayerY = 48;
Props.Minimap.PlayerScaleFactor = 0.0174f;
Props.Minimap.FinishlineX = 0;
Props.Minimap.FinishlineY = 0;
Id = "mk:bowsers_castle";
Props.SetText(Props.Name, "bowser's castle", sizeof(Props.Name));
Props.SetText(Props.DebugName, "castle", sizeof(Props.DebugName));
Props.SetText(Props.CourseLength, "777m", sizeof(Props.CourseLength));
Props.Id = "mk:bowsers_castle";
Props.Name = "bowser's castle";
Props.DebugName = "castle";
Props.CourseLength = "777m";
Props.AIBehaviour = D_0D008FB8;
Props.AIMaximumSeparation = 35.0f;
Props.AIMinimumSeparation = 0.2f;
Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 2.0f;
@@ -121,8 +131,6 @@ BowsersCastle::BowsersCastle() {
Props.Clouds = NULL; // no clouds
Props.CloudList = NULL;
Props.MinimapFinishlineX = 0;
Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {48, 8, 120};
Props.Skybox.BottomRight = {0, 0, 0};
@@ -133,21 +141,40 @@ BowsersCastle::BowsersCastle() {
Props.Skybox.FloorBottomLeft = {0, 0, 0};
Props.Skybox.FloorTopLeft = {0, 0, 0};
Props.Sequence = MusicSeq::MUSIC_SEQ_BOWSERS_CASTLE;
Props.WaterLevel = -50.0f;
WaterVolumes.push_back({20.0f, 1549.0f, 1859.0f, -1402.0f, -1102.0f});
}
void BowsersCastle::Load() {
Course::Load();
parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_bowsers_castle_addr));
parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_bowsers_castle_addr));
func_80295C6C();
find_vtx_and_set_colours(segmented_gfx_to_virtual(reinterpret_cast<void*>(0x07001350)), 0x32, 0, 0, 0);
D_8015F8E4 = -50.0f;
}
void BowsersCastle::LoadTextures() {
dma_textures(gTextureShrub, 0x000003FFU, 0x00000800U);
}
// Required for the 2 thwomps that go far
void BowsersCastle::SpawnStockThwomp() {
s32 objectId = indexObjectList1[0];
init_object(objectId, 0);
gObjectList[objectId].origin_pos[0] = 0x04b0 * xOrientation;
gObjectList[objectId].origin_pos[2] = 0xf5ba;
gObjectList[objectId].unk_0D5 = 3;
gObjectList[objectId].primAlpha = 0;
objectId = indexObjectList1[1];
init_object(objectId, 0);
gObjectList[objectId].origin_pos[0] = 0x04b0 * xOrientation;
gObjectList[objectId].origin_pos[2] = 0xf592;
gObjectList[objectId].unk_0D5 = 3;
gObjectList[objectId].primAlpha = 1;
}
void BowsersCastle::BeginPlay() {
spawn_foliage((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_bowsers_castle_tree_spawn));
spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_bowsers_castle_item_box_spawns));
@@ -159,6 +186,7 @@ void BowsersCastle::BeginPlay() {
gWorldInstance.AddObject(new OThwomp(0x044c, 0xf92a, 0xC000, 1.0f, 1, 1));
gWorldInstance.AddObject(new OThwomp(0x02bc, 0xf95c, 0xC000, 1.0f, 2, 0));
gWorldInstance.AddObject(new OThwomp(0x04b0, 0xf8f8, 0xC000, 1.0f, 2, 1));
BowsersCastle::SpawnStockThwomp();
gWorldInstance.AddObject(new OThwomp(0x04b0, 0xf5ba, 0xC000, 1.0f, 3, 0));
gWorldInstance.AddObject(new OThwomp(0x04b0, 0xf592, 0xC000, 1.0f, 3, 1));
gWorldInstance.AddObject(new OThwomp(0x091a, 0xf5bf, 0xC000, 1.0f, 4, 0));
@@ -170,6 +198,7 @@ void BowsersCastle::BeginPlay() {
case CC_50:
gWorldInstance.AddObject(new OThwomp(0x3B6, 0xF92A, 0xC000, 1.0f, 1, 0));
gWorldInstance.AddObject(new OThwomp(0x0352, 0xf95c, 0xC000, 1.0f, 2, 0));
BowsersCastle::SpawnStockThwomp();
gWorldInstance.AddObject(new OThwomp(0x04b0, 0xf5ba, 0xC000, 1.0f, 3, 0));
gWorldInstance.AddObject(new OThwomp(0x04b0, 0xf592, 0xC000, 1.0f, 3, 1));
gWorldInstance.AddObject(new OThwomp(0x091a, 0xf5b0, 0xC000, 1.0f, 4, 0));
@@ -182,6 +211,7 @@ void BowsersCastle::BeginPlay() {
gWorldInstance.AddObject(new OThwomp(0x044c, 0xf92a, 0xC000, 1.0f, 1, 1));
gWorldInstance.AddObject(new OThwomp(0x02bc, 0xf95c, 0xC000, 1.0f, 2, 0));
gWorldInstance.AddObject(new OThwomp(0x04b0, 0xf8f8, 0xC000, 1.0f, 2, 1));
BowsersCastle::SpawnStockThwomp();
gWorldInstance.AddObject(new OThwomp(0x04b0, 0xf5ba, 0xC000, 1.0f, 3, 0));
gWorldInstance.AddObject(new OThwomp(0x04b0, 0xf592, 0xC000, 1.0f, 3, 1));
gWorldInstance.AddObject(new OThwomp(0x091a, 0xf5c9, 0xC000, 1.0f, 4, 0));
@@ -194,7 +224,7 @@ void BowsersCastle::BeginPlay() {
}
if (gModeSelection == VERSUS) {
Vec3f pos = {0, 0, 0};
FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][50], 50, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][150], 150, 1, 0.8333333f));
@@ -206,14 +236,6 @@ void BowsersCastle::BeginPlay() {
}
}
// Likely sets minimap boundaries
void BowsersCastle::MinimapSettings() {
D_8018D2C0[0] = 265;
D_8018D2A0 = 0.0174f;
D_8018D2E0 = 12;
D_8018D2E8 = 48;
}
void BowsersCastle::InitCourseObjects() {
size_t objectId;
size_t i;
@@ -283,12 +305,6 @@ void BowsersCastle::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
// Positions the finishline on the minimap
void BowsersCastle::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
void BowsersCastle::Render(struct UnkStruct_800DC5EC* arg0) {
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
@@ -320,8 +336,6 @@ void BowsersCastle::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_bowsers_castle_dl_9148));
}
void BowsersCastle::Collision() {}
void BowsersCastle::SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) {
func_8003E6EC(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}
+1 -3
View File
@@ -26,19 +26,17 @@ public:
// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void LoadTextures() override;
void SpawnStockThwomp();
virtual void BeginPlay() override;
//virtual void InitClouds() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void UpdateCourseObjects() override;
virtual void RenderCourseObjects(s32 cameraId) override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) override;
virtual void Waypoints(Player*, int8_t) override;
virtual void DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection);
+21 -29
View File
@@ -7,7 +7,7 @@
#include "World.h"
#include "engine/objects/BombKart.h"
#include "choco_mountain_data.h"
#include "engine/actors/AFinishline.h"
#include "engine/actors/Finishline.h"
extern "C" {
#include "main.h"
@@ -31,6 +31,7 @@ extern "C" {
#include "code_8003DC40.h"
#include "memory.h"
#include "course_offsets.h"
#include "course.h"
extern const char *choco_mountain_dls[];
}
@@ -63,17 +64,25 @@ ChocoMountain::ChocoMountain() {
this->gfx = d_course_choco_mountain_packed_dls;
this->gfxSize = 2910;
Props.textures = choco_mountain_textures;
Props.MinimapTexture = gTextureCourseOutlineChocoMountain;
Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
Props.Minimap.Texture = gTextureCourseOutlineChocoMountain;
Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
Props.Minimap.Pos[0].X = 265;
Props.Minimap.Pos[0].Y = 170;
Props.Minimap.PlayerX = 19;
Props.Minimap.PlayerY = 37;
Props.Minimap.PlayerScaleFactor = 0.022f;
Props.Minimap.FinishlineX = 0;
Props.Minimap.FinishlineY = -16.0;
Id = "mk:choco_mountain";
Props.SetText(Props.Name, "choco mountain", sizeof(Props.Name));
Props.SetText(Props.DebugName, "mountain", sizeof(Props.DebugName));
Props.SetText(Props.CourseLength, "687m", sizeof(Props.CourseLength));
Props.Id = "mk:choco_mountain";
Props.Name = "choco mountain";
Props.DebugName = "mountain";
Props.CourseLength = "687m";
Props.AIBehaviour = D_0D008F80;
Props.AIMaximumSeparation = 35.0f;
Props.AIMinimumSeparation = 0.3f;
Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 2.0f;
@@ -113,8 +122,6 @@ ChocoMountain::ChocoMountain() {
Props.Clouds = NULL; // no clouds
Props.CloudList = NULL;
Props.MinimapFinishlineX = 0;
Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {255, 255, 255};
Props.Skybox.BottomRight = {255, 255, 255};
@@ -125,6 +132,8 @@ ChocoMountain::ChocoMountain() {
Props.Skybox.FloorBottomLeft = {255, 255, 255};
Props.Skybox.FloorTopLeft = {255, 255, 255};
Props.Sequence = MusicSeq::MUSIC_SEQ_CHOCO_MOUNTAIN;
Props.WaterLevel = -80.0f;
}
void ChocoMountain::Load() {
@@ -154,10 +163,9 @@ void ChocoMountain::Load() {
nullify_displaylist((uintptr_t) segmented_gfx_to_virtual(reinterpret_cast<void*>(0x070003C8)));
}
parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_choco_mountain_addr));
parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_choco_mountain_addr));
func_802B5CAC(0x238E, 0x31C7, D_8015F590);
func_80295C6C();
D_8015F8E4 = -80.0f;
}
void ChocoMountain::LoadTextures() {
@@ -168,7 +176,7 @@ void ChocoMountain::BeginPlay() {
spawn_falling_rocks((struct ActorSpawnData*)LOAD_ASSET_RAW((const char*)d_course_choco_mountain_falling_rock_spawns));
if (gModeSelection == VERSUS) {
Vec3f pos = {0, 0, 0};
FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][140], 140, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][165], 165, 1, 0.8333333f));
@@ -180,14 +188,6 @@ void ChocoMountain::BeginPlay() {
}
}
// Likely sets minimap boundaries
void ChocoMountain::MinimapSettings() {
D_8018D2A0 = 0.022f;
D_8018D2C0[0] = 265;
D_8018D2E0 = 19;
D_8018D2E8 = 37;
}
void ChocoMountain::InitCourseObjects() {
if (gGamestate != CREDITS_SEQUENCE) {
if (gModeSelection == GRAND_PRIX) {
@@ -235,12 +235,6 @@ void ChocoMountain::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
// Positions the finishline on the minimap
void ChocoMountain::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
void ChocoMountain::Render(struct UnkStruct_800DC5EC* arg0) {
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
@@ -292,8 +286,6 @@ void ChocoMountain::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_choco_mountain_dl_71B8));
}
void ChocoMountain::Collision() {}
void ChocoMountain::SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) {
func_8003E37C(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}
-3
View File
@@ -27,15 +27,12 @@ public:
virtual void Load() override;
virtual void LoadTextures() override;
virtual void BeginPlay() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) override;
virtual void Destroy() override;
};
+162 -16
View File
@@ -3,6 +3,9 @@
#include "Course.h"
#include "MarioRaceway.h"
#include "ChocoMountain.h"
#include "port/Game.h"
#include "port/resource/type/TrackWaypoint.h"
#include "port/resource/type/TrackSections.h"
extern "C" {
#include "main.h"
@@ -18,20 +21,36 @@ extern "C" {
#include "staff_ghosts.h"
#include "code_800029B0.h"
#include "render_courses.h"
#include "collision.h"
#include "actors.h"
extern StaffGhost* d_mario_raceway_staff_ghost;
}
Course::Course() {
// Props.Name = "Course Name";
// Props.DebugName = "CName";
// Props.CourseLength = "567m";
Props.SetText(Props.CourseLength, "100m", sizeof(Props.CourseLength));
// Props.Cup = FLOWER_CUP;
// Props.CupIndex = 3;
Id = "";
Props.Minimap.Texture = gTextureCourseOutlineMarioRaceway;
Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
Props.Minimap.Pos[0].X = 257;
Props.Minimap.Pos[0].Y = 170;
Props.Minimap.PlayerX = 0;
Props.Minimap.PlayerY = 0;
Props.Minimap.PlayerScaleFactor = 0.22f;
Props.Minimap.FinishlineX = 0;
Props.Minimap.FinishlineY = 0;
Props.Minimap.Colour = {255, 255, 255};
Props.WaterLevel = -10.0f;
Props.LakituTowType = (s32) OLakitu::LakituTowType::NORMAL;
Props.AIBehaviour = D_0D008F28;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.3f;
Props.SomePtr = D_800DCB34;
Props.AIDistance = gMarioRacewayAIDistances;
Props.AISteeringSensitivity = 48;
Props.NearPersp = 3.0f;
@@ -71,11 +90,10 @@ Course::Course() {
Props.Clouds = NULL;
Props.CloudList = NULL;
Props.MinimapFinishlineX = 0;
Props.MinimapFinishlineY = 0;
Props.Sequence = MusicSeq::MUSIC_SEQ_UNKNOWN;
}
// Load custom track from code
void Course::Load(Vtx* vtx, Gfx* gfx) {
gSegmentTable[4] = reinterpret_cast<uintptr_t>(&vtx[0]);
gSegmentTable[7] = reinterpret_cast<uintptr_t>(&gfx[0]);
@@ -83,8 +101,60 @@ void Course::Load(Vtx* vtx, Gfx* gfx) {
Course::Init();
}
void Course::LoadO2R(std::string trackPath) {
if (!trackPath.empty()) {
TrackSectionsPtr = (trackPath + "/data_track_sections");
std::string path_file = (trackPath + "/data_paths").c_str();
auto res = std::dynamic_pointer_cast<MK64::Paths>(ResourceLoad(path_file.c_str()));
if (res != nullptr) {
auto& paths = res->PathList;
size_t i = 0;
for (auto& path : paths) {
if (i == 0) {
Props.PathTable[0] = (TrackWaypoint*)path.data();
Props.PathTable[1] = NULL;
Props.PathTable[2] = NULL;
Props.PathTable[3] = NULL;
Props.PathTable2[0] = (TrackWaypoint*)path.data();
Props.PathTable2[1] = NULL;
Props.PathTable2[2] = NULL;
Props.PathTable2[3] = NULL;
}
i += 1;
}
}
} else {
printf("Course.cpp: LoadO2R: trackPath str is empty\n");
}
}
// Load stock track
void Course::Load() {
// Load from O2R
if (!TrackSectionsPtr.empty()) {
bIsMod = true;
//auto res = std::dynamic_pointer_cast<MK64::TrackSectionsO2RClass>(ResourceLoad(TrackSectionsPtr.c_str()));
TrackSectionsO2R* sections = (TrackSectionsO2R*) LOAD_ASSET_RAW(TrackSectionsPtr.c_str());
size_t size = ResourceGetSizeByName(TrackSectionsPtr.c_str());
if (sections != nullptr) {
Course::Init();
ParseCourseSections(sections, size);
func_80295C6C();
Props.WaterLevel = gCourseMinY - 10.0f;
}
return;
}
// Stock
size_t vtxSize = (ResourceGetSizeByName(this->vtx) / sizeof(CourseVtx)) * sizeof(Vtx);
size_t texSegSize;
@@ -129,6 +199,53 @@ void Course::Load() {
Course::Init();
}
// C++ version of parse_course_displaylists()
void Course::ParseCourseSections(TrackSectionsO2R* sections, size_t size) {
for (size_t i = 0; i < (size / sizeof(TrackSectionsO2R)); i++) {
if (sections[i].flags & 0x8000) {
D_8015F59C = 1;
} else {
D_8015F59C = 0;
}
if (sections[i].flags & 0x2000) {
D_8015F5A0 = 1;
} else {
D_8015F5A0 = 0;
}
if (sections[i].flags & 0x4000) {
D_8015F5A4 = 1;
} else {
D_8015F5A4 = 0;
}
printf("LOADING DL %s\n", sections[i].addr.c_str());
generate_collision_mesh((Gfx*)LOAD_ASSET_RAW(sections[i].addr.c_str()), sections[i].surfaceType, sections[i].sectionId);
}
}
void Course::TestPath() {
// DEBUG ONLY TO VISUALIZE PATH
return;
s16 x;
s16 y;
s16 z;
Vec3s rot = {0, 0, 0};
Vec3f vel = {0, 0, 0};
for (size_t i = 0; i < gWaypointCountByPathIndex[0]; i++) {
x = D_80164550[0][i].posX;
y = D_80164550[0][i].posY;
z = D_80164550[0][i].posZ;
if (((x & 0xFFFF) == 0x8000) && ((y & 0xFFFF) == 0x8000) && ((z & 0xFFFF) == 0x8000)) {
break;
}
f32 height = spawn_actor_on_surface(x, 2000.0f, z);
Vec3f itemPos = {x, height, z};
add_actor_to_empty_slot(itemPos, rot, vel, ACTOR_ITEM_BOX);
}
}
void Course::Init() {
gNumActors = 0;
gCourseMinX = 0;
@@ -153,6 +270,7 @@ void Course::LoadTextures() {
}
void Course::BeginPlay() {
TestPath();
}
void Course::InitClouds() {
@@ -181,9 +299,6 @@ void Course::SomeCollisionThing(Player* player, Vec3f arg1, Vec3f arg2, Vec3f ar
func_8003E048(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}
void Course::MinimapSettings() {
}
void Course::InitCourseObjects() {
}
@@ -206,13 +321,6 @@ void Course::WhatDoesThisDo(Player* player, int8_t playerId) {
void Course::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
// Positions the finishline on the minimap
void Course::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY,
(u8*) common_texture_minimap_finish_line);
}
void Course::SetStaffGhost() {
D_80162DD6 = 1;
D_80162DF4 = 1;
@@ -226,11 +334,49 @@ void Course::Waypoints(Player* player, int8_t playerId) {
}
void Course::Render(struct UnkStruct_800DC5EC* arg0) {
if (!TrackSectionsPtr.empty()) {
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
// set_track_light_direction(D_800DC610, D_802B87D4, 0, 1);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
if (func_80290C20(arg0->camera) == 1) {
gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE);
gDPSetRenderMode(gDisplayListHead++, G_RM_AA_ZB_OPA_SURF, G_RM_AA_ZB_OPA_SURF2);
// d_course_big_donut_packed_dl_DE8
}
TrackSectionsO2R* sections = (TrackSectionsO2R*)LOAD_ASSET_RAW(TrackSectionsPtr.c_str());
size_t size = ResourceGetSizeByName(TrackSectionsPtr.c_str());
for (size_t i = 0; i < (size / sizeof(TrackSectionsO2R)); i++) {
gSPDisplayList(gDisplayListHead++, (Gfx*)LOAD_ASSET_RAW(sections[i].addr.c_str()));
}
}
}
void Course::RenderCredits() {
}
void Course::Collision() {
f32 Course::GetWaterLevel(FVector pos, Collision* collision) {
float highestWater = -FLT_MAX;
bool found = false;
for (const auto& volume : gWorldInstance.CurrentCourse->WaterVolumes) {
if (pos.x >= volume.MinX && pos.x <= volume.MaxX &&
pos.z >= volume.MinZ && pos.z <= volume.MaxZ) {
// Choose the highest water volume the player is over
if (!found || volume.Height > highestWater) {
highestWater = volume.Height;
found = true;
}
}
}
// If player is not over-top of a water volume then return the courses default water level
return found ? highestWater : gWorldInstance.CurrentCourse->Props.WaterLevel;
}
void Course::ScrollingTextures() {
}
void Course::DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot,
@@ -241,7 +387,7 @@ void Course::Destroy() {
}
bool Course::IsMod() {
return false;
return bIsMod;
}
Course* currentCourse = nullptr;
+195 -15
View File
@@ -6,6 +6,7 @@
#ifdef __cplusplus
#include "engine/objects/Lakitu.h"
#include "port/resource/type/TrackSections.h"
extern "C" {
#endif
@@ -34,20 +35,44 @@ typedef struct SkyboxColours {
RGB8 FloorTopLeft;
} SkyboxColours;
// Extends infinitely in the Y direction
// If a player is overtop of a water volume then it should use its height
// Recommend using the new water surface type. This is here to support the stock tracks.
// Albeit, there's no reason you cannot use this so long as you input a square.
// How to use: WaterVolumes.push_back({0, -100, 100, -100, 100});
struct WaterVolume {
float Height; // Y coordinate of the Water level
float MinX;
float MaxX;
float MinZ;
float MaxZ;
};
typedef struct MinimapProps {
const char* Texture;
int16_t Width;
int16_t Height;
IVector2D Pos[2]; // Minimap position for players 1 and 2. 3/4 player mode is hard-coded to the center.
int32_t PlayerX; // The offset to place the player markers
int32_t PlayerY;
float PlayerScaleFactor; // Scale factor of the player markers
float FinishlineX; // The offset to place the finishline texture on the minimap
float FinishlineY;
RGB8 Colour; // Colour of the visible pixels (the track path)
} MinimapProps;
typedef struct Properties {
const char* Id;
const char* Name;
const char* DebugName;
const char* CourseLength;
char Name[128];
char DebugName[128];
char CourseLength[128];
int32_t LakituTowType;
MinimapProps Minimap;
const char* AIBehaviour;
const char* MinimapTexture;
s32 LakituTowType;
IVector2D MinimapDimensions;
float AIMaximumSeparation;
float AIMinimumSeparation;
float NearPersp;
float FarPersp;
int16_t *SomePtr;
int16_t* AIDistance;
uint32_t AISteeringSensitivity;
_struct_gCoursePathSizes_0x10 PathSizes;
Vec4f D_0D009418;
@@ -56,13 +81,160 @@ typedef struct Properties {
Vec4f D_0D009808;
TrackWaypoint* PathTable[4];
TrackWaypoint* PathTable2[4];
uint8_t* CloudTexture;
CloudData *Clouds;
CloudData *CloudList;
int32_t MinimapFinishlineX;
int32_t MinimapFinishlineY;
SkyboxColours Skybox;
const course_texture *textures;
enum MusicSeq Sequence;
float WaterLevel; // Used for effects, and Lakitu pick up height. Not necessarily the visual water model height.
#ifdef __cplusplus
nlohmann::json to_json() const {
nlohmann::json j;
// j["Id"] = Id ? Id : "";
j["Name"] = Name ? Name : "";
j["DebugName"] = DebugName ? DebugName : "";
j["CourseLength"] = CourseLength ? CourseLength : "";
j["AIBehaviour"] = AIBehaviour ? AIBehaviour : "";
j["LakituTowType"] = LakituTowType;
j["AIMaximumSeparation"] = AIMaximumSeparation;
j["AIMinimumSeparation"] = AIMinimumSeparation;
j["NearPersp"] = NearPersp;
j["FarPersp"] = FarPersp;
// AIDistance as a JSON array
j["AIDistance"] = std::vector<int16_t>(AIDistance, AIDistance + 32); // gAIDistances array size of 32
j["AISteeringSensitivity"] = AISteeringSensitivity;
// PathSizes - Assuming _struct_gCoursePathSizes_0x10 can be serialized similarly
// j["PathSizes"] = PathSizes; // Implement your serialization logic here
j["D_0D009418"] = { D_0D009418[0], D_0D009418[1], D_0D009418[2], D_0D009418[3] };
j["D_0D009568"] = { D_0D009568[0], D_0D009568[1], D_0D009568[2], D_0D009568[3] };
j["D_0D0096B8"] = { D_0D0096B8[0], D_0D0096B8[1], D_0D0096B8[2], D_0D0096B8[3] };
j["D_0D009808"] = { D_0D009808[0], D_0D009808[1], D_0D009808[2], D_0D009808[3] };
// Serialize arrays PathTable and PathTable2 (convert pointers into a JSON array if possible)
//j["PathTable"] = {{}};
//j["PathTable2"] = {{}};
// Populate PathTable and PathTable2
//j["Clouds"] = Clouds ? nlohmann::json{{"x", Clouds->x, "y", Clouds->y, "z", Clouds->z}} : nullptr;
//j["CloudList"] = CloudList ? nlohmann::json{{"x", CloudList->x, "y", CloudList->y, "z", CloudList->z}} : nullptr;
j["MinimapPosition"] = {Minimap.Pos[0].X, Minimap.Pos[0].Y};
j["MinimapPosition2P"] = {Minimap.Pos[1].X, Minimap.Pos[1].Y};
j["MinimapPlayerX"] = Minimap.PlayerX;
j["MinimapPlayerY"] = Minimap.PlayerY;
j["MinimapPlayerScaleFactor"] = Minimap.PlayerScaleFactor;
j["MinimapFinishlineX"] = Minimap.FinishlineX;
j["MinimapFinishlineY"] = Minimap.FinishlineY;
j["MinimapColour"] = {static_cast<int>(Minimap.Colour.r), static_cast<int>(Minimap.Colour.g), static_cast<int>(Minimap.Colour.b)};
// SkyboxColors - assuming SkyboxColors can be serialized similarly
// j["Skybox"] = Skybox; // Implement your serialization logic here
j["Sequence"] = static_cast<int>(Sequence);
j["WaterLevel"] = static_cast<float>(WaterLevel);
return j;
}
// Function to load struct from JSON
void from_json(const nlohmann::json& j) {
//Id = j.at("Id").get<std::string>().c_str();
// Name = j.at("Name").get<std::string>().c_str();
strncpy(Name, j.at("Name").get<std::string>().c_str(), sizeof(Name) - 1);
Name[sizeof(Name) - 1] = '\0'; // Ensure null termination
// DebugName = j.at("DebugName").get<std::string>().c_str();
strncpy(DebugName, j.at("DebugName").get<std::string>().c_str(), sizeof(DebugName) - 1);
DebugName[sizeof(DebugName) - 1] = '\0'; // Ensure null termination
// CourseLength = j.at("CourseLength").get<std::string>().c_str();
strncpy(CourseLength, j.at("CourseLength").get<std::string>().c_str(), sizeof(CourseLength) - 1);
CourseLength[sizeof(CourseLength) - 1] = '\0'; // Ensure null termination
AIBehaviour = j.at("AIBehaviour").get<std::string>().c_str();
LakituTowType = j.at("LakituTowType").get<int>();
AIMaximumSeparation = j.at("AIMaximumSeparation").get<float>();
AIMinimumSeparation = j.at("AIMinimumSeparation").get<float>();
NearPersp = j.at("NearPersp").get<float>();
FarPersp = j.at("FarPersp").get<float>();
const auto temp = j.at("AIDistance").get<std::vector<int16_t>>();
// Ensure the vector has 32 entries
if (temp.size() == 32) {
// Copy the data into the existing AIDistances array
std::copy(temp.begin(), temp.end(), AIDistance);
} else {
printf("Course::from_json() AIDistance array not size of 32\n");
}
AISteeringSensitivity = j.at("AISteeringSensitivity").get<uint32_t>();
// Deserialize PathSizes and other custom structs if needed
D_0D009418[0] = j.at("D_0D009418")[0].get<float>();
D_0D009418[1] = j.at("D_0D009418")[1].get<float>();
D_0D009418[2] = j.at("D_0D009418")[2].get<float>();
D_0D009418[3] = j.at("D_0D009418")[3].get<float>();
D_0D009568[0] = j.at("D_0D009568")[0].get<float>();
D_0D009568[1] = j.at("D_0D009568")[1].get<float>();
D_0D009568[2] = j.at("D_0D009568")[2].get<float>();
D_0D009568[3] = j.at("D_0D009568")[3].get<float>();
D_0D0096B8[0] = j.at("D_0D0096B8")[0].get<float>();
D_0D0096B8[1] = j.at("D_0D0096B8")[1].get<float>();
D_0D0096B8[2] = j.at("D_0D0096B8")[2].get<float>();
D_0D0096B8[3] = j.at("D_0D0096B8")[3].get<float>();
D_0D009808[0] = j.at("D_0D009808")[0].get<float>();
D_0D009808[1] = j.at("D_0D009808")[1].get<float>();
D_0D009808[2] = j.at("D_0D009808")[2].get<float>();
D_0D009808[3] = j.at("D_0D009808")[3].get<float>();
// Deserialize arrays PathTable and PathTable2 similarly
//Clouds = nullptr; // Deserialize if data is present
//CloudList = nullptr; // Deserialize if data is present
Minimap.Pos[0].X = j.at("MinimapPosition")[0].get<int32_t>();
Minimap.Pos[0].Y = j.at("MinimapPosition")[1].get<int32_t>();
Minimap.Pos[1].X = j.at("MinimapPosition2P")[0].get<int32_t>();
Minimap.Pos[1].Y = j.at("MinimapPosition2P")[1].get<int32_t>();
Minimap.PlayerX = j.at("MinimapPlayerX").get<int32_t>();
Minimap.PlayerY = j.at("MinimapPlayerY").get<int32_t>();
Minimap.PlayerScaleFactor = j.at("MinimapPlayerScaleFactor").get<float>();
Minimap.FinishlineX = j.at("MinimapFinishlineX").get<float>();
Minimap.FinishlineY = j.at("MinimapFinishlineY").get<float>();
Minimap.Colour.r = j.at("MinimapColour")[0].get<uint8_t>();
Minimap.Colour.g = j.at("MinimapColour")[1].get<uint8_t>();
Minimap.Colour.b = j.at("MinimapColour")[2].get<uint8_t>();
//textures = nullptr; // Deserialize textures if present
Sequence = static_cast<MusicSeq>(j.at("Sequence").get<int>());
WaterLevel = j.at("WaterLevel").get<float>();
}
void SetText(char* name, const char* title, size_t bufferSize) {
// Copy the title into the name buffer, ensuring it's null-terminated and within bounds
std::strncpy(name, title, bufferSize - 1);
name[bufferSize - 1] = '\0'; // Ensure the string is null-terminated
}
const char* GetName() {
return Name;
}
void New() {
SetText(Name, "", sizeof(Name));
SetText(DebugName, "", sizeof(DebugName));
SetText(CourseLength, "", sizeof(CourseLength));
}
#endif
} Properties;
#ifdef __cplusplus
@@ -72,32 +244,41 @@ class World; // <-- Forward declare
class Course {
public:
std::string Id;
Properties Props;
// This allows multiple water levels in a map.
// Ex. DK Jungle where there's a waterfall and you can drive above and below it.
std::vector<WaterVolume> WaterVolumes;
const char* vtx = nullptr;
const char* gfx = nullptr;
size_t gfxSize = 0;
const course_texture* textures = nullptr;
bool bSpawnFinishline = true;
std::optional<FVector> FinishlineSpawnPoint;
std::string TrackSectionsPtr;
bool bIsMod = false;
virtual ~Course() = default;
explicit Course();
virtual void Load(); // Decompress and load stock courses. Must be overridden for custom courses
virtual void Load(Vtx* vtx, Gfx *gfx); // Load custom course
virtual void LoadO2R(std::string trackPath); // Load custom track from o2r
virtual void Load(); // Decompress and load stock courses or from o2r but TrackSectionsPtr must be set.
virtual void Load(Vtx* vtx, Gfx *gfx); // Load custom track from code. Load must be overridden and then call to this base class method impl.
virtual void LoadTextures();
virtual void ParseCourseSections(TrackSectionsO2R* sections, size_t size);
/**
* @brief BeginPlay This function is called once at the start of gameplay.
* Actor spawning should go here.
*/
virtual void BeginPlay();
virtual void TestPath();
virtual void InitClouds();
virtual void UpdateClouds(s32, Camera*);
virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7);
virtual void MinimapSettings();
virtual void InitCourseObjects();
virtual void UpdateCourseObjects();
virtual void RenderCourseObjects(s32 cameraId);
@@ -105,12 +286,11 @@ public:
virtual void CreditsSpawnActors();
virtual void WhatDoesThisDo(Player*, int8_t);
virtual void WhatDoesThisDoAI(Player*, int8_t);
virtual void MinimapFinishlinePosition();
virtual void SetStaffGhost();
virtual void Render(struct UnkStruct_800DC5EC*);
virtual void RenderCredits();
virtual void Waypoints(Player* player, int8_t playerId);
virtual void Collision();
virtual f32 GetWaterLevel(FVector pos, Collision* collision);
virtual void ScrollingTextures();
virtual void DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection);
virtual void Destroy();
+54 -30
View File
@@ -5,7 +5,7 @@
#include "DKJungle.h"
#include "World.h"
#include "engine/actors/AFinishline.h"
#include "engine/actors/Finishline.h"
#include "engine/objects/BombKart.h"
#include "assets/dks_jungle_parkway_data.h"
@@ -14,6 +14,7 @@
extern "C" {
#include "main.h"
#include "common_structs.h"
#include "camera.h"
#include "course_offsets.h"
#include "code_800029B0.h"
@@ -34,6 +35,7 @@ extern "C" {
#include "code_8003DC40.h"
#include "memory.h"
#include "sounds.h"
#include "course.h"
extern const char *d_course_dks_jungle_parkway_unknown_dl_list[];
extern s16 currentScreenSection;
}
@@ -71,16 +73,24 @@ DKJungle::DKJungle() {
this->gfx = d_course_dks_jungle_parkway_packed_dls;
this->gfxSize = 4997;
Props.textures = dks_jungle_parkway_textures;
Props.MinimapTexture = gTextureCourseOutlineDksJungleParkway;
Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
Props.Minimap.Texture = gTextureCourseOutlineDksJungleParkway;
Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
Props.Minimap.Pos[0].X = 255;
Props.Minimap.Pos[0].Y = 170;
Props.Minimap.PlayerX = 29;
Props.Minimap.PlayerY = 47;
Props.Minimap.PlayerScaleFactor = 0.0155f;
Props.Minimap.FinishlineX = 0;
Props.Minimap.FinishlineY = 0;
Props.SetText(Props.Name, "d.k.'s jungle parkway", sizeof(Props.Name));
Props.SetText(Props.DebugName, "jungle", sizeof(Props.DebugName));
Props.SetText(Props.CourseLength, "893m", sizeof(Props.CourseLength));
Props.Name = "d.k.'s jungle parkway";
Props.DebugName = "jungle";
Props.CourseLength = "893m";
Props.AIBehaviour = D_0D0093C0;
Props.AIMaximumSeparation = 40.0f;
Props.AIMinimumSeparation = 0.1f;
Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 9.0f;
@@ -120,8 +130,6 @@ DKJungle::DKJungle() {
Props.Clouds = NULL; // no clouds
Props.CloudList = NULL;
Props.MinimapFinishlineX = 0;
Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {255, 174, 0};
Props.Skybox.BottomRight = {255, 229, 124};
@@ -132,18 +140,50 @@ DKJungle::DKJungle() {
Props.Skybox.FloorBottomLeft = {0, 0, 0};
Props.Skybox.FloorTopLeft = {22, 145, 22};
Props.Sequence = MusicSeq::MUSIC_SEQ_DK_JUNGLE;
Props.WaterLevel = -475.0f;
}
void DKJungle::Load() {
Course::Load();
parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_dks_jungle_parkway_addr));
parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_dks_jungle_parkway_addr));
func_80295C6C();
D_8015F8E4 = -475.0f;
// d_course_dks_jungle_parkway_packed_dl_3FA8
find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07003FA8), 120, 255, 255, 255);
}
f32 DKJungle::GetWaterLevel(FVector pos, Collision* collision) {
int32_t temp_v1 = get_track_section_id(collision->meshIndexZX) & 0xFF;
if (temp_v1 == 0xFF) {
if ((get_surface_type(collision->meshIndexZX) & 0xFF) == CAVE) {
return -475.0f;
}
if (pos.x > -478.0f) {
return -33.9f;
}
if (pos.x < -838.0f) {
return -475.0f;
}
if (pos.z > -436.0f) {
return -475.0f;
}
if (pos.z < -993.0f) {
return -33.9f;
}
if (pos.z < pos.x) {
return -475.0f;
}
return -33.9f;
}
if (temp_v1 >= 0x14) {
return -475.0f;
}
return -33.9f;
}
void DKJungle::LoadTextures() {
dma_textures(gTextureDksJungleParkwayKiwanoFruit1, 0x0000032FU, 0x00000400U);
dma_textures(gTextureDksJungleParkwayKiwanoFruit2, 0x00000369U, 0x00000400U);
@@ -164,7 +204,7 @@ void DKJungle::BeginPlay() {
gWorldInstance.AddActor(new ABoat((0.6666666f)/4, 0));
if (gModeSelection == VERSUS) {
Vec3f pos = {0, 0, 0};
FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][50], 50, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][100], 100, 1, 0.8333333f));
@@ -177,14 +217,6 @@ void DKJungle::BeginPlay() {
}
}
// Likely sets minimap boundaries
void DKJungle::MinimapSettings() {
D_8018D2A0 = 0.0155f;
D_8018D2C0[0] = 255;
D_8018D2E0 = 29;
D_8018D2E8 = 47;
}
void DKJungle::InitCourseObjects() {
for (size_t i = 0; i < NUM_TORCHES; i++) {
init_smoke_particles(i);
@@ -253,15 +285,9 @@ void DKJungle::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
// Positions the finishline on the minimap
void DKJungle::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
void DKJungle::Render(struct UnkStruct_800DC5EC* arg0) {
func_802B5D64(D_800DC610, D_802B87D4, 0, 1);
func_802B5D64(&D_800DC610[1], D_802B87D4, D_802B87D0, 1);
set_track_light_direction(D_800DC610, D_802B87D4, 0, 1);
set_track_light_direction(&D_800DC610[1], D_802B87D4, D_802B87D0, 1);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_CULL_BACK | G_LIGHTING);
@@ -286,8 +312,6 @@ void DKJungle::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_dks_jungle_parkway_dl_13C30));
}
void DKJungle::Collision() {}
void DKJungle::SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) {
func_8003F138(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}
+1 -3
View File
@@ -26,19 +26,17 @@ public:
// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void LoadTextures() override;
virtual f32 GetWaterLevel(FVector pos, Collision* collision) override;
virtual void BeginPlay() override;
//virtual void InitClouds() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void UpdateCourseObjects() override;
virtual void RenderCourseObjects(s32 cameraId) override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) override;
virtual void Waypoints(Player* player, int8_t playerId) override;
virtual void ScrollingTextures() override;
+18 -26
View File
@@ -43,16 +43,25 @@ DoubleDeck::DoubleDeck() {
this->gfx = d_course_double_deck_packed_dls;
this->gfxSize = 699;
Props.textures = double_deck_textures;
Props.MinimapTexture = gTextureCourseOutlineDoubleDeck;
Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
Props.Minimap.Texture = gTextureCourseOutlineDoubleDeck;
Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
Props.Minimap.Pos[0].X = 257;
Props.Minimap.Pos[0].Y = 170;
Props.Minimap.PlayerX = 32;
Props.Minimap.PlayerY = 32;
Props.Minimap.PlayerScaleFactor = 0.0285f;
Props.Minimap.FinishlineX = 0;
Props.Minimap.FinishlineY = 0;
Props.SetText(Props.Name, "double deck", sizeof(Props.Name));
Props.SetText(Props.DebugName, "deck", sizeof(Props.DebugName));
Props.SetText(Props.CourseLength, "", sizeof(Props.CourseLength));
Props.Name = "double deck";
Props.DebugName = "deck";
Props.CourseLength = "";
Props.AIBehaviour = D_0D008F18;
Props.AIMaximumSeparation = -1.0f;
Props.AIMinimumSeparation = 0.5f;
Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 2.0f;
@@ -92,8 +101,6 @@ DoubleDeck::DoubleDeck() {
Props.Clouds = NULL; // no clouds
Props.CloudList = NULL;
Props.MinimapFinishlineX = 0;
Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {113, 70, 255};
Props.Skybox.BottomRight = {255, 184, 99};
@@ -111,7 +118,7 @@ void DoubleDeck::Load() {
generate_collision_mesh_with_default_section_id((Gfx*) segmented_gfx_to_virtual((void*)0x07000738), 1);
func_80295C6C();
D_8015F8E4 = gCourseMinY - 10.0f;
Props.WaterLevel = gCourseMinY - 10.0f;
}
void DoubleDeck::LoadTextures() {
@@ -121,7 +128,7 @@ void DoubleDeck::BeginPlay() {
spawn_all_item_boxes((ActorSpawnData*)LOAD_ASSET_RAW(d_course_double_deck_item_box_spawns));
if (gModeSelection == VERSUS) {
Vec3f pos = {0, 0, 0};
FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][20], 20, 0, 1.0f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][40], 40, 0, 1.0f));
@@ -133,13 +140,6 @@ void DoubleDeck::BeginPlay() {
}
}
// Likely sets minimap boundaries
void DoubleDeck::MinimapSettings() {
D_8018D2A0 = 0.0285f;
D_8018D2E0 = 32;
D_8018D2E8 = 32;
}
void DoubleDeck::InitCourseObjects() {}
void DoubleDeck::SomeSounds() {}
@@ -148,14 +148,8 @@ void DoubleDeck::WhatDoesThisDo(Player* player, int8_t playerId) {}
void DoubleDeck::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
// Positions the finishline on the minimap
void DoubleDeck::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
void DoubleDeck::Render(struct UnkStruct_800DC5EC* arg0) {
func_802B5D64(D_800DC610, D_802B87D4, 0, 1);
set_track_light_direction(D_800DC610, D_802B87D4, 0, 1);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
@@ -167,8 +161,6 @@ void DoubleDeck::Render(struct UnkStruct_800DC5EC* arg0) {
void DoubleDeck::RenderCredits() {}
void DoubleDeck::Collision() {}
void DoubleDeck::Waypoints(Player* player, int8_t playerId) {
player->nearestWaypointId = 0;
}
-4
View File
@@ -27,16 +27,12 @@ public:
virtual void Load() override;
virtual void LoadTextures() override;
virtual void BeginPlay() override;
//virtual void InitClouds() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void Waypoints(Player* player, int8_t playerId) override;
virtual void Destroy() override;
};
+22 -46
View File
@@ -6,7 +6,7 @@
#include "FrappeSnowland.h"
#include "World.h"
#include "CoreMath.h"
#include "engine/actors/AFinishline.h"
#include "engine/actors/Finishline.h"
#include "engine/objects/BombKart.h"
#include "engine/objects/Snowman.h"
#include "assets/frappe_snowland_data.h"
@@ -34,6 +34,7 @@ extern "C" {
#include "memory.h"
#include "update_objects.h"
#include "course_offsets.h"
#include "course.h"
extern const char *d_course_frappe_snowland_dl_list[];
extern s8 gPlayerCount;
}
@@ -51,16 +52,25 @@ FrappeSnowland::FrappeSnowland() {
this->gfx = d_course_frappe_snowland_packed_dls;
this->gfxSize = 4140;
Props.textures = frappe_snowland_textures;
Props.MinimapTexture = gTextureCourseOutlineFrappeSnowland;
Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
Props.Minimap.Texture = gTextureCourseOutlineFrappeSnowland;
Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
Props.Minimap.Pos[0].X = 262;
Props.Minimap.Pos[0].Y = 170;
Props.Minimap.PlayerX = 36;
Props.Minimap.PlayerY = 40;
Props.Minimap.PlayerScaleFactor = 0.016f;
Props.Minimap.FinishlineX = 0;
Props.Minimap.FinishlineY = 0;
Props.Minimap.Colour = {72, 100, 255};
Props.SetText(Props.Name, "frappe snowland", sizeof(Props.Name));
Props.SetText(Props.DebugName, "snow", sizeof(Props.DebugName));
Props.SetText(Props.CourseLength, "734m", sizeof(Props.CourseLength));
Props.Name = "frappe snowland";
Props.DebugName = "snow";
Props.CourseLength = "734m";
Props.AIBehaviour = D_0D0090F8;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.3f;
Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 9.0f;
@@ -100,8 +110,6 @@ FrappeSnowland::FrappeSnowland() {
Props.Clouds = NULL; // not used for frappe
Props.CloudList = NULL;
Props.MinimapFinishlineX = 0;
Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {28, 11, 90};
Props.Skybox.BottomRight = {0, 99, 164};
@@ -112,14 +120,15 @@ FrappeSnowland::FrappeSnowland() {
Props.Skybox.FloorBottomLeft = {0, 0, 0};
Props.Skybox.FloorTopLeft = {0, 99, 164};
Props.Sequence = MusicSeq::MUSIC_SEQ_FRAPPE_SNOWLAND;
Props.WaterLevel = -50.0f;
}
void FrappeSnowland::Load() {
Course::Load();
parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_frappe_snowland_addr));
parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_frappe_snowland_addr));
func_80295C6C();
D_8015F8E4 = -50.0f;
}
void FrappeSnowland::LoadTextures() {
@@ -130,7 +139,7 @@ void FrappeSnowland::LoadTextures() {
void FrappeSnowland::BeginPlay() {
spawn_foliage((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_frappe_snowland_tree_spawns));
spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_frappe_snowland_item_box_spawns));
if (gGamestate != CREDITS_SEQUENCE) {
gWorldInstance.AddObject(new OSnowman(FVector(697, 0, -1684)));
gWorldInstance.AddObject(new OSnowman(FVector(82, 0, -2245)));
@@ -154,7 +163,7 @@ void FrappeSnowland::BeginPlay() {
}
if (gModeSelection == VERSUS) {
Vec3f pos = {0, 0, 0};
FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][50], 50, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][100], 100, 1, 0.8333333f));
@@ -186,17 +195,6 @@ void FrappeSnowland::UpdateClouds(s32 sp1C, Camera* camera) {
func_80078170(sp1C, camera);
}
// Likely sets minimap boundaries
void FrappeSnowland::MinimapSettings() {
D_8018D2C0[0] = 262;
D_8018D2A0 = 0.016f;
D_8018D2E0 = 36;
D_8018D2E8 = 40;
D_8018D300 = 72;
D_8018D308 = 100;
D_8018D310 = 255;
}
void FrappeSnowland::InitCourseObjects() {
size_t objectId;
size_t i;
@@ -209,22 +207,6 @@ void FrappeSnowland::UpdateCourseObjects() {
update_snowflakes();
}
void FrappeSnowland::RenderCourseObjects(s32 cameraId) {
}
void FrappeSnowland::SomeSounds() {
}
void FrappeSnowland::WhatDoesThisDo(Player* player, int8_t playerId) {}
void FrappeSnowland::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
// Positions the finishline on the minimap
void FrappeSnowland::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
void FrappeSnowland::Render(struct UnkStruct_800DC5EC* arg0) {
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
@@ -246,8 +228,6 @@ void FrappeSnowland::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_frappe_snowland_dl_76A0));
}
void FrappeSnowland::Collision() {}
void FrappeSnowland::Waypoints(Player* player, int8_t playerId) {
s16 waypoint = gNearestWaypointByPlayerId[playerId];
@@ -260,7 +240,3 @@ void FrappeSnowland::Waypoints(Player* player, int8_t playerId) {
}
}
}
void FrappeSnowland::ScrollingTextures() {}
void FrappeSnowland::Destroy() {}
+1 -13
View File
@@ -17,30 +17,18 @@ extern "C" {
class FrappeSnowland : public Course {
public:
virtual ~FrappeSnowland() = default; // Virtual destructor for proper cleanup in derived classes
virtual ~FrappeSnowland() = default;
// Constructor
explicit FrappeSnowland();
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void LoadTextures() override;
virtual void BeginPlay() override;
virtual void InitClouds() override;
virtual void UpdateClouds(s32 sp1C, Camera* camera) override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void UpdateCourseObjects() override;
virtual void RenderCourseObjects(s32 cameraId) override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void ScrollingTextures() override;
virtual void Waypoints(Player* player, int8_t playerId) override;
virtual void Destroy() override;
};
+33 -65
View File
@@ -6,7 +6,7 @@
#include "Harbour.h"
#include "World.h"
#include "engine/actors/AFinishline.h"
#include "engine/actors/Finishline.h"
#include "engine/actors/BowserStatue.h"
#include "engine/actors/Ship.h"
#include "engine/actors/SpaghettiShip.h"
@@ -16,8 +16,8 @@
#include "assets/mario_raceway_data.h"
#include "assets/bowsers_castle_data.h"
#include "assets/bowsers_castle_displaylists.h"
#include "engine/actors/ATree.h"
#include "engine/actors/ACloud.h"
#include "engine/actors/Tree.h"
#include "engine/actors/Cloud.h"
#include "engine/vehicles/Train.h"
#include "engine/objects/Trophy.h"
#include "engine/objects/CheepCheep.h"
@@ -28,6 +28,7 @@
#include "engine/objects/HotAirBalloon.h"
#include "engine/objects/Crab.h"
#include "engine/objects/Boos.h"
#include "engine/objects/GrandPrixBalloons.h"
extern "C" {
#include "main.h"
@@ -50,12 +51,7 @@ extern "C" {
#include "collision.h"
#include "memory.h"
#include "courses/harbour/track.h"
typedef struct {
Gfx* addr;
u8 surfaceType;
u8 sectionId;
u16 flags;
} TrackSections;
#include "course.h"
}
TrackWaypoint harbour_path[] = {
@@ -518,27 +514,28 @@ TrackWaypoint harbour_path[] = {
{13,-121,0,0},
{15,-121,-14,0},
{-32768, -32768, -32768, 0}
};
Harbour::Harbour() {
this->gfxSize = 100;
this->textures = NULL;
Props.MinimapTexture = gTextureCourseOutlineMarioRaceway;
Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
Props.Minimap.Texture = gTextureCourseOutlineMarioRaceway;
Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
Props.Minimap.Pos[0].X = 260;
Props.Minimap.Pos[0].Y = 170;
Props.Minimap.PlayerX = 6;
Props.Minimap.PlayerY = 28;
Props.Minimap.PlayerScaleFactor = 0.022f;
Props.Id = "mk:harbour";
Props.Name = "Harbour";
Props.DebugName = "harbour";
Props.CourseLength = "99m";
Id = "mk:harbour";
Props.SetText(Props.Name, "Harbour", sizeof(Props.Name));
Props.SetText(Props.DebugName, "harbour", sizeof(Props.DebugName));
Props.SetText(Props.CourseLength, "99m", sizeof(Props.CourseLength));
Props.AIBehaviour = D_0D008F28;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.3f;
Props.SomePtr = D_800DCB34;
Props.AISteeringSensitivity = 48;
Props.NearPersp = 9.0f;
@@ -576,10 +573,11 @@ Harbour::Harbour() {
Props.PathTable2[2] = NULL;
Props.PathTable2[3] = NULL;
Props.CloudTexture = (u8*) LOAD_ASSET_RAW(gTextureExhaust5);
Props.Clouds = gKalimariDesertClouds;
Props.CloudList = gLuigiRacewayClouds;
Props.MinimapFinishlineX = 0;
Props.MinimapFinishlineY = 0;
Props.Minimap.FinishlineX = 0;
Props.Minimap.FinishlineY = 0;
Props.Skybox.TopRight = {120, 140, 188};
Props.Skybox.BottomRight = {216, 232, 248};
@@ -601,6 +599,12 @@ TrackSections harbour_surfaces[] = {
void Harbour::Load() {
Course::Load(road_map_001_mesh_vtx_0, NULL);
// The light gets overridden in hm_intro, reset to normal
ground_f3d_material_013_lights = gdSPDefLights1(
0x7F, 0x7F, 0x7F,
0xFF, 0xFF, 0xFF, 0x49, 0x49, 0x49
);
generate_collision_mesh_with_default_section_id(ground_map_mesh, 8);
generate_collision_mesh_with_default_section_id(road_map_001_mesh, 1);
generate_collision_mesh_with_defaults(castle_map_002_mesh);
@@ -608,9 +612,9 @@ void Harbour::Load() {
generate_collision_mesh_with_defaults(bush_map_004_mesh);
generate_collision_mesh_with_defaults(statue_map_005_mesh);
parse_course_displaylists((TrackSectionsI*)harbour_surfaces);
parse_course_displaylists((TrackSections*)harbour_surfaces);
func_80295C6C();
D_8015F8E4 = gCourseMinY - 10.0f;
Props.WaterLevel = gCourseMinY - 10.0f;
}
void Harbour::LoadTextures() {
@@ -726,7 +730,7 @@ void Harbour::BeginPlay() {
// gWorldInstance.AddObject(new OCheepCheep(FVector(0, 40, 0), OCheepCheep::CheepType::RACE, IPathSpan(0, 10)));
// gWorldInstance.AddObject(new OTrophy(FVector(0,0,0), OTrophy::TrophyType::GOLD, OTrophy::Behaviour::GO_FISH));
//gWorldInstance.AddObject(new OSnowman(FVector(0, 0, 0)));
//gWorldInstance.AddObject(new OTrashBin(FVector(0.0f, 0.0f, 0.0f), FRotation(0, 90, 0), 1.0f, OTrashBin::Behaviour::MUNCHING));
//gWorldInstance.AddObject(new OTrashBin(FVector(0.0f, 0.0f, 0.0f), IRotator(0, 90, 0), 1.0f, OTrashBin::Behaviour::MUNCHING));
//gWorldInstance.AddObject(new OHedgehog(FVector(0, 0, 0), FVector2D(0, -200), 9));
//gWorldInstance.AddObject(new OFlagpole(FVector(0, 0, -200), 0x400));
@@ -750,34 +754,11 @@ void Harbour::BeginPlay() {
// add_actor_to_empty_slot(itemPos, rot, vel, ACTOR_ITEM_BOX);
// }
// }
gWorldInstance.AddActor(new AShip(FVector(-1694, -111, 1451), AShip::Skin::GHOSTSHIP));
gWorldInstance.AddActor(new AShip(FVector(2811, -83, 966), AShip::Skin::SHIP2));
gWorldInstance.AddActor(new AShip(FVector(1526, -36, -2228), AShip::Skin::SHIP3));
gWorldInstance.AddActor(new ASpaghettiShip(FVector(582, -70, -650)));
//gWorldInstance.AddActor(new ASpaghettiShip(FVector(2811, -83, 966 )));
gWorldInstance.AddActor(new AStarship(FVector(1019, 160, 1987)));
//gWorldInstance.AddActor(new AShip(FVector(-1694, -111, 1451), AShip::Skin::GHOSTSHIP));
//gWorldInstance.AddActor(new AShip(FVector(2811, -83, 966), AShip::Skin::SHIP2));
//gWorldInstance.AddObject(new OGrandPrixBalloons(FVector(16, -136, -34)));
}
// Likely sets minimap boundaries
void Harbour::MinimapSettings() {
D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust5, 0x443, 0x1000));
D_8018D2A0 = 0.022f;
D_8018D2E0 = 6;
D_8018D2E8 = 28;
D_8018D2C0[0] = 260;
D_8018D2D8[0] = 170;
D_80165718 = 0;
D_80165720 = 5;
D_80165728 = -240;
}
void Harbour::InitCourseObjects() {}
void Harbour::SomeSounds() {}
void Harbour::WhatDoesThisDo(Player* player, int8_t playerId) {
if (((s16) gNearestWaypointByPlayerId[playerId] >= 0x19B) &&
((s16) gNearestWaypointByPlayerId[playerId] < 0x1B9)) {
@@ -808,16 +789,10 @@ void Harbour::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
// Positions the finishline on the minimap
void Harbour::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
void Harbour::Render(struct UnkStruct_800DC5EC* arg0) {
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
func_802B5D64(D_800DC610, D_802B87D4, 0, 1);
set_track_light_direction(D_800DC610, D_802B87D4, 0, 1);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
@@ -836,13 +811,6 @@ void Harbour::Render(struct UnkStruct_800DC5EC* arg0) {
gSPDisplayList(gDisplayListHead++, moon_moon_mesh);
}
void Harbour::RenderCredits() {
}
void Harbour::Collision() {}
void Harbour::Destroy() { }
bool Harbour::IsMod() {
return true;
}
-7
View File
@@ -27,15 +27,8 @@ public:
virtual void Load() override;
virtual void LoadTextures() override;
virtual void BeginPlay() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void Destroy() override;
virtual bool IsMod() override;
};
+21 -31
View File
@@ -5,7 +5,7 @@
#include "KalimariDesert.h"
#include "World.h"
#include "engine/actors/AFinishline.h"
#include "engine/actors/Finishline.h"
#include "engine/objects/BombKart.h"
#include "kalimari_desert_data.h"
#include "engine/vehicles/Utils.h"
@@ -32,6 +32,7 @@ extern "C" {
#include "actors.h"
#include "collision.h"
#include "memory.h"
#include "course.h"
extern const char *kalimari_desert_dls[];
}
@@ -56,16 +57,24 @@ KalimariDesert::KalimariDesert() {
this->gfx = d_course_kalimari_desert_packed_dls;
this->gfxSize = 5328;
Props.textures = kalimari_desert_textures;
Props.MinimapTexture = gTextureCourseOutlineKalimariDesert;
Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
Props.Minimap.Texture = gTextureCourseOutlineKalimariDesert;
Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
Props.Minimap.Pos[0].X = 263;
Props.Minimap.Pos[0].Y = 165;
Props.Minimap.PlayerX = 55;
Props.Minimap.PlayerY = 27;
Props.Minimap.PlayerScaleFactor = 0.015f;
Props.Minimap.FinishlineX = 0;
Props.Minimap.FinishlineY = 4.0;
Props.SetText(Props.Name, "kalimari desert", sizeof(Props.Name));
Props.SetText(Props.DebugName, "desert", sizeof(Props.DebugName));
Props.SetText(Props.CourseLength, "753m", sizeof(Props.CourseLength));
Props.Name = "kalimari desert";
Props.DebugName = "desert";
Props.CourseLength = "753m";
Props.AIBehaviour = D_0D009260;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.3f;
Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 10.0f;
@@ -103,10 +112,9 @@ KalimariDesert::KalimariDesert() {
Props.PathTable2[2] = NULL;
Props.PathTable2[3] = NULL;
Props.CloudTexture = (u8*) LOAD_ASSET_RAW(gTextureExhaust5);
Props.Clouds = gKalimariDesertClouds;
Props.CloudList = gKalimariDesertClouds;
Props.MinimapFinishlineX = 0;
Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {195, 231, 255};
Props.Skybox.BottomRight = {255, 192, 0};
@@ -122,9 +130,9 @@ KalimariDesert::KalimariDesert() {
void KalimariDesert::Load() {
Course::Load();
parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_kalimari_desert_addr));
parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_kalimari_desert_addr));
func_80295C6C();
D_8015F8E4 = gCourseMinY - 10.0f;
Props.WaterLevel = gCourseMinY - 10.0f;
}
void KalimariDesert::LoadTextures() {
@@ -202,7 +210,7 @@ void KalimariDesert::BeginPlay() {
}
if (gModeSelection == VERSUS) {
Vec3f pos = {0, 0, 0};
FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][50], 50, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][138], 138, 1, 0.8333333f));
@@ -215,16 +223,6 @@ void KalimariDesert::BeginPlay() {
}
}
// Likely sets minimap boundaries
void KalimariDesert::MinimapSettings() {
D_8018D2C0[0] = 263;
D_8018D2D8[0] = 165;
D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust5, 0x443, 0x1000));
D_8018D2A0 = 0.015f;
D_8018D2E0 = 55;
D_8018D2E8 = 27;
}
void KalimariDesert::InitCourseObjects() {
size_t i;
if (gGamestate != CREDITS_SEQUENCE) {
@@ -248,14 +246,8 @@ void KalimariDesert::WhatDoesThisDo(Player* player, int8_t playerId) {}
void KalimariDesert::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
// Positions the finishline on the minimap
void KalimariDesert::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
void KalimariDesert::Render(struct UnkStruct_800DC5EC* arg0) {
func_802B5D64(D_800DC610, D_802B87D4, 0, 1);
set_track_light_direction(D_800DC610, D_802B87D4, 0, 1);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
@@ -291,6 +283,4 @@ void KalimariDesert::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_kalimari_desert_dl_22E00));
}
void KalimariDesert::Collision() {}
void KalimariDesert::Destroy() { }
-3
View File
@@ -29,15 +29,12 @@ public:
virtual void Load() override;
virtual void LoadTextures() override;
virtual void BeginPlay() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void Destroy() override;
private:
+30 -34
View File
@@ -6,7 +6,7 @@
#include "KoopaTroopaBeach.h"
#include "World.h"
#include "engine/actors/AFinishline.h"
#include "engine/actors/Finishline.h"
#include "engine/objects/BombKart.h"
#include "engine/objects/Crab.h"
#include "assets/koopa_troopa_beach_data.h"
@@ -32,6 +32,7 @@ extern "C" {
#include "collision.h"
#include "code_8003DC40.h"
#include "memory.h"
#include "course.h"
extern const char *koopa_troopa_beach_dls[];
extern s8 gPlayerCount;
}
@@ -61,17 +62,25 @@ KoopaTroopaBeach::KoopaTroopaBeach() {
this->gfx = d_course_koopa_troopa_beach_packed_dls;
this->gfxSize = 5720;
Props.textures = koopa_troopa_beach_textures;
Props.MinimapTexture = gTextureCourseOutlineKoopaTroopaBeach;
Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
Props.Minimap.Texture = gTextureCourseOutlineKoopaTroopaBeach;
Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
Props.Minimap.Pos[0].X = 268;
Props.Minimap.Pos[0].Y = 170;
Props.Minimap.PlayerX = 40;
Props.Minimap.PlayerY = 21;
Props.Minimap.PlayerScaleFactor = 0.014f;
Props.Minimap.FinishlineX = 0;
Props.Minimap.FinishlineY = 0;
Id = "mk:koopa_beach";
Props.SetText(Props.Name, "koopa troopa beach", sizeof(Props.Name));
Props.SetText(Props.DebugName, "beach", sizeof(Props.DebugName));
Props.SetText(Props.CourseLength, "691m", sizeof(Props.CourseLength));
Props.Id = "mk:koopa_beach";
Props.Name = "koopa troopa beach";
Props.DebugName = "beach";
Props.CourseLength = "691m";
Props.AIBehaviour = D_0D009158;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.5f;
Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 1.0f;
@@ -109,10 +118,9 @@ KoopaTroopaBeach::KoopaTroopaBeach() {
Props.PathTable2[2] = NULL;
Props.PathTable2[3] = NULL;
Props.CloudTexture = (u8*) LOAD_ASSET_RAW(gTextureExhaust3);
Props.Clouds = gKoopaTroopaBeachClouds;
Props.CloudList = gKoopaTroopaBeachClouds;
Props.MinimapFinishlineX = 0;
Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {48, 152, 120};
Props.Skybox.BottomRight = {216, 232, 248};
@@ -123,12 +131,16 @@ KoopaTroopaBeach::KoopaTroopaBeach() {
Props.Skybox.FloorBottomLeft = {0, 0, 0};
Props.Skybox.FloorTopLeft = {48, 152, 120};
Props.Sequence = MusicSeq::MUSIC_SEQ_KOOPA_TROOPA_BEACH;
Props.WaterLevel = 0.0f;
gWaterVelocity = -0.1f;
WaterVolumes.push_back({0.8f, 67.0f, 239.0f, 2233.0f, 2405.0f});
}
void KoopaTroopaBeach::Load() {
Course::Load();
parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_koopa_troopa_beach_addr));
parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_koopa_troopa_beach_addr));
func_80295C6C();
find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x0700ADE0), -0x6A, 255, 255, 255);
find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x0700A540), -0x6A, 255, 255, 255);
@@ -172,7 +184,7 @@ void KoopaTroopaBeach::BeginPlay() {
}
if (gModeSelection == VERSUS) {
Vec3f pos = {0, 0, 0};
FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][60], 60, 1, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][120], 120, 1, 0.8333333f));
@@ -184,15 +196,6 @@ void KoopaTroopaBeach::BeginPlay() {
}
}
// Likely sets minimap boundaries
void KoopaTroopaBeach::MinimapSettings() {
D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust3, 0x3C8U, 0x1000));
D_8018D2A0 = 0.014f;
D_8018D2C0[0] = 268;
D_8018D2E0 = 40;
D_8018D2E8 = 21;
}
void KoopaTroopaBeach::InitCourseObjects() {
}
@@ -228,12 +231,6 @@ void KoopaTroopaBeach::WhatDoesThisDo(Player* player, int8_t playerId) {}
void KoopaTroopaBeach::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
// Positions the finishline on the minimap
void KoopaTroopaBeach::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
void KoopaTroopaBeach::Render(struct UnkStruct_800DC5EC* arg0) {
gDPPipeSync(gDisplayListHead++);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
@@ -264,21 +261,20 @@ void KoopaTroopaBeach::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_koopa_troopa_beach_dl_18D68));
}
void KoopaTroopaBeach::Collision() {}
void KoopaTroopaBeach::SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) {
func_8003E37C(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}
void KoopaTroopaBeach::ScrollingTextures() {
// clang-format off
if (D_8015F8E8 < 0.0f) {
if (D_8015F8E4 < -20.0f) { D_8015F8E8 *= -1.0f; }
// This flips the velocity from 0.1f to -0.1f
if (gWaterVelocity < 0.0f) {
if (Props.WaterLevel < -20.0f) { gWaterVelocity *= -1.0f; }
} else {
if (D_8015F8E4 > 0.0f) { D_8015F8E8 *= -1.0f; }
if (Props.WaterLevel > 0.0f) { gWaterVelocity *= -1.0f; }
}
// clang-format on
D_8015F8E4 += D_8015F8E8;
Props.WaterLevel += gWaterVelocity;
D_802B87BC += 9;
if (D_802B87BC > 255) {
@@ -330,7 +326,7 @@ void KoopaTroopaBeach::DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pat
break;
}
vector[0] = 0.0f;
vector[1] = D_8015F8E4;
vector[1] = Props.WaterLevel;
vector[2] = 0.0f;
mtxf_translate(matrix, vector);
render_set_position(matrix, 0);
-3
View File
@@ -30,17 +30,14 @@ public:
virtual void Load() override;
virtual void LoadTextures() override;
virtual void BeginPlay() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void UpdateCourseObjects() override;
virtual void RenderCourseObjects(s32 cameraId) override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) override;
virtual void ScrollingTextures() override;
virtual void DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) override;
+23 -49
View File
@@ -8,7 +8,8 @@
#include "engine/objects/BombKart.h"
#include "assets/luigi_raceway_data.h"
#include "engine/objects/HotAirBalloon.h"
#include "engine/actors/AFinishline.h"
#include "engine/actors/Finishline.h"
#include "engine/objects/GrandPrixBalloons.h"
extern "C" {
#include "main.h"
@@ -34,6 +35,7 @@ extern "C" {
#include "courses/staff_ghost_data.h"
#include "framebuffer_effects.h"
#include "skybox_and_splitscreen.h"
#include "course.h"
extern const char* luigi_raceway_dls[];
extern s16 currentScreenSection;
}
@@ -87,17 +89,25 @@ LuigiRaceway::LuigiRaceway() {
this->gfx = d_course_luigi_raceway_packed_dls;
this->gfxSize = 6377;
Props.textures = luigi_raceway_textures;
Props.MinimapTexture = gTextureCourseOutlineLuigiRaceway;
Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
Props.Minimap.Texture = gTextureCourseOutlineLuigiRaceway;
Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
Props.Minimap.Pos[0].X = 271;
Props.Minimap.Pos[0].Y = 170;
Props.Minimap.PlayerX = 45;
Props.Minimap.PlayerY = 60;
Props.Minimap.PlayerScaleFactor = 0.0155f;
Props.Minimap.FinishlineX = 0;
Props.Minimap.FinishlineY = 0;
Id = "mk:luigi_raceway";
Props.SetText(Props.Name, "luigi raceway", sizeof(Props.Name));
Props.SetText(Props.DebugName, "l circuit", sizeof(Props.DebugName));
Props.SetText(Props.CourseLength, "717m", sizeof(Props.CourseLength));
Props.Id = "mk:luigi_raceway";
Props.Name = "luigi raceway";
Props.DebugName = "l circuit";
Props.CourseLength = "717m";
Props.AIBehaviour = D_0D0091E8;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.7f;
Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 48;
Props.NearPersp = 9.0f;
@@ -135,10 +145,9 @@ LuigiRaceway::LuigiRaceway() {
Props.PathTable2[2] = NULL;
Props.PathTable2[3] = NULL;
Props.CloudTexture = (u8*)LOAD_ASSET_RAW(gTextureExhaust2);
Props.Clouds = gLuigiRacewayClouds;
Props.CloudList = gLuigiRacewayClouds;
Props.MinimapFinishlineX = 0;
Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = { 128, 184, 248 };
Props.Skybox.BottomRight = { 216, 232, 248 };
@@ -154,9 +163,9 @@ LuigiRaceway::LuigiRaceway() {
void LuigiRaceway::Load() {
Course::Load();
parse_course_displaylists((TrackSectionsI*) LOAD_ASSET_RAW(d_course_luigi_raceway_addr));
parse_course_displaylists((TrackSections*) LOAD_ASSET_RAW(d_course_luigi_raceway_addr));
func_80295C6C();
D_8015F8E4 = gCourseMinY - 10.0f;
Props.WaterLevel = gCourseMinY - 10.0f;
}
void LuigiRaceway::LoadTextures() {
@@ -172,10 +181,11 @@ void LuigiRaceway::BeginPlay() {
gWorldInstance.AddObject(new OHotAirBalloon(FVector(-1250.0f, 0.0f, 1110.0f)));
} else { // Normal gameplay
gWorldInstance.AddObject(new OHotAirBalloon(FVector(-176.0, 0.0f, -2323.0f)));
gWorldInstance.AddObject(new OGrandPrixBalloons(FVector(-140, -44, -215)));
}
if (gModeSelection == VERSUS) {
Vec3f pos = { 0, 0, 0 };
FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][50], 50, 1, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][200], 200, 3, 0.8333333f));
@@ -187,38 +197,15 @@ void LuigiRaceway::BeginPlay() {
}
}
// Likely sets minimap boundaries
void LuigiRaceway::MinimapSettings() {
D_8018D220 = reinterpret_cast<uint8_t(*)[1024]>(dma_textures(gTextureExhaust2, 0x4F4U, 0xC00));
D_8018D2A0 = 0.0155f;
D_8018D2C0[0] = 271;
D_8018D2E0 = 45;
D_8018D2E8 = 60;
D_80165718 = -140;
D_80165720 = -44;
D_80165728 = -215;
}
void LuigiRaceway::InitCourseObjects() {
size_t i;
if (gGamestate != CREDITS_SEQUENCE) {
if (gModeSelection == GRAND_PRIX) {
func_80070714();
}
for (i = 0; i < D_80165738; i++) {
find_unused_obj_index(&gObjectParticle3[i]);
init_object(gObjectParticle3[i], 0);
}
}
}
void LuigiRaceway::UpdateCourseObjects() {
}
void LuigiRaceway::RenderCourseObjects(s32 cameraId) {
}
void LuigiRaceway::SomeSounds() {
vec3f_set(D_8015F748, 85.0f, 21.0f, -219.0f);
func_800C9D80(D_8015F748, D_802B91C8, 0x5103700B);
@@ -252,13 +239,6 @@ void LuigiRaceway::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
// Positions the finishline on the minimap
void LuigiRaceway::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY,
(u8*) common_texture_minimap_finish_line);
}
void LuigiRaceway::SetStaffGhost() {
u32 temp_v0 = func_800B4E24(0) & 0xfffff;
if (temp_v0 <= 11200) {
@@ -444,13 +424,7 @@ void LuigiRaceway::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*) (d_course_luigi_raceway_dl_FD40));
}
void LuigiRaceway::Collision() {
}
void LuigiRaceway::SomeCollisionThing(Player* player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5,
f32* arg6, f32* arg7) {
func_8003E9EC(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}
void LuigiRaceway::Destroy() {
}
-6
View File
@@ -29,19 +29,13 @@ class LuigiRaceway : public Course {
virtual void Load() override;
virtual void LoadTextures() override;
virtual void BeginPlay() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void UpdateCourseObjects() override;
virtual void RenderCourseObjects(s32 cameraId) override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
virtual void SetStaffGhost() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void SomeCollisionThing(Player* player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6,
f32* arg7) override;
virtual void Destroy() override;
};
+27 -38
View File
@@ -5,9 +5,10 @@
#include "MarioRaceway.h"
#include "World.h"
#include "engine/actors/AFinishline.h"
#include "engine/actors/Finishline.h"
#include "engine/objects/Object.h"
#include "engine/objects/BombKart.h"
#include "engine/objects/GrandPrixBalloons.h"
extern "C" {
#include "main.h"
@@ -31,6 +32,7 @@ extern "C" {
#include "collision.h"
#include "memory.h"
#include "courses/staff_ghost_data.h"
#include "course.h"
extern const char *mario_raceway_dls[];
}
@@ -72,19 +74,28 @@ MarioRaceway::MarioRaceway() {
this->vtx = d_course_mario_raceway_vertex;
this->gfx = d_course_mario_raceway_packed_dls;
this->gfxSize = 3367;
Props.textures = mario_raceway_textures;
Props.MinimapTexture = gTextureCourseOutlineMarioRaceway;
Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
Props.Id = "mk:mario_raceway";
Props.Name = "Mario Raceway";
Props.DebugName = "m circuit";
Props.CourseLength = "567m";
Props.textures = mario_raceway_textures;
Props.Minimap.Texture = gTextureCourseOutlineMarioRaceway;
Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
Props.Minimap.Pos[0].X = 260;
Props.Minimap.Pos[0].Y = 170;
Props.Minimap.PlayerX = 6;
Props.Minimap.PlayerY = 28;
Props.Minimap.PlayerScaleFactor = 0.022f;
Props.Minimap.FinishlineX = 0;
Props.Minimap.FinishlineY = -2.0;
Id = "mk:mario_raceway";
Props.SetText(Props.Name, "mario raceway", sizeof(Props.Name));
Props.SetText(Props.DebugName, "m circuit", sizeof(Props.DebugName));
Props.SetText(Props.CourseLength, "567m", sizeof(Props.CourseLength));
Props.AIBehaviour = D_0D008F28;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.3f;
Props.SomePtr = D_800DCB34;
Props.AIDistance = gMarioRacewayAIDistances;
Props.AISteeringSensitivity = 48;
Props.NearPersp = 9.0f;
@@ -122,10 +133,9 @@ MarioRaceway::MarioRaceway() {
Props.PathTable2[2] = NULL;
Props.PathTable2[3] = NULL;
Props.CloudTexture = (uint8_t*) LOAD_ASSET_RAW(gTextureExhaust5);
Props.Clouds = gKalimariDesertClouds;
Props.CloudList = gLuigiRacewayClouds;
Props.MinimapFinishlineX = 0;
Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {0, 184, 248};
Props.Skybox.BottomRight = {216, 232, 248};
@@ -156,9 +166,9 @@ void MarioRaceway::Load() {
}
}
parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_mario_raceway_addr));
parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_mario_raceway_addr));
func_80295C6C();
D_8015F8E4 = gCourseMinY - 10.0f;
Props.WaterLevel = gCourseMinY - 10.0f;
}
void MarioRaceway::LoadTextures() {
@@ -191,7 +201,7 @@ void MarioRaceway::BeginPlay() {
add_actor_to_empty_slot(position, rotation, velocity, ACTOR_MARIO_SIGN);
if (gModeSelection == VERSUS) {
Vec3f pos = {0, 0, 0};
FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][40], 40, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][100], 100, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][265], 265, 3, 0.8333333f));
@@ -200,19 +210,10 @@ void MarioRaceway::BeginPlay() {
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][0], 0, 0, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][0], 0, 0, 0.8333333f));
}
}
// Likely sets minimap boundaries
void MarioRaceway::MinimapSettings() {
D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust5, 0x443, 0x1000));
D_8018D2A0 = 0.022f;
D_8018D2E0 = 6;
D_8018D2E8 = 28;
D_8018D2C0[0] = 260;
D_8018D2D8[0] = 170;
D_80165718 = 0;
D_80165720 = 5;
D_80165728 = -240;
if (gGamestate != CREDITS_SEQUENCE) {
gWorldInstance.AddObject(new OGrandPrixBalloons(FVector(0, 5, -240)));
}
}
void MarioRaceway::InitCourseObjects() {
@@ -220,10 +221,6 @@ void MarioRaceway::InitCourseObjects() {
if (gModeSelection == GRAND_PRIX) {
func_80070714();
}
for (size_t i = 0; i < D_80165738; i++) {
find_unused_obj_index(&gObjectParticle3[i]);
init_object(gObjectParticle3[i], 0);
}
}
}
@@ -262,12 +259,6 @@ void MarioRaceway::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
// Positions the finishline on the minimap
void MarioRaceway::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
void MarioRaceway::SetStaffGhost() {
u32 temp_v0 = func_800B4E24(0) & 0xfffff;
if (temp_v0 <= 9000) {
@@ -390,8 +381,6 @@ void MarioRaceway::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_mario_raceway_dl_9348));
}
void MarioRaceway::Collision() {}
void MarioRaceway::CreditsSpawnActors() {
dma_textures(gTextureTrees1, 0x35B, 0x800);
spawn_foliage((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_mario_raceway_tree_spawns));
-3
View File
@@ -27,16 +27,13 @@ public:
virtual void Load() override;
virtual void LoadTextures() override;
virtual void BeginPlay() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
virtual void SetStaffGhost() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void CreditsSpawnActors() override;
virtual void Destroy() override;
};
+21 -30
View File
@@ -5,7 +5,7 @@
#include "MooMooFarm.h"
#include "World.h"
#include "engine/actors/AFinishline.h"
#include "engine/actors/Finishline.h"
#include "engine/objects/BombKart.h"
#include "assets/moo_moo_farm_data.h"
#include "engine/objects/MoleGroup.h"
@@ -32,6 +32,7 @@ extern "C" {
#include "collision.h"
#include "memory.h"
#include "code_80086E70.h"
#include "course.h"
extern const char *moo_moo_farm_dls[];
extern s16 currentScreenSection;
extern s8 gPlayerCount;
@@ -74,16 +75,24 @@ MooMooFarm::MooMooFarm() {
this->gfx = d_course_moo_moo_farm_packed_dls;
this->gfxSize = 3304;
Props.textures = moo_moo_farm_textures;
Props.MinimapTexture = gTextureCourseOutlineMooMooFarm;
Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
Props.Minimap.Texture = gTextureCourseOutlineMooMooFarm;
Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
Props.Minimap.Pos[0].X = 271;
Props.Minimap.Pos[0].Y = 170;
Props.Minimap.PlayerX = 18;
Props.Minimap.PlayerY = 36;
Props.Minimap.PlayerScaleFactor = 0.0155f;
Props.Minimap.FinishlineX = 0;
Props.Minimap.FinishlineY = 0;
Props.SetText(Props.Name, "moo moo farm", sizeof(Props.Name));
Props.SetText(Props.DebugName, "farm", sizeof(Props.DebugName));
Props.SetText(Props.CourseLength, "527m", sizeof(Props.CourseLength));
Props.Name = "moo moo farm";
Props.DebugName = "farm";
Props.CourseLength = "527m";
Props.AIBehaviour = D_0D009210;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.5f;
Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 48;
Props.NearPersp = 9.0f;
@@ -121,10 +130,9 @@ MooMooFarm::MooMooFarm() {
Props.PathTable2[2] = NULL;
Props.PathTable2[3] = NULL;
Props.CloudTexture = (u8*) LOAD_ASSET_RAW(gTextureExhaust0);
Props.Clouds = gYoshiValleyMooMooFarmClouds;
Props.CloudList = gYoshiValleyMooMooFarmClouds;
Props.MinimapFinishlineX = 0;
Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {0, 18, 255};
Props.Skybox.BottomRight = {197, 211, 255};
@@ -140,9 +148,9 @@ MooMooFarm::MooMooFarm() {
void MooMooFarm::Load() {
Course::Load();
parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_moo_moo_farm_addr));
parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_moo_moo_farm_addr));
func_80295C6C();
D_8015F8E4 = gCourseMinY - 10.0f;
Props.WaterLevel = gCourseMinY - 10.0f;
}
void MooMooFarm::LoadTextures() {
@@ -311,7 +319,7 @@ void MooMooFarm::BeginPlay() {
}
if (gModeSelection == VERSUS) {
Vec3f pos = {0, 0, 0};
FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][50], 50, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][140], 140, 3, 0.8333333f));
@@ -323,15 +331,6 @@ void MooMooFarm::BeginPlay() {
}
}
// Likely sets minimap boundaries
void MooMooFarm::MinimapSettings() {
D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust0, 0x479, 0xC00));
D_8018D2A0 = 0.0155f;
D_8018D2C0[0] = 271;
D_8018D2E0 = 18;
D_8018D2E8 = 36;
}
void MooMooFarm::WhatDoesThisDo(Player* player, int8_t playerId) {
if (((s16) gNearestWaypointByPlayerId[playerId] >= 0x145) &&
((s16) gNearestWaypointByPlayerId[playerId] < 0x18B)) {
@@ -362,17 +361,11 @@ void MooMooFarm::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
// Positions the finishline on the minimap
void MooMooFarm::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
void MooMooFarm::Render(struct UnkStruct_800DC5EC* arg0) {
s16 temp_s0 = arg0->pathCounter;
s16 temp_s1 = arg0->playerDirection;
func_802B5D64(D_800DC610, D_802B87D4, 0, 1);
set_track_light_direction(D_800DC610, D_802B87D4, 0, 1);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
@@ -445,8 +438,6 @@ void MooMooFarm::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_moo_moo_farm_dl_14088));
}
void MooMooFarm::Collision() {}
void MooMooFarm::CreditsSpawnActors() {
dma_textures(gTextureTrees4Left, 0x3E8, 0x800);
dma_textures(gTextureTrees4Right, 0x3E8, 0x800);
-3
View File
@@ -30,13 +30,10 @@ public:
virtual void Load() override;
virtual void LoadTextures() override;
virtual void BeginPlay() override;
virtual void MinimapSettings() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void CreditsSpawnActors() override;
virtual void Destroy() override;
};
+23 -33
View File
@@ -12,6 +12,7 @@
#include "engine/objects/Podium.h"
#include "engine/objects/CheepCheep.h"
#include "engine/particles/StarEmitter.h"
#include "engine/objects/GrandPrixBalloons.h"
extern "C" {
#include "main.h"
@@ -35,6 +36,7 @@ extern "C" {
#include "memory.h"
#include "courses/staff_ghost_data.h"
#include "podium_ceremony_actors.h"
#include "course.h"
extern const char *royal_raceway_dls[];
}
@@ -90,15 +92,23 @@ PodiumCeremony::PodiumCeremony() {
this->gfx = d_course_royal_raceway_packed_dls;
this->gfxSize = 5670;
Props.textures = podium_ceremony_textures;
Props.MinimapDimensions = IVector2D(0, 0);
Props.Minimap.Width = 0;
Props.Minimap.Height = 0;
Props.Minimap.Pos[0].X = 262;
Props.Minimap.Pos[0].Y = 170;
Props.Minimap.PlayerX = 37;
Props.Minimap.PlayerY = 50;
Props.Minimap.PlayerScaleFactor = 0.014f;
Props.Minimap.FinishlineX = 0;
Props.Minimap.FinishlineY = 0;
Props.SetText(Props.Name, "royal raceway", sizeof(Props.Name));
Props.SetText(Props.DebugName, "p circuit", sizeof(Props.DebugName));
Props.SetText(Props.CourseLength, "1025m", sizeof(Props.CourseLength));
Props.Name = "royal raceway";
Props.DebugName = "p circuit";
Props.CourseLength = "1025m";
Props.AIBehaviour = D_0D009188;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.4f;
Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.PathSizes = {500, 500, 500, 500, 1, 0, 0, 0, 0, 0, 0};
@@ -133,10 +143,9 @@ PodiumCeremony::PodiumCeremony() {
Props.PathTable2[2] = NULL;
Props.PathTable2[3] = NULL;
Props.CloudTexture = (u8*) LOAD_ASSET_RAW(gTextureExhaust4);
Props.Clouds = NULL; // no clouds
Props.CloudList = NULL;
Props.MinimapFinishlineX = 0;
Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {238, 144, 255};
Props.Skybox.BottomRight = {255, 224, 240};
@@ -147,14 +156,15 @@ PodiumCeremony::PodiumCeremony() {
Props.Skybox.FloorBottomLeft = {0, 0, 0};
Props.Skybox.FloorTopLeft = {255, 224, 240};
Props.Sequence = MusicSeq::MUSIC_SEQ_UNKNOWN;
Props.WaterLevel = -60.0f;
}
void PodiumCeremony::Load() {
Course::Load();
parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_royal_raceway_addr));
parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_royal_raceway_addr));
func_80295C6C();
D_8015F8E4 = -60.0f;
}
void PodiumCeremony::LoadTextures() {
@@ -189,7 +199,7 @@ void PodiumCeremony::BeginPlay() {
OTrophy* trophy = reinterpret_cast<OTrophy*>(gWorldInstance.AddObject(new OTrophy(pos, type, OTrophy::Behaviour::PODIUM_CEREMONY)));
Vec3f kart = {0, 0, 0};
FVector kart = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(kart, &D_80164550[3][3], 3, 5, 1.25f));
gWorldInstance.AddObject(new OBombKart(kart, &D_80164550[3][40], 40, 0, 1.0f));
gWorldInstance.AddObject(new OBombKart(kart, &D_80164550[3][60], 60, 0, 1.0f));
@@ -197,18 +207,10 @@ void PodiumCeremony::BeginPlay() {
gWorldInstance.AddObject(new OBombKart(kart, &D_80164550[3][100], 100, 0, 1.0f));
gWorldInstance.AddObject(new OBombKart(kart, &D_80164550[3][120], 120, 0, 1.0f));
gWorldInstance.AddObject(new OBombKart(kart, &D_80164550[3][140], 140, 0, 1.0f));
}
// Likely sets minimap boundaries
void PodiumCeremony::MinimapSettings() {
D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust4, 0x3F8, 0x1000));
D_8018D2C0[0] = 262;
D_8018D2A0 = 0.014f;
D_8018D2E0 = 37;
D_8018D2E8 = 50;
D_80165718 = -64;
D_80165720 = 5;
D_80165728 = -330;
if (gGamestate != CREDITS_SEQUENCE) {
gWorldInstance.AddObject(new OGrandPrixBalloons(FVector(-64, 5, -330)));
}
}
void PodiumCeremony::InitCourseObjects() {
@@ -217,10 +219,6 @@ void PodiumCeremony::InitCourseObjects() {
if (gModeSelection == GRAND_PRIX) {
func_80070714();
}
for (i = 0; i < D_80165738; i++) {
find_unused_obj_index(&gObjectParticle3[i]);
init_object(gObjectParticle3[i], 0);
}
}
}
@@ -257,12 +255,6 @@ void PodiumCeremony::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
// Positions the finishline on the minimap
void PodiumCeremony::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
void PodiumCeremony::Render(struct UnkStruct_800DC5EC* arg0) {
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
@@ -296,6 +288,4 @@ void PodiumCeremony::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_royal_raceway_dl_D8E8));
}
void PodiumCeremony::Collision() {}
void PodiumCeremony::Destroy() { }
-3
View File
@@ -29,14 +29,11 @@ public:
virtual void LoadTextures() override;
virtual void BeginPlay() override;
//virtual void InitClouds() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void Destroy() override;
};
+20 -29
View File
@@ -5,7 +5,7 @@
#include "RainbowRoad.h"
#include "World.h"
#include "engine/actors/AFinishline.h"
#include "engine/actors/Finishline.h"
#include "engine/objects/ChainChomp.h"
#include "engine/objects/BombKart.h"
#include "assets/rainbow_road_data.h"
@@ -30,6 +30,7 @@ extern "C" {
#include "actors.h"
#include "collision.h"
#include "memory.h"
#include "course.h"
extern const char *rainbow_road_dls[];
}
@@ -48,16 +49,24 @@ RainbowRoad::RainbowRoad() {
this->gfx = d_course_rainbow_road_packed_dls;
this->gfxSize = 5670;
Props.textures = rainbow_road_textures;
Props.MinimapTexture = gTextureCourseOutlineRainbowRoad;
Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
Props.Minimap.Texture = gTextureCourseOutlineRainbowRoad;
Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
Props.Minimap.Pos[0].X = 261;
Props.Minimap.Pos[0].Y = 166;
Props.Minimap.PlayerX = 39;
Props.Minimap.PlayerY = 55;
Props.Minimap.PlayerScaleFactor = 0.0103f;
Props.Minimap.FinishlineX = 0;
Props.Minimap.FinishlineY = 0;
Props.SetText(Props.Name, "rainbow road", sizeof(Props.Name));
Props.SetText(Props.DebugName, "rainbow", sizeof(Props.DebugName));
Props.SetText(Props.CourseLength, "2000m", sizeof(Props.CourseLength));
Props.Name = "rainbow road";
Props.DebugName = "rainbow";
Props.CourseLength = "2000m";
Props.AIBehaviour = D_0D0092C8;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.4f;
Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 38;
Props.NearPersp = 2.0f;
@@ -97,8 +106,6 @@ RainbowRoad::RainbowRoad() {
Props.Clouds = gToadsTurnpikeRainbowRoadStars;
Props.CloudList = gToadsTurnpikeRainbowRoadStars;
Props.MinimapFinishlineX = 0;
Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {0, 0, 0};
Props.Skybox.BottomRight = {0, 0, 0};
@@ -109,15 +116,16 @@ RainbowRoad::RainbowRoad() {
Props.Skybox.FloorBottomLeft = {0, 0, 0};
Props.Skybox.FloorTopLeft = {0, 0, 0};
Props.Sequence = MusicSeq::MUSIC_SEQ_RAINBOW_ROAD;
Props.WaterLevel = 0.0f;
}
void RainbowRoad::Load() {
Course::Load();
D_800DC5C8 = 1;
parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_rainbow_road_addr));
parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_rainbow_road_addr));
func_80295C6C();
D_8015F8E4 = 0.0f;
// d_course_rainbow_road_packed_dl_2068
find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07002068), -0x6A, 255, 255, 255);
// d_course_rainbow_road_packed_dl_1E18
@@ -147,7 +155,7 @@ void RainbowRoad::BeginPlay() {
}
if (gModeSelection == VERSUS) {
Vec3f pos = {0, 0, 0};
FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][50], 50, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][100], 100, 1, 0.8333333f));
@@ -167,15 +175,6 @@ void RainbowRoad::UpdateClouds(s32 sp1C, Camera* camera) {
update_stars(sp1C, camera, this->Props.CloudList);
}
// Likely sets minimap boundaries
void RainbowRoad::MinimapSettings() {
D_8018D2A0 = 0.0103f;
D_8018D2C0[0] = 261;
D_8018D2D8[0] = 166;
D_8018D2E0 = 39;
D_8018D2E8 = 55;
}
void RainbowRoad::InitCourseObjects() {
if (gGamestate != CREDITS_SEQUENCE) {
size_t i;
@@ -206,12 +205,6 @@ void RainbowRoad::WhatDoesThisDo(Player* player, int8_t playerId) {}
void RainbowRoad::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
// Positions the finishline on the minimap
void RainbowRoad::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
void RainbowRoad::Render(struct UnkStruct_800DC5EC* arg0) {
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
@@ -224,8 +217,6 @@ void RainbowRoad::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_rainbow_road_dl_16220));
}
void RainbowRoad::Collision() {}
void RainbowRoad::Waypoints(Player* player, int8_t playerId) {
player->nearestWaypointId = gCopyNearestWaypointByPlayerId[playerId];
}
-3
View File
@@ -29,17 +29,14 @@ public:
virtual void BeginPlay() override;
virtual void InitClouds() override;
virtual void UpdateClouds(s32, Camera*) override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void UpdateCourseObjects() override;
virtual void RenderCourseObjects(s32 cameraId) override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void Waypoints(Player* player, int8_t playerId) override;
virtual void DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) override;
virtual void CreditsSpawnActors() override;
+25 -41
View File
@@ -5,9 +5,10 @@
#include "RoyalRaceway.h"
#include "World.h"
#include "engine/actors/AFinishline.h"
#include "engine/actors/Finishline.h"
#include "engine/objects/BombKart.h"
#include "assets/royal_raceway_data.h"
#include "engine/objects/GrandPrixBalloons.h"
extern "C" {
#include "main.h"
@@ -30,6 +31,7 @@ extern "C" {
#include "collision.h"
#include "memory.h"
#include "courses/staff_ghost_data.h"
#include "course.h"
extern const char *royal_raceway_dls[];
}
@@ -85,16 +87,24 @@ RoyalRaceway::RoyalRaceway() {
this->gfx = d_course_royal_raceway_packed_dls;
this->gfxSize = 5670;
Props.textures = royal_raceway_textures;
Props.MinimapTexture = gTextureCourseOutlineRoyalRaceway;
Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
Props.Minimap.Texture = gTextureCourseOutlineRoyalRaceway;
Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
Props.Minimap.Pos[0].X = 262;
Props.Minimap.Pos[0].Y = 170;
Props.Minimap.PlayerX = 37;
Props.Minimap.PlayerY = 50;
Props.Minimap.PlayerScaleFactor = 0.014f;
Props.Minimap.FinishlineX = 0;
Props.Minimap.FinishlineY = 0;
Props.SetText(Props.Name, "royal raceway", sizeof(Props.Name));
Props.SetText(Props.DebugName, "p circuit", sizeof(Props.DebugName));
Props.SetText(Props.CourseLength, "1025m", sizeof(Props.CourseLength));
Props.Name = "royal raceway";
Props.DebugName = "p circuit";
Props.CourseLength = "1025m";
Props.AIBehaviour = D_0D009188;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.4f;
Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 9.0f;
@@ -132,10 +142,9 @@ RoyalRaceway::RoyalRaceway() {
Props.PathTable2[2] = NULL;
Props.PathTable2[3] = NULL;
Props.CloudTexture = (u8*) LOAD_ASSET_RAW(gTextureExhaust4);
Props.Clouds = gRoyalRacewayClouds;
Props.CloudList = gRoyalRacewayClouds;
Props.MinimapFinishlineX = 0;
Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {238, 144, 255};
Props.Skybox.BottomRight = {255, 224, 240};
@@ -146,14 +155,15 @@ RoyalRaceway::RoyalRaceway() {
Props.Skybox.FloorBottomLeft = {0, 0, 0};
Props.Skybox.FloorTopLeft = {255, 224, 240};
Props.Sequence = MusicSeq::MUSIC_SEQ_RACEWAYS_WARIO_STADIUM;
Props.WaterLevel = -60.0f;
}
void RoyalRaceway::Load() {
Course::Load();
parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_royal_raceway_addr));
parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_royal_raceway_addr));
func_80295C6C();
D_8015F8E4 = -60.0f;
}
void RoyalRaceway::LoadTextures() {
@@ -176,7 +186,7 @@ void RoyalRaceway::BeginPlay() {
spawn_piranha_plants((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_royal_raceway_piranha_plant_spawn));
if (gModeSelection == VERSUS) {
Vec3f pos = {0, 0, 0};
FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][50], 50, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][100], 100, 3, 0.8333333f));
@@ -186,18 +196,9 @@ void RoyalRaceway::BeginPlay() {
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][0], 0, 0, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][0], 0, 0, 0.8333333f));
}
}
// Likely sets minimap boundaries
void RoyalRaceway::MinimapSettings() {
D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust4, 0x3F8, 0x1000));
D_8018D2C0[0] = 262;
D_8018D2A0 = 0.014f;
D_8018D2E0 = 37;
D_8018D2E8 = 50;
D_80165718 = -64;
D_80165720 = 5;
D_80165728 = -330;
if (gGamestate != CREDITS_SEQUENCE) {
gWorldInstance.AddObject(new OGrandPrixBalloons(FVector(-64, 5, -330)));
}
}
void RoyalRaceway::InitCourseObjects() {
@@ -206,16 +207,9 @@ void RoyalRaceway::InitCourseObjects() {
if (gModeSelection == GRAND_PRIX) {
func_80070714();
}
for (i = 0; i < D_80165738; i++) {
find_unused_obj_index(&gObjectParticle3[i]);
init_object(gObjectParticle3[i], 0);
}
}
}
void RoyalRaceway::SomeSounds() {
}
void RoyalRaceway::WhatDoesThisDo(Player* player, int8_t playerId) {
if (((s16) gNearestWaypointByPlayerId[playerId] >= 0x180) &&
((s16) gNearestWaypointByPlayerId[playerId] < 0x1E1)) {
@@ -246,12 +240,6 @@ void RoyalRaceway::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
// Positions the finishline on the minimap
void RoyalRaceway::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
void RoyalRaceway::SetStaffGhost() {
u32 temp_v0 = func_800B4E24(0) & 0xfffff;
if (temp_v0 <= 16000) {
@@ -298,8 +286,6 @@ void RoyalRaceway::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_royal_raceway_dl_D8E8));
}
void RoyalRaceway::Collision() {}
void RoyalRaceway::Waypoints(Player* player, int8_t playerId) {
s16 waypoint = gNearestWaypointByPlayerId[playerId];
if ((waypoint >= 0x258) && (waypoint < 0x2A4)) {
@@ -322,5 +308,3 @@ void RoyalRaceway::ScrollingTextures() {
// d_course_royal_raceway_packed_dl_A648
find_and_set_tile_size((uintptr_t) segmented_gfx_to_virtual((void*)0x0700A648), 0, D_802B87BC);
}
void RoyalRaceway::Destroy() { }
-5
View File
@@ -27,17 +27,12 @@ public:
virtual void Load() override;
virtual void LoadTextures() override;
virtual void BeginPlay() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
virtual void SetStaffGhost() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void ScrollingTextures() override;
virtual void Waypoints(Player* player, int8_t playerId) override;
virtual void Destroy() override;
};
+39 -58
View File
@@ -5,7 +5,7 @@
#include "SherbetLand.h"
#include "World.h"
#include "engine/actors/AFinishline.h"
#include "engine/actors/Finishline.h"
#include "engine/objects/BombKart.h"
#include "assets/sherbet_land_data.h"
#include "engine/objects/Penguin.h"
@@ -30,6 +30,7 @@ extern "C" {
#include "actors.h"
#include "collision.h"
#include "memory.h"
#include "course.h"
extern const char *sherbet_land_dls[];
extern const char *sherbet_land_dls_2[];
}
@@ -48,19 +49,27 @@ SherbetLand::SherbetLand() {
this->gfx = d_course_sherbet_land_packed_dls;
this->gfxSize = 1803;
Props.textures = sherbet_land_textures;
Props.MinimapTexture = gTextureCourseOutlineSherbetLand;
Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
Props.Minimap.Texture = gTextureCourseOutlineSherbetLand;
Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
Props.Minimap.Pos[0].X = 262;
Props.Minimap.Pos[0].Y = 170;
Props.Minimap.PlayerX = 52;
Props.Minimap.PlayerY = 33;
Props.Minimap.PlayerScaleFactor = 0.015f;
Props.Minimap.FinishlineX = 0;
Props.Minimap.FinishlineY = 0;
Props.Minimap.Colour = {72, 100, 255};
Props.Name = "sherbet land";
Props.DebugName = "sherbet";
Props.CourseLength = "756m";
Props.SetText(Props.Name, "sherbet land", sizeof(Props.Name));
Props.SetText(Props.DebugName, "sherbet", sizeof(Props.DebugName));
Props.SetText(Props.CourseLength, "756m", sizeof(Props.CourseLength));
Props.LakituTowType = (s32)OLakitu::LakituTowType::ICE;
Props.AIBehaviour = D_0D009280;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.3f;
Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 9.0f;
@@ -98,10 +107,9 @@ SherbetLand::SherbetLand() {
Props.PathTable2[2] = NULL;
Props.PathTable2[3] = NULL;
Props.CloudTexture = (u8*) LOAD_ASSET_RAW(gTextureExhaust1);
Props.Clouds = gSherbetLandClouds;
Props.CloudList = gSherbetLandClouds;
Props.MinimapFinishlineX = 0;
Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {128, 184, 248};
Props.Skybox.BottomRight = {216, 232, 248};
@@ -112,21 +120,26 @@ SherbetLand::SherbetLand() {
Props.Skybox.FloorBottomLeft = {128, 184, 248};
Props.Skybox.FloorTopLeft = {216, 232, 248};
Props.Sequence = MusicSeq::MUSIC_SEQ_FRAPPE_SNOWLAND;
Props.WaterLevel = -18.0f;
}
void SherbetLand::Load() {
Course::Load();
parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_sherbet_land_addr));
parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_sherbet_land_addr));
func_80295C6C();
D_8015F8E4 = -18.0f;
// d_course_sherbet_land_packed_dl_1EB8
find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07001EB8), -0x4C, 255, 255, 255);
// d_course_sherbet_land_packed_dl_2308
find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07002308), -0x6A, 255, 255, 255);
}
void SherbetLand::LoadTextures() {
f32 SherbetLand::GetWaterLevel(FVector pos, Collision* collision) {
if ((get_surface_type(collision->meshIndexZX) & 0xFF) == SNOW) {
return (f32) (gCourseMinY - 0xA);
}
return Props.WaterLevel;
}
void SherbetLand::BeginPlay() {
@@ -134,65 +147,65 @@ void SherbetLand::BeginPlay() {
// Multiplayer does not spawn the big penguin
// if (gPlayerCountSelection1 == 1) {
Vec3f pos = {-383.0f, 2.0f, -690.0f};
FVector pos = {-383.0f, 2.0f, -690.0f};
gWorldInstance.AddObject(new OPenguin(pos, 0, OPenguin::PenguinType::EMPEROR, OPenguin::Behaviour::STRUT));
// }
Vec3f pos2 = {-2960.0f, -80.0f, 1521.0f};
FVector pos2 = { -2960.0f, -80.0f, 1521.0f };
auto penguin = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos2, 0x150, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE)));
auto penguin2 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos2, 0x150, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE)));
penguin->Diameter = penguin2->Diameter = 100.0f;
Vec3f pos3 = {-2490.0f, -80.0f, 1612.0f};
FVector pos3 = { -2490.0f, -80.0f, 1612.0f };
auto penguin3 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos3, 0x100, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE)));
auto penguin4 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos3, 0x100, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE)));
penguin3->Diameter = penguin4->Diameter = 80.0f;
Vec3f pos4 = {-2098.0f, -80.0f, 1624.0f};
FVector pos4 = { -2098.0f, -80.0f, 1624.0f };
auto penguin5 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos4, 0xFF00, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE)));
auto penguin6 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos4, 0xFF00, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE)));
penguin5->Diameter = penguin6->Diameter = 80.0f;
Vec3f pos5 = {-2080.0f, -80.0f, 1171.0f};
FVector pos5 = { -2080.0f, -80.0f, 1171.0f };
auto penguin7 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos5, 0x150, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE)));
auto penguin8 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos5, 0x150, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE)));
penguin7->Diameter = penguin8->Diameter = 80.0f;
if (gGamestate == CREDITS_SEQUENCE) {
Vec3f pos6 = {380.0, 0.0f, -535.0f};
FVector pos6 = { 380.0, 0.0f, -535.0f };
auto penguin9 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos6, 0x9000, OPenguin::PenguinType::CREDITS, OPenguin::Behaviour::SLIDE3)));
penguin9->MirrorModeAngleOffset = -0x4000;
} else {
Vec3f pos6 = {146.0f, 0.0f, -380.0f};
FVector pos6 = { 146.0f, 0.0f, -380.0f };
auto penguin9 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos6, 0x9000, OPenguin::PenguinType::CHICK, OPenguin::Behaviour::SLIDE3)));
penguin9->MirrorModeAngleOffset = -0x4000;
}
Vec3f pos7 = {380.0f, 0.0f, -766.0f};
FVector pos7 = { 380.0f, 0.0f, -766.0f };
auto penguin10 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos7, 0x5000, OPenguin::PenguinType::CHICK, OPenguin::Behaviour::SLIDE4)));
penguin10->MirrorModeAngleOffset = 0x8000;
Vec3f pos8 = {-2300.0f, 0.0f, -210.0f};
FVector pos8 = { -2300.0f, 0.0f, -210.0f };
auto penguin11 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos8, 0xC000, OPenguin::PenguinType::CHICK, OPenguin::Behaviour::SLIDE6)));
penguin11->MirrorModeAngleOffset = 0x8000;
Vec3f pos9 = {-2500.0f, 0.0f, -250.0f};
FVector pos9 = { -2500.0f, 0.0f, -250.0f };
auto penguin12 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos9, 0x4000, OPenguin::PenguinType::CHICK, OPenguin::Behaviour::SLIDE6)));
penguin12->MirrorModeAngleOffset = 0x8000;
Vec3f pos10 = {-535.0f, 0.0f, 875.0f};
FVector pos10 = { -535.0f, 0.0f, 875.0f };
auto penguin13 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos10, 0x8000, OPenguin::PenguinType::CHICK, OPenguin::Behaviour::SLIDE6)));
penguin13->MirrorModeAngleOffset = -0x4000;
Vec3f pos11 = {-250.0f, 0.0f, 953.0f};
FVector pos11 = { -250.0f, 0.0f, 953.0f };
auto penguin14 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos11, 0x9000, OPenguin::PenguinType::CHICK, OPenguin::Behaviour::SLIDE6)));
penguin14->MirrorModeAngleOffset = -0x4000;
if (gGamestate != CREDITS_SEQUENCE) {
if (gModeSelection == VERSUS) {
Vec3f kart = {0, 0, 0};
FVector kart = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(kart, &D_80164550[0][50], 50, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(kart, &D_80164550[0][100], 100, 1, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(kart, &D_80164550[0][150], 150, 3, 0.8333333f));
@@ -204,21 +217,6 @@ void SherbetLand::BeginPlay() {
}
}
// Likely sets minimap boundaries
void SherbetLand::MinimapSettings() {
D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust1, 0x485, 0xC00));
D_8018D2A0 = 0.015f;
D_8018D2C0[0] = 262;
D_8018D2E0 = 52;
D_8018D2E8 = 33;
D_8018D300 = 72;
D_8018D308 = 100;
D_8018D310 = 255;
}
void SherbetLand::InitCourseObjects() {
}
void SherbetLand::UpdateCourseObjects() {
if (gGamestate != CREDITS_SEQUENCE) {
func_800842C8();
@@ -231,19 +229,6 @@ void SherbetLand::RenderCourseObjects(s32 cameraId) {
}
}
void SherbetLand::SomeSounds() {
}
void SherbetLand::WhatDoesThisDo(Player* player, int8_t playerId) {}
void SherbetLand::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
// Positions the finishline on the minimap
void SherbetLand::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
void SherbetLand::Render(struct UnkStruct_800DC5EC* arg0) {
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
@@ -257,8 +242,6 @@ void SherbetLand::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_sherbet_land_dl_9AE8));
}
void SherbetLand::Collision() {}
void SherbetLand::DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) {
Mat4 matrix;
@@ -275,7 +258,7 @@ void SherbetLand::DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCoun
render_course_segments(sherbet_land_dls_2, screen);
gDPSetAlphaCompare(gDisplayListHead++, G_AC_NONE);
if ((func_80290C20(screen->camera) == 1) && (func_802AAB4C(screen->player) < screen->player->pos[1])) {
if ((func_80290C20(screen->camera) == 1) && (get_water_level(screen->player) < screen->player->pos[1])) {
gSPSetGeometryMode(gDisplayListHead++, G_ZBUFFER);
gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE);
gDPSetRenderMode(gDisplayListHead++, G_RM_AA_ZB_OPA_SURF, G_RM_AA_ZB_OPA_SURF2);
@@ -291,5 +274,3 @@ void SherbetLand::CreditsSpawnActors() {
// d_course_sherbet_land_packed_dl_2308
find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07002308), -0x6A, 0xFF, 0xFF, 0xFF);
}
void SherbetLand::Destroy() { }
+1 -9
View File
@@ -25,20 +25,12 @@ public:
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void LoadTextures() override;
virtual f32 GetWaterLevel(FVector pos, Collision* collision) override;
virtual void BeginPlay() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void UpdateCourseObjects() override;
virtual void RenderCourseObjects(s32 cameraId) override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) override;
virtual void CreditsSpawnActors() override;
virtual void Destroy() override;
};
+18 -27
View File
@@ -64,16 +64,24 @@ Skyscraper::Skyscraper() {
this->gfx = d_course_skyscraper_packed_dls;
this->gfxSize = 548;
Props.textures = skyscraper_textures;
Props.MinimapTexture = gTextureCourseOutlineSkyscraper;
Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
Props.Minimap.Texture = gTextureCourseOutlineSkyscraper;
Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
Props.Minimap.Pos[0].X = 257;
Props.Minimap.Pos[0].Y = 170;
Props.Minimap.PlayerX = 32;
Props.Minimap.PlayerY = 32;
Props.Minimap.PlayerScaleFactor = 0.0445f;
Props.Minimap.FinishlineX = 0;
Props.Minimap.FinishlineY = 0;
Props.SetText(Props.Name, "skyscraper", sizeof(Props.Name));
Props.SetText(Props.DebugName, "skyscraper", sizeof(Props.DebugName));
Props.SetText(Props.CourseLength, "", sizeof(Props.CourseLength));
Props.Name = "skyscraper";
Props.DebugName = "skyscraper";
Props.CourseLength = "";
Props.AIBehaviour = D_0D008F18;
Props.AIMaximumSeparation = -1.0f;
Props.AIMinimumSeparation = 0.5f;
Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 2.0f;
@@ -113,8 +121,6 @@ Skyscraper::Skyscraper() {
Props.Clouds = NULL; // no clouds
Props.CloudList = NULL;
Props.MinimapFinishlineX = 0;
Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {0, 0, 0};
Props.Skybox.BottomRight = {0, 0, 0};
@@ -125,6 +131,8 @@ Skyscraper::Skyscraper() {
Props.Skybox.FloorBottomLeft = {0, 0, 0};
Props.Skybox.FloorTopLeft = {0, 0, 0};
Props.Sequence = MusicSeq::MUSIC_SEQ_BATTLE_ARENAS;
Props.WaterLevel = -480.0f;
}
void Skyscraper::Load() {
@@ -135,8 +143,6 @@ void Skyscraper::Load() {
// d_course_skyscraper_packed_dl_258
generate_collision_mesh_with_default_section_id((Gfx*) segmented_gfx_to_virtual((void*)0x07000258), 1);
func_80295C6C();
D_8015F8E4 = -480.0f;
}
void Skyscraper::LoadTextures() {
@@ -146,7 +152,7 @@ void Skyscraper::BeginPlay() {
spawn_all_item_boxes((ActorSpawnData*)LOAD_ASSET_RAW(d_course_skyscraper_item_box_spawns));
if (gModeSelection == VERSUS) {
Vec3f pos = {0, 0, 0};
FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][20], 20, 0, 1.0f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][40], 40, 0, 1.0f));
@@ -158,13 +164,6 @@ void Skyscraper::BeginPlay() {
}
}
// Likely sets minimap boundaries
void Skyscraper::MinimapSettings() {
D_8018D2A0 = 0.0445f;
D_8018D2E0 = 32;
D_8018D2E8 = 32;
}
void Skyscraper::InitCourseObjects() {}
void Skyscraper::SomeSounds() {}
@@ -173,14 +172,8 @@ void Skyscraper::WhatDoesThisDo(Player* player, int8_t playerId) {}
void Skyscraper::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
// Positions the finishline on the minimap
void Skyscraper::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
void Skyscraper::Render(struct UnkStruct_800DC5EC* arg0) {
func_802B5D64(D_800DC610, D_802B87D4, 0, 1);
set_track_light_direction(D_800DC610, D_802B87D4, 0, 1);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
@@ -204,8 +197,6 @@ void Skyscraper::Render(struct UnkStruct_800DC5EC* arg0) {
void Skyscraper::RenderCredits() {}
void Skyscraper::Collision() {}
void Skyscraper::Waypoints(Player* player, int8_t playerId) {
player->nearestWaypointId = 0;
}
-3
View File
@@ -28,15 +28,12 @@ public:
virtual void LoadTextures() override;
virtual void BeginPlay() override;
//virtual void InitClouds() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void Waypoints(Player* player, int8_t playerId) override;
virtual void Destroy() override;
};
+28 -53
View File
@@ -6,7 +6,7 @@
#include "TestCourse.h"
#include "World.h"
#include "engine/actors/AFinishline.h"
#include "engine/actors/Finishline.h"
#include "engine/actors/BowserStatue.h"
#include "engine/actors/Ship.h"
#include "engine/actors/SpaghettiShip.h"
@@ -16,8 +16,8 @@
#include "assets/mario_raceway_data.h"
#include "assets/bowsers_castle_data.h"
#include "assets/bowsers_castle_displaylists.h"
#include "engine/actors/ATree.h"
#include "engine/actors/ACloud.h"
#include "engine/actors/Tree.h"
#include "engine/actors/Cloud.h"
#include "engine/vehicles/Train.h"
#include "engine/objects/Trophy.h"
#include "engine/objects/CheepCheep.h"
@@ -28,6 +28,7 @@
#include "engine/objects/HotAirBalloon.h"
#include "engine/objects/Crab.h"
#include "engine/objects/Boos.h"
#include "engine/objects/GrandPrixBalloons.h"
extern "C" {
#include "main.h"
@@ -49,12 +50,7 @@ extern "C" {
#include "actors.h"
#include "collision.h"
#include "memory.h"
typedef struct {
Gfx* addr;
u8 surfaceType;
u8 sectionId;
u16 flags;
} TrackSections;
#include "course.h"
extern Gfx test_course_dls[];
extern Vtx mario_Plane_001_mesh_vtx_1[];
extern Gfx mario_Plane_001_mesh[];
@@ -65,18 +61,27 @@ extern "C" {
TestCourse::TestCourse() {
this->gfxSize = 100;
this->textures = NULL;
Props.MinimapTexture = gTextureCourseOutlineMarioRaceway;
Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
Props.Minimap.Texture = gTextureCourseOutlineMarioRaceway;
Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
Props.Minimap.Pos[0].X = 260;
Props.Minimap.Pos[0].Y = 170;
Props.Minimap.PlayerX = 6;
Props.Minimap.PlayerY = 28;
Props.Minimap.PlayerScaleFactor = 0.022f;
Props.Minimap.FinishlineX = 0;
Props.Minimap.FinishlineY = 0;
Props.Minimap.Colour = {255, 255, 255};
Props.Id = "mk:test_course";
Props.Name = "Test Course";
Props.DebugName = "test track";
Props.CourseLength = "100m";
Id = "mk:test_course";
Props.SetText(Props.Name, "Test Course", sizeof(Props.Name));
Props.SetText(Props.DebugName, "test track", sizeof(Props.DebugName));
Props.SetText(Props.CourseLength, "100m", sizeof(Props.CourseLength));
Props.AIBehaviour = D_0D008F28;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.3f;
Props.SomePtr = D_800DCB34;
Props.AISteeringSensitivity = 48;
Props.NearPersp = 9.0f;
@@ -114,10 +119,9 @@ TestCourse::TestCourse() {
Props.PathTable2[2] = NULL;
Props.PathTable2[3] = NULL;
Props.CloudTexture = (u8*) LOAD_ASSET_RAW(gTextureExhaust5);
Props.Clouds = gKalimariDesertClouds;
Props.CloudList = gLuigiRacewayClouds;
Props.MinimapFinishlineX = 0;
Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {120, 140, 188};
Props.Skybox.BottomRight = {216, 232, 248};
@@ -135,9 +139,9 @@ void TestCourse::Load() {
generate_collision_mesh_with_defaults(mario_Plane_001_mesh);
parse_course_displaylists((TrackSectionsI*)test_course_addr);
parse_course_displaylists((TrackSections*)test_course_addr);
func_80295C6C();
D_8015F8E4 = gCourseMinY - 10.0f;
Props.WaterLevel = gCourseMinY - 10.0f;
}
void TestCourse::LoadTextures() {
@@ -267,7 +271,7 @@ void TestCourse::BeginPlay() {
// gWorldInstance.AddObject(new OCheepCheep(FVector(0, 40, 0), OCheepCheep::CheepType::RACE, IPathSpan(0, 10)));
// gWorldInstance.AddObject(new OTrophy(FVector(0,0,0), OTrophy::TrophyType::GOLD, OTrophy::Behaviour::GO_FISH));
//gWorldInstance.AddObject(new OSnowman(FVector(0, 0, 0)));
//gWorldInstance.AddObject(new OTrashBin(FVector(0.0f, 0.0f, 0.0f), FRotation(0, 90, 0), 1.0f, OTrashBin::Behaviour::MUNCHING));
//gWorldInstance.AddObject(new OTrashBin(FVector(0.0f, 0.0f, 0.0f), IRotator(0, 90, 0), 1.0f, OTrashBin::Behaviour::MUNCHING));
//gWorldInstance.AddObject(new OHedgehog(FVector(0, 0, 0), FVector2D(0, -200), 9));
//gWorldInstance.AddObject(new OFlagpole(FVector(0, 0, -200), 0x400));
@@ -285,32 +289,16 @@ void TestCourse::BeginPlay() {
//gWorldInstance.AddTrain(ATrain::TenderStatus::HAS_TENDER, 5, 2.5f, 0);
//gWorldInstance.AddTrain(ATrain::TenderStatus::HAS_TENDER, 5, 2.5f, 8);
Vec3f pos2 = {0, 0, 0};
FVector pos2 = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos2, &D_80164550[0][25], 25, 4, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos2, &D_80164550[0][45], 45, 4, 0.8333333f));
gWorldInstance.AddActor(new AShip(FVector(0, 0, 0), AShip::Skin::SHIP3));
gWorldInstance.AddObject(new OGrandPrixBalloons(FVector(0, 0, 0)));
}
// Likely sets minimap boundaries
void TestCourse::MinimapSettings() {
D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust5, 0x443, 0x1000));
D_8018D2A0 = 0.022f;
D_8018D2E0 = 6;
D_8018D2E8 = 28;
D_8018D2C0[0] = 260;
D_8018D2D8[0] = 170;
D_80165718 = 0;
D_80165720 = 5;
D_80165728 = -240;
}
void TestCourse::InitCourseObjects() {}
void TestCourse::SomeSounds() {}
void TestCourse::WhatDoesThisDo(Player* player, int8_t playerId) {
if (((s16) gNearestWaypointByPlayerId[playerId] >= 0x19B) &&
((s16) gNearestWaypointByPlayerId[playerId] < 0x1B9)) {
@@ -341,16 +329,10 @@ void TestCourse::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
// Positions the finishline on the minimap
void TestCourse::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
void TestCourse::Render(struct UnkStruct_800DC5EC* arg0) {
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
func_802B5D64(D_800DC610, D_802B87D4, 0, 1);
set_track_light_direction(D_800DC610, D_802B87D4, 0, 1);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
@@ -362,13 +344,6 @@ void TestCourse::Render(struct UnkStruct_800DC5EC* arg0) {
gSPDisplayList(gDisplayListHead++, mario_Plane_001_mesh);
}
void TestCourse::RenderCredits() {
}
void TestCourse::Collision() {}
void TestCourse::Destroy() { }
bool TestCourse::IsMod() {
return true;
}
-7
View File
@@ -27,15 +27,8 @@ public:
virtual void Load() override;
virtual void LoadTextures() override;
virtual void BeginPlay() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void Destroy() override;
virtual bool IsMod() override;
};
+20 -30
View File
@@ -7,7 +7,7 @@
#include "World.h"
#include "engine/objects/BombKart.h"
#include "assets/toads_turnpike_data.h"
#include "engine/actors/AFinishline.h"
#include "engine/actors/Finishline.h"
#include "engine/vehicles/Bus.h"
#include "engine/vehicles/Car.h"
#include "engine/vehicles/Truck.h"
@@ -36,6 +36,7 @@ extern "C" {
#include "collision.h"
#include "memory.h"
#include "code_80086E70.h"
#include "course.h"
extern const char *d_course_toads_turnpike_dl_list[];
extern s16 currentScreenSection;
extern s8 gPlayerCount;
@@ -69,16 +70,24 @@ ToadsTurnpike::ToadsTurnpike() {
this->gfx = d_course_toads_turnpike_packed_dls;
this->gfxSize = 3427;
Props.textures = toads_turnpike_textures;
Props.MinimapTexture = gTextureCourseOutlineToadsTurnpike;
Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
Props.Minimap.Texture = gTextureCourseOutlineToadsTurnpike;
Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
Props.Minimap.Pos[0].X = 252;
Props.Minimap.Pos[0].Y = 170;
Props.Minimap.PlayerX = 57;
Props.Minimap.PlayerY = 44;
Props.Minimap.PlayerScaleFactor = 0.013f;
Props.Minimap.FinishlineX = 0;
Props.Minimap.FinishlineY = 0;
Props.SetText(Props.Name, "toad's turnpike", sizeof(Props.Name));
Props.SetText(Props.DebugName, "highway", sizeof(Props.DebugName));
Props.SetText(Props.CourseLength, "1036m", sizeof(Props.CourseLength));
Props.Name = "toad's turnpike";
Props.DebugName = "highway";
Props.CourseLength = "1036m";
Props.AIBehaviour = D_0D009238;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.5f;
Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 40;
Props.NearPersp = 9.0f;
@@ -126,9 +135,6 @@ ToadsTurnpike::ToadsTurnpike() {
this->FinishlineSpawnPoint = finish;
Props.MinimapFinishlineX = 0;
Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {0, 2, 94};
Props.Skybox.BottomRight = {209, 65, 23};
Props.Skybox.BottomLeft = {209, 65, 23};
@@ -148,9 +154,9 @@ void ToadsTurnpike::Load() {
D_801625F0 = 4;
D_802B87B0 = 993;
D_802B87B4 = 1000;
parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_toads_turnpike_addr));
parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_toads_turnpike_addr));
func_80295C6C();
D_8015F8E4 = gCourseMinY - 10.0f;
Props.WaterLevel = gCourseMinY - 10.0f;
}
void ToadsTurnpike::LoadTextures() {
@@ -195,7 +201,7 @@ void ToadsTurnpike::BeginPlay() {
}
if (gModeSelection == VERSUS) {
Vec3f pos = {0, 0, 0};
FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][50], 50, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][100], 100, 1, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][150], 150, 3, 0.8333333f));
@@ -215,14 +221,6 @@ void ToadsTurnpike::UpdateClouds(s32 sp1C, Camera* camera) {
update_stars(sp1C, camera, this->Props.CloudList);
}
// Likely sets minimap boundaries
void ToadsTurnpike::MinimapSettings() {
D_8018D2A0 = 0.013f;
D_8018D2C0[0] = 252;
D_8018D2E0 = 57;
D_8018D2E8 = 44;
}
void ToadsTurnpike::SomeSounds() {}
void ToadsTurnpike::WhatDoesThisDo(Player* player, int8_t playerId) {
@@ -253,14 +251,8 @@ void ToadsTurnpike::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
// Positions the finishline on the minimap
void ToadsTurnpike::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
void ToadsTurnpike::Render(struct UnkStruct_800DC5EC* arg0) {
func_802B5D64(D_800DC610, D_802B87D4, 0, 1);
set_track_light_direction(D_800DC610, D_802B87D4, 0, 1);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
@@ -289,6 +281,4 @@ void ToadsTurnpike::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_toads_turnpike_dl_23930));
}
void ToadsTurnpike::Collision() {}
void ToadsTurnpike::Destroy() { }
-3
View File
@@ -29,14 +29,11 @@ public:
virtual void BeginPlay() override;
virtual void InitClouds() override;
virtual void UpdateClouds(s32, Camera*) override;
virtual void MinimapSettings() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void Destroy() override;
private:
size_t _numTrucks = 7;
+26 -38
View File
@@ -7,8 +7,8 @@
#include "World.h"
#include "engine/objects/BombKart.h"
#include "assets/wario_stadium_data.h"
#include "engine/actors/AWarioSign.h"
#include "engine/actors/AFinishline.h"
#include "engine/actors/WarioSign.h"
#include "engine/actors/Finishline.h"
extern "C" {
#include "main.h"
@@ -32,6 +32,7 @@ extern "C" {
#include "code_8003DC40.h"
#include "memory.h"
#include "skybox_and_splitscreen.h"
#include "course.h"
extern const char* wario_stadium_dls[];
extern s16 currentScreenSection;
}
@@ -65,16 +66,24 @@ WarioStadium::WarioStadium() {
this->gfx = d_course_wario_stadium_packed_dls;
this->gfxSize = 5272;
Props.textures = wario_stadium_textures;
Props.MinimapTexture = gTextureCourseOutlineWarioStadium;
Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
Props.Minimap.Texture = gTextureCourseOutlineWarioStadium;
Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
Props.Minimap.Pos[0].X = 262;
Props.Minimap.Pos[0].Y = 170;
Props.Minimap.PlayerX = 53;
Props.Minimap.PlayerY = 35;
Props.Minimap.PlayerScaleFactor = 0.0155f;
Props.Minimap.FinishlineX = 0;
Props.Minimap.FinishlineY = 0;
Props.SetText(Props.Name, "wario stadium", sizeof(Props.Name));
Props.SetText(Props.DebugName, "stadium", sizeof(Props.DebugName));
Props.SetText(Props.CourseLength, "1591m", sizeof(Props.CourseLength));
Props.Name = "wario stadium";
Props.DebugName = "stadium";
Props.CourseLength = "1591m";
Props.AIBehaviour = D_0D009310;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.6f;
Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 10.0f;
@@ -122,9 +131,6 @@ WarioStadium::WarioStadium() {
this->FinishlineSpawnPoint = finish;
Props.MinimapFinishlineX = 0;
Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = { 20, 30, 56 };
Props.Skybox.BottomRight = { 40, 60, 110 };
Props.Skybox.BottomLeft = { 40, 60, 110 };
@@ -139,9 +145,9 @@ WarioStadium::WarioStadium() {
void WarioStadium::Load() {
Course::Load();
parse_course_displaylists((TrackSectionsI*) LOAD_ASSET_RAW(d_course_wario_stadium_addr));
parse_course_displaylists((TrackSections*) LOAD_ASSET_RAW(d_course_wario_stadium_addr));
func_80295C6C();
D_8015F8E4 = gCourseMinY - 10.0f;
Props.WaterLevel = gCourseMinY - 10.0f;
// d_course_wario_stadium_packed_dl_C50
find_vtx_and_set_colours(segmented_gfx_to_virtual((void*) 0x07000C50), 100, 255, 255, 255);
// d_course_wario_stadium_packed_dl_BD8
@@ -166,20 +172,20 @@ void WarioStadium::LoadTextures() {
void WarioStadium::BeginPlay() {
spawn_all_item_boxes((struct ActorSpawnData*) LOAD_ASSET_RAW(d_course_wario_stadium_item_box_spawns));
Vec3f pos = { -131.0f, 83.0f, 286.0f };
pos[0] *= gCourseDirection;
FVector pos = { -131.0f, 83.0f, 286.0f };
pos.x *= gCourseDirection;
gWorldInstance.AddActor(new AWarioSign(pos));
Vec3f pos2 = { -2353.0f, 72.0f, -1608.0f };
pos2[0] *= gCourseDirection;
FVector pos2 = { -2353.0f, 72.0f, -1608.0f };
pos2.x *= gCourseDirection;
gWorldInstance.AddActor(new AWarioSign(pos2));
Vec3f pos3 = { -2622.0f, 79.0f, 739.0f };
pos3[0] *= gCourseDirection;
FVector pos3 = { -2622.0f, 79.0f, 739.0f };
pos3.x *= gCourseDirection;
gWorldInstance.AddActor(new AWarioSign(pos3));
if (gModeSelection == VERSUS) {
Vec3f pos = { 0, 0, 0 };
FVector pos = { 0, 0, 0 };
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][50], 50, 3, 0.8333333f));
gWorldInstance.AddObject(new OBombKart(pos, &D_80164550[0][100], 100, 1, 0.8333333f));
@@ -199,14 +205,6 @@ void WarioStadium::UpdateClouds(s32 sp1C, Camera* camera) {
update_stars(sp1C, camera, this->Props.CloudList);
}
// Likely sets minimap boundaries
void WarioStadium::MinimapSettings() {
D_8018D2A0 = 0.0155f;
D_8018D2C0[0] = 0x0106;
D_8018D2E0 = 53;
D_8018D2E8 = 35;
}
void WarioStadium::InitCourseObjects() {
}
@@ -227,13 +225,6 @@ void WarioStadium::WhatDoesThisDo(Player* player, int8_t playerId) {
void WarioStadium::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
// Positions the finishline on the minimap
void WarioStadium::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY,
(u8*) common_texture_minimap_finish_line);
}
void WarioStadium::Jumbotron() {
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gDPTileSync(gDisplayListHead++);
@@ -365,9 +356,6 @@ void WarioStadium::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*) (d_course_wario_stadium_dl_CA78));
}
void WarioStadium::Collision() {
}
void WarioStadium::SomeCollisionThing(Player* player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5,
f32* arg6, f32* arg7) {
func_8003EE2C(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
-3
View File
@@ -31,15 +31,12 @@ class WarioStadium : public Course {
virtual void BeginPlay() override;
virtual void InitClouds() override;
virtual void UpdateClouds(s32, Camera*) override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void SomeCollisionThing(Player* player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6,
f32* arg7) override;
virtual void DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot,
+25 -35
View File
@@ -6,7 +6,7 @@
#include "YoshiValley.h"
#include "World.h"
#include "engine/actors/AFinishline.h"
#include "engine/actors/Finishline.h"
#include "engine/objects/BombKart.h"
#include "engine/objects/Hedgehog.h"
#include "engine/objects/Flagpole.h"
@@ -33,6 +33,7 @@ extern "C" {
#include "actors.h"
#include "collision.h"
#include "memory.h"
#include "course.h"
extern const char *d_course_yoshi_valley_dl_list[];
}
@@ -60,16 +61,22 @@ YoshiValley::YoshiValley() {
this->gfxSize = 4140;
Props.textures = yoshi_valley_textures;
Props.MinimapTexture = gTextureCourseOutlineYoshiValley;
Props.MinimapDimensions = IVector2D(ResourceGetTexWidthByName(Props.MinimapTexture), ResourceGetTexHeightByName(Props.MinimapTexture));
Props.Minimap.Texture = gTextureCourseOutlineYoshiValley;
Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture);
Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture);
Props.Minimap.PlayerX = 61;
Props.Minimap.PlayerY = 38;
Props.Minimap.PlayerScaleFactor = 0.018f;
Props.Minimap.FinishlineX = 0;
Props.Minimap.FinishlineY = 0;
Props.SetText(Props.Name, "yoshi valley", sizeof(Props.Name));
Props.SetText(Props.DebugName, "maze", sizeof(Props.DebugName));
Props.SetText(Props.CourseLength, "772m", sizeof(Props.CourseLength));
Props.Name = "yoshi valley";
Props.DebugName = "maze";
Props.CourseLength = "772m";
Props.AIBehaviour = D_0D0090B8;
Props.AIMaximumSeparation = 35.0f;
Props.AIMinimumSeparation = 0.0f;
Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 9.0f;
@@ -107,10 +114,9 @@ YoshiValley::YoshiValley() {
Props.PathTable2[2] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_yoshi_valley_track_waypoints_3);
Props.PathTable2[3] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_yoshi_valley_track_waypoints_4);
Props.CloudTexture = (u8*) LOAD_ASSET_RAW(gTextureExhaust0);
Props.Clouds = gYoshiValleyMooMooFarmClouds;
Props.CloudList = gYoshiValleyMooMooFarmClouds;
Props.MinimapFinishlineX = 0;
Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {113, 70, 255};
Props.Skybox.BottomRight = {255, 184, 99};
@@ -127,10 +133,10 @@ void YoshiValley::Load() {
Course::Load();
Lights1 lights4 = gdSPDefLights1(100, 100, 100, 255, 254, 254, 0, 0, 120);
func_802B5D64(&lights4, -0x38F0, 0x1C70, 1);
parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_yoshi_valley_addr));
set_track_light_direction(&lights4, -0x38F0, 0x1C70, 1);
parse_course_displaylists((TrackSections*)LOAD_ASSET_RAW(d_course_yoshi_valley_addr));
func_80295C6C();
D_8015F8E4 = gCourseMinY - 10.0f;
Props.WaterLevel = gCourseMinY - 10.0f;
}
void YoshiValley::LoadTextures() {
@@ -177,31 +183,23 @@ void YoshiValley::BeginPlay() {
// the original data has values here.
// Note that the Y height is calculated automatically to place the kart on the surface
Vec3f pos = {-1533, 0, -682};
FVector pos = { -1533, 0, -682 };
gWorldInstance.AddObject(new OBombKart(pos, NULL, 0, 0, 0.8333333f));
Vec3f pos2 = {-1565, 0, -619};
FVector pos2 = { -1565, 0, -619 };
gWorldInstance.AddObject(new OBombKart(pos2, NULL, 10, 0, 0.8333333f));
Vec3f pos3 = {-1529, 0, -579};
FVector pos3 = { -1529, 0, -579 };
gWorldInstance.AddObject(new OBombKart(pos3, NULL, 20, 0, 0.8333333f));
Vec3f pos4 = {-1588, 0, -534};
FVector pos4 = { -1588, 0, -534 };
gWorldInstance.AddObject(new OBombKart(pos4, NULL, 30, 0, 0.8333333f));
Vec3f pos5 = {-1598, 0, -207};
FVector pos5 = { -1598, 0, -207 };
gWorldInstance.AddObject(new OBombKart(pos5, NULL, 40, 0, 0.8333333f));
Vec3f pos6 = {-1646, 0, -147};
FVector pos6 = { -1646, 0, -147 };
gWorldInstance.AddObject(new OBombKart(pos6, NULL, 50, 0, 0.8333333f));
Vec3f pos7 = {-2532, 0, -445};
FVector pos7 = { -2532, 0, -445 };
gWorldInstance.AddObject(new OBombKart(pos7, NULL, 60, 0, 0.8333333f));
}
}
// Likely sets minimap boundaries
void YoshiValley::MinimapSettings() {
D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust0, 0x479, 0xC00));
D_8018D2A0 = 0.018f;
D_8018D2E0 = 61;
D_8018D2E8 = 38;
}
void YoshiValley::InitCourseObjects() {
}
@@ -218,12 +216,6 @@ void YoshiValley::WhatDoesThisDo(Player* player, int8_t playerId) {}
void YoshiValley::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
// Positions the finishline on the minimap
void YoshiValley::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
void YoshiValley::Render(struct UnkStruct_800DC5EC* arg0) {
gDPPipeSync(gDisplayListHead++);
gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEI, G_CC_MODULATEI);
@@ -237,8 +229,6 @@ void YoshiValley::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_yoshi_valley_dl_18020));
}
void YoshiValley::Collision() {}
void YoshiValley::Waypoints(Player* player, int8_t playerId) {
player->nearestWaypointId = gCopyNearestWaypointByPlayerId[playerId];
}
-3
View File
@@ -27,17 +27,14 @@ public:
virtual void Load() override;
virtual void LoadTextures() override;
virtual void BeginPlay() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void UpdateCourseObjects() override;
virtual void RenderCourseObjects(s32 cameraId) override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void ScrollingTextures() override;
virtual void Waypoints(Player* player, int8_t playerId) override;
virtual void CreditsSpawnActors() override;
+188
View File
@@ -0,0 +1,188 @@
#include "Collision.h"
#include <libultraship/libultraship.h>
#include <libultra/gbi.h>
#include "Matrix.h"
extern "C" {
#include "main.h"
#include "other_textures.h"
}
namespace Editor {
void GenerateCollisionMesh(GameObject* object, Gfx* model, float scale) {
int8_t opcode;
uintptr_t lo;
uintptr_t hi;
Gfx* ptr = model;
Vtx* vtx = NULL;
size_t i = 0;
bool run = true;
while (run) {
i++;
lo = ptr->words.w0;
hi = ptr->words.w1;
opcode = (EDITOR_GFX_GET_OPCODE(lo) >> 24);
switch(opcode) {
case G_DL:
GenerateCollisionMesh(object, (Gfx*)hi, scale);
break;
case G_DL_OTR_HASH:
ptr++;
GenerateCollisionMesh(object, (Gfx*)ResourceGetDataByCrc(((uint64_t)(ptr->words.w0 << 32)) + ptr->words.w1), scale);
break;
case G_DL_OTR_FILEPATH:
// printf("otr filepath: %s\n", (const char*)hi);
GenerateCollisionMesh(object, (Gfx*)ResourceGetDataByName((const char*)hi), scale);
break;
case G_VTX:
vtx = (Vtx*)ptr->words.w1;
break;
case G_VTX_OTR_HASH: {
ptr++;
vtx = (Vtx*)ResourceGetDataByCrc(((uint64_t)(ptr->words.w0 << 32)) + ptr->words.w1);
break;
}
case G_VTX_OTR_FILEPATH: {
const char* filePath = (const char*)hi;
ptr++;
size_t vtxDataOff = ptr->words.w1 & 0xFFFF;
vtx = ( (Vtx*)ResourceGetDataByName(filePath) ) + vtxDataOff;
break;
}
case G_TRI1: {
if (vtx == NULL) {
ptr++;
continue;
}
uint32_t v1 = ((hi & 0x00FF0000) >> 16) / 2;
uint32_t v2 = ((hi & 0x0000FF00) >> 8) / 2;
uint32_t v3 = (hi & 0x000000FF) / 2;
FVector p1 = FVector(vtx[v1].v.ob[0], vtx[v1].v.ob[1], vtx[v1].v.ob[2]);
FVector p2 = FVector(vtx[v2].v.ob[0], vtx[v2].v.ob[1], vtx[v2].v.ob[2]);
FVector p3 = FVector(vtx[v3].v.ob[0], vtx[v3].v.ob[1], vtx[v3].v.ob[2]);
object->Triangles.push_back({p1, p2, p3});
break;
}
case G_TRI1_OTR: {
if (vtx == NULL) {
ptr++;
continue;
}
// The shift values here are different than the above. No idea why. But it has to be this way.
uint32_t v1 = (lo & 0x0000FFFF);
uint32_t v2 = (hi >> 16);
uint32_t v3 = (hi & 0x0000FFFF);
FVector p1 = FVector(vtx[v1].v.ob[0], vtx[v1].v.ob[1], vtx[v1].v.ob[2]);
FVector p2 = FVector(vtx[v2].v.ob[0], vtx[v2].v.ob[1], vtx[v2].v.ob[2]);
FVector p3 = FVector(vtx[v3].v.ob[0], vtx[v3].v.ob[1], vtx[v3].v.ob[2]);
object->Triangles.push_back({p1, p2, p3});
break;
}
case G_TRI2: {
if (vtx == NULL) {
ptr++;
continue;
}
uint32_t v1 = ((lo & 0x00FF0000) >> 16) / 2;
uint32_t v2 = ((lo & 0x0000FF00) >> 8) / 2;
uint32_t v3 = (lo & 0x000000FF) / 2;
// This is actually triangle 2; vert 1,2,3.
uint32_t v4 = ((hi & 0x00FF0000) >> 16) / 2;
uint32_t v5 = ((hi & 0x0000FF00) >> 8) / 2;
uint32_t v6 = (hi & 0x000000FF) / 2;
FVector p1 = FVector(vtx[v1].v.ob[0], vtx[v1].v.ob[1], vtx[v1].v.ob[2]);
FVector p2 = FVector(vtx[v2].v.ob[0], vtx[v2].v.ob[1], vtx[v2].v.ob[2]);
FVector p3 = FVector(vtx[v3].v.ob[0], vtx[v3].v.ob[1], vtx[v3].v.ob[2]);
FVector p4 = FVector(vtx[v4].v.ob[0], vtx[v4].v.ob[1], vtx[v4].v.ob[2]);
FVector p5 = FVector(vtx[v5].v.ob[0], vtx[v5].v.ob[1], vtx[v5].v.ob[2]);
FVector p6 = FVector(vtx[v6].v.ob[0], vtx[v6].v.ob[1], vtx[v6].v.ob[2]);
object->Triangles.push_back({p1, p2, p3});
object->Triangles.push_back({p4, p5, p6});
break;
}
case G_QUAD: {
if (vtx == NULL) {
ptr++;
continue;
}
uint32_t v1 = ((hi & 0x00FF0000) >> 16) / 2;
uint32_t v2 = ((hi & 0x0000FF00) >> 8) / 2;
uint32_t v3 = (hi & 0x000000FF) / 2;
uint32_t v4 = ((hi & 0xFF000000) >> 24) / 2;
FVector p1 = FVector(vtx[v1].v.ob[0], vtx[v1].v.ob[1], vtx[v1].v.ob[2]);
FVector p2 = FVector(vtx[v2].v.ob[0], vtx[v2].v.ob[1], vtx[v2].v.ob[2]);
FVector p3 = FVector(vtx[v3].v.ob[0], vtx[v3].v.ob[1], vtx[v3].v.ob[2]);
FVector p4 = FVector(vtx[v4].v.ob[0], vtx[v4].v.ob[1], vtx[v4].v.ob[2]);
object->Triangles.push_back({p1, p2, p3});
object->Triangles.push_back({p1, p3, p4});
break;
}
case G_ENDDL:
run = false;
break;
}
ptr++;
}
}
std::unordered_map<GameObject*, std::vector<Vtx>> gDebugObjVtxCache;
// Render a collision model
void DebugCollision(GameObject* obj, FVector pos, IRotator rot, FVector scale, const std::vector<Triangle>& triangles) {
if (obj == NULL || triangles.empty()) {
return;
}
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF);
auto& vtxBuffer = gDebugObjVtxCache[obj];
if (vtxBuffer.empty()) {
for (const auto& tri : triangles) {
vtxBuffer.push_back({(s16)tri.v0.x, (s16)tri.v0.y, (s16)tri.v0.z, 0, {0, 0}, {255, 255, 255, 255}});
vtxBuffer.push_back({(s16)tri.v1.x, (s16)tri.v1.y, (s16)tri.v1.z, 0, {0, 0}, {255, 255, 255, 255}});
vtxBuffer.push_back({(s16)tri.v2.x, (s16)tri.v2.y, (s16)tri.v2.z, 0, {0, 0}, {255, 255, 255, 255}});
}
}
// Setup matrix and render state
Mat4 mtx;
ApplyMatrixTransformations(mtx, pos, rot, scale);
Editor_AddMatrix(mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPSetGeometryMode(gDisplayListHead++, G_FOG);
gDPPipeSync(gDisplayListHead++);
gDPSetCombineMode(gDisplayListHead++, G_CC_PRIMITIVE, G_CC_PRIMITIVE);
gSPTexture(gDisplayListHead++, 0, 0, 0, G_TX_RENDERTILE, G_OFF);
gDPSetRenderMode(gDisplayListHead++, G_RM_FOG_SHADE_A, G_RM_AA_ZB_OPA_SURF2);
uint32_t hash = (uint32_t)((uintptr_t)obj ^ ((uintptr_t)obj >> 16));
u8 r = (hash >> 16) & 0xFF;
u8 g = (hash >> 8) & 0xFF;
u8 b = hash & 0xFF;
gDPSetPrimColor(gDisplayListHead++, 0, 0, r, g, b, 255);
// Render triangles in batches of 3
for (size_t i = 0; i + 2 < vtxBuffer.size(); i += 3) {
gSPVertex(gDisplayListHead++, (uintptr_t)&vtxBuffer[i], 3, 0);
gSP1Triangle(gDisplayListHead++, 0, 1, 2, 0);
}
gSPSetGeometryMode(gDisplayListHead++, G_CULL_BACK | G_ZBUFFER);
}
}
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include <libultraship/libultraship.h>
#include <libultra/gbi.h>
#include "GameObject.h"
#include "EditorMath.h"
/**
* @file Editor Collision
*
* Most actors use cylinder collision.
* Proper vtx intersection tests are necessary for object picking
*
* Therefore, generate a full collision mesh for actors
*/
#define EDITOR_GFX_GET_OPCODE(var) ((uint32_t) ((var) & 0xFF000000))
namespace Editor {
void GenerateCollisionMesh(GameObject* object, Gfx* model, float scale);
void DebugCollision(GameObject* obj, FVector pos, IRotator rot, FVector scale, const std::vector<Triangle>& triangles);
}
+166
View File
@@ -0,0 +1,166 @@
#include <libultraship/libultraship.h>
#include <libultra/gbi.h>
#include "../CoreMath.h"
#include <libultra/types.h>
#include "../World.h"
#include "Editor.h"
#include "Collision.h"
#include "Light.h"
#include "port/Engine.h"
#include <controller/controldevice/controller/mapping/keyboard/KeyboardScancodes.h>
#include <window/Window.h>
#include "engine/actors/Ship.h"
#include "port/Game.h"
extern "C" {
#include "common_structs.h"
#include "main.h"
#include "defines.h"
#include "actors.h"
#include "camera.h"
}
namespace Editor {
int gfx_create_framebuffer(uint32_t width, uint32_t height, uint32_t native_width, uint32_t native_height,
uint8_t resize);
Editor::Editor() {
}
void Editor::Load() {
printf("Editor: Loading Editor...\n");
eObjectPicker.Load();
for (auto& object : eGameObjects) {
GenerateCollisionMesh(object, object->Model, 1.0f);
object->Load();
}
printf("Editor: Loading Complete!\n");
}
void Editor::Tick() {
if (CVarGetInteger("gEditorEnabled", 0) == true) {
bEditorEnabled = true;
} else {
bEditorEnabled = false;
return;
}
auto wnd = GameEngine::Instance->context->GetWindow();
static bool wasMouseDown = false;
static bool isDragging = false;
static Ship::Coords mouseStartPos;
Ship::Coords mousePos = wnd->GetMousePos();
bool isMouseDown = wnd->GetMouseState(Ship::LUS_MOUSE_BTN_LEFT);
eGameObjects.erase(
std::remove_if(eGameObjects.begin(), eGameObjects.end(),
[](const auto& object) { return (*object->DespawnFlag) == object->DespawnValue; }),
eGameObjects.end());
if (isMouseDown && !wasMouseDown) {
// Mouse just pressed (Pressed state)
mouseStartPos = mousePos;
isDragging = false;
}
if (isMouseDown) {
// Mouse is being held (Held state)
int dx = mousePos.x - mouseStartPos.x;
int dy = mousePos.y - mouseStartPos.y;
int dragThreshold = 5; // Adjust as needed
if ((dx * dx + dy * dy) > (dragThreshold * dragThreshold)) {
// Squared distance check to avoid unnecessary sqrt()
isDragging = true;
eObjectPicker.DragHandle(); // Call drag logic
}
}
if (!isMouseDown && wasMouseDown) {
// Mouse just released (Released state)
eObjectPicker.eGizmo.SelectedHandle = Gizmo::GizmoHandle::None;
eObjectPicker.eGizmo.ManipulationStart = true;
if (!isDragging) {
eObjectPicker.SelectObject(eGameObjects);
}
}
wasMouseDown = isMouseDown; // Update previous state
eObjectPicker.Tick();
for (auto& object : eGameObjects) {
object->Tick();
}
}
void Editor::Draw() {
if (!bEditorEnabled) {
return;
}
eObjectPicker.Draw();
for (auto& object : eGameObjects) {
object->Draw();
}
}
GameObject* Editor::AddObject(const char* name, FVector* pos, IRotator* rot, FVector* scale, Gfx* model, float collScale, GameObject::CollisionType collision, float boundingBoxSize, int32_t* despawnFlag, int32_t despawnValue) {
//printf("After AddObj: Pos(%f, %f, %f), Name: %s, Model: %s\n",
// pos->x, pos->y, pos->z, name, model);
if (model != nullptr) {
eGameObjects.push_back(new GameObject(name, pos, rot, scale, model, {}, collision, boundingBoxSize, despawnFlag, despawnValue));
GenerateCollisionMesh(eGameObjects.back(), model, collScale);
} else { // to bounding box or sphere collision
eGameObjects.push_back(new GameObject(name, pos, rot, scale, model, {}, GameObject::CollisionType::BOUNDING_BOX,
10.0f, despawnFlag, despawnValue));
}
return eGameObjects.back();
}
void Editor::AddLight(const char* name, FVector* pos, s8* rot) {
eGameObjects.push_back(new LightObject(name, pos, rot));
}
void Editor::ClearObjects() {
for (auto& obj : eGameObjects) {
delete obj;
}
eGameObjects.clear();
}
void Editor::DeleteObject() {
GameObject* obj = eObjectPicker.eGizmo._selected;
if (obj) {
*obj->DespawnFlag = obj->DespawnValue;
obj = nullptr;
eObjectPicker._selected = nullptr;
}
}
void Editor::ClearMatrixPool() {
EditorMatrix.clear();
}
void Editor::SelectObjectFromSceneExplorer(GameObject* object) {
eObjectPicker._selected = object;
eObjectPicker.eGizmo.Enabled = true;
eObjectPicker.eGizmo.SetGizmoNoCursor(object);
}
void Editor::SetLevelDimensions(s16 minX, s16 maxX, s16 minZ, s16 maxZ, s16 minY, s16 maxY) {
eObjectPicker.eGizmo.dimensions.MinX = minX + -1000;
eObjectPicker.eGizmo.dimensions.MaxX = maxX + 1000;
eObjectPicker.eGizmo.dimensions.MinY = minY + -100;
eObjectPicker.eGizmo.dimensions.MaxY = maxY + 500;
eObjectPicker.eGizmo.dimensions.MinZ = minZ + -1000;
eObjectPicker.eGizmo.dimensions.MaxZ = maxZ + 1000;
}
}
+47
View File
@@ -0,0 +1,47 @@
#ifndef __EDITOR_H__
#define __EDITOR_H__
#include <libultraship/libultraship.h>
#include <libultra/gbi.h>
#include "GameObject.h"
#ifdef __cplusplus
#include "ObjectPicker.h"
namespace Editor {
class ObjectPicker;
class Editor {
public:
Editor();
ObjectPicker eObjectPicker;
std::vector<GameObject*> eGameObjects;
void Tick();
void Draw();
void Load();
GameObject* AddObject(const char* name, FVector* pos, IRotator* rot, FVector* scale, Gfx* model, float collScale, GameObject::CollisionType collision, float boundingBoxSize, int32_t* despawnFlag, int32_t despawnValue);
void AddLight(const char* name, FVector* pos, s8* rot);
void ClearObjects();
void RemoveObject();
void SelectObjectFromSceneExplorer(GameObject* object);
void SetLevelDimensions(s16 minX, s16 maxX, s16 minZ, s16 maxZ, s16 minY, s16 maxY);
void ClearMatrixPool();
void DeleteObject();
bool bEditorEnabled = false;
private:
bool _draw = false;
Vec3f _ray;
s32 Inverse(MtxF* src, MtxF* dest);
void Copy(MtxF* src, MtxF* dest);
void Clear(MtxF* mf);
};
}
#endif
void SetLevelDimensions(s16 minX, s16 maxX, s16 minZ, s16 maxZ, s16 minY, s16 maxY);
#endif // __EDITOR_H__
+427
View File
@@ -0,0 +1,427 @@
#include "EditorMath.h"
#include <libultraship/libultraship.h>
#include "port/Game.h"
#include "port/Engine.h"
#include <libultra/types.h>
#include "GameObject.h"
#include <vector>
#include <limits>
#include <cmath>
extern "C" {
#include "common_structs.h"
#include "main.h"
#include "defines.h"
#include "actors.h"
#include "math_util.h"
#include "math_util_2.h"
#include "camera.h"
}
std::vector<Mtx> EditorMatrix;
bool IsInGameScreen() {
auto wnd = GameEngine::Instance->context->GetWindow();
Ship::Coords mouse = wnd->GetMousePos();
// Define viewport boundaries
int left = gfx_current_game_window_viewport.x;
int right = left + OTRGetGameRenderWidth();
int top = gfx_current_game_window_viewport.y;
int bottom = top + OTRGetGameRenderHeight();
// Check if the mouse is within the game render area
return (mouse.x >= left && mouse.x < right) && (mouse.y >= top && mouse.y < bottom);
}
FVector ScreenRayTrace() {
auto wnd = GameEngine::Instance->context->GetWindow();
Camera* camera = &cameras[0];
Ship::Coords mouse = wnd->GetMousePos();
mouse.x -= gfx_current_game_window_viewport.x;
mouse.y -= gfx_current_game_window_viewport.y;
// Get screen dimensions
uint32_t width = OTRGetGameViewportWidth();
uint32_t height = OTRGetGameViewportHeight();
// Convert mouse to NDS screen coordinates
float x = (2.0f * mouse.x) / width - 1.0f; // Normalized X: -1 to 1
float y = 1.0f - (2.0f * mouse.y) / height; // Normalized Y: -1 to 1
float z = 1.0f; // z is typically 1.0 for the near plane
FVector4 rayClip = {x, y, z, 1.0f};
Mat4 perspMtx;
u16 perspNorm;
guPerspectiveF(perspMtx, &perspNorm, gCameraZoom[0], OTRGetAspectRatio(), CM_GetProps()->NearPersp, CM_GetProps()->FarPersp, 1.0f);
Mat4 inversePerspMtx;
if (InverseMatrix((float*)&perspMtx, (float*)&inversePerspMtx) != 2) {
FVector4 rayEye = MultiplyMatrixVector(inversePerspMtx, (float*)&rayClip.x);
Mat4 lookAtMtx;
guLookAtF(lookAtMtx, camera->pos[0], camera->pos[1], camera->pos[2], camera->lookAt[0], camera->lookAt[1], camera->lookAt[2], camera->up[0], camera->up[1], camera->up[2]);
Mat4 inverseViewMtx;
if (InverseMatrix((float*)&lookAtMtx, (float*)&inverseViewMtx[0][0]) != 2) {
rayEye.w = 0;
FVector4 invRayWor = MultiplyMatrixVector(inverseViewMtx, (float*)&rayEye.x);
FVector direction;
direction = FVector(invRayWor.x, invRayWor.y, invRayWor.z);
return direction;
}
}
return FVector(0, 0, 0);
}
bool QueryCollisionRayActor(Vec3f rayOrigin, Vec3f rayDir, Vec3f actorMin, Vec3f actorMax, float* t) {
float tmin = -FLT_MAX, tmax = FLT_MAX;
for (int i = 0; i < 3; i++) {
if (fabs(rayDir[i]) > 1e-6f) { // Avoid division by zero
float t1 = (actorMin[i] - rayOrigin[i]) / rayDir[i];
float t2 = (actorMax[i] - rayOrigin[i]) / rayDir[i];
if (t1 > t2) { float temp = t1; t1 = t2; t2 = temp; }
tmin = fmax(tmin, t1);
tmax = fmin(tmax, t2);
if (tmax < tmin) return false; // No intersection
} else if (rayOrigin[i] < actorMin[i] || rayOrigin[i] > actorMax[i]) {
return false; // Ray is outside the slab
}
}
*t = tmin; // Distance to first intersection
return true;
}
FVector4 MultiplyMatrixVector(float matrix[4][4], float vector[4]) {
FVector4 result;
float* resultPtr = &result.x;
for (int i = 0; i < 4; i++) {
resultPtr[i] = 0;
for (int j = 0; j < 4; j++) {
resultPtr[i] += matrix[j][i] * vector[j]; // Swap [i][j] → [j][i] for column order
}
}
return result;
}
// https://stackoverflow.com/questions/1148309/inverting-a-4x4-matrix
static bool InverseMatrix(const float m[16], float invOut[16]) {
float inv[16], det;
int i;
inv[0] = m[5] * m[10] * m[15] - m[5] * m[11] * m[14] - m[9] * m[6] * m[15] + m[9] * m[7] * m[14] +
m[13] * m[6] * m[11] - m[13] * m[7] * m[10];
inv[4] = -m[4] * m[10] * m[15] + m[4] * m[11] * m[14] + m[8] * m[6] * m[15] - m[8] * m[7] * m[14] -
m[12] * m[6] * m[11] + m[12] * m[7] * m[10];
inv[8] = m[4] * m[9] * m[15] - m[4] * m[11] * m[13] - m[8] * m[5] * m[15] + m[8] * m[7] * m[13] +
m[12] * m[5] * m[11] - m[12] * m[7] * m[9];
inv[12] = -m[4] * m[9] * m[14] + m[4] * m[10] * m[13] + m[8] * m[5] * m[14] - m[8] * m[6] * m[13] -
m[12] * m[5] * m[10] + m[12] * m[6] * m[9];
inv[1] = -m[1] * m[10] * m[15] + m[1] * m[11] * m[14] + m[9] * m[2] * m[15] - m[9] * m[3] * m[14] -
m[13] * m[2] * m[11] + m[13] * m[3] * m[10];
inv[5] = m[0] * m[10] * m[15] - m[0] * m[11] * m[14] - m[8] * m[2] * m[15] + m[8] * m[3] * m[14] +
m[12] * m[2] * m[11] - m[12] * m[3] * m[10];
inv[9] = -m[0] * m[9] * m[15] + m[0] * m[11] * m[13] + m[8] * m[1] * m[15] - m[8] * m[3] * m[13] -
m[12] * m[1] * m[11] + m[12] * m[3] * m[9];
inv[13] = m[0] * m[9] * m[14] - m[0] * m[10] * m[13] - m[8] * m[1] * m[14] + m[8] * m[2] * m[13] +
m[12] * m[1] * m[10] - m[12] * m[2] * m[9];
inv[2] = m[1] * m[6] * m[15] - m[1] * m[7] * m[14] - m[5] * m[2] * m[15] + m[5] * m[3] * m[14] +
m[13] * m[2] * m[7] - m[13] * m[3] * m[6];
inv[6] = -m[0] * m[6] * m[15] + m[0] * m[7] * m[14] + m[4] * m[2] * m[15] - m[4] * m[3] * m[14] -
m[12] * m[2] * m[7] + m[12] * m[3] * m[6];
inv[10] = m[0] * m[5] * m[15] - m[0] * m[7] * m[13] - m[4] * m[1] * m[15] + m[4] * m[3] * m[13] +
m[12] * m[1] * m[7] - m[12] * m[3] * m[5];
inv[14] = -m[0] * m[5] * m[14] + m[0] * m[6] * m[13] + m[4] * m[1] * m[14] - m[4] * m[2] * m[13] -
m[12] * m[1] * m[6] + m[12] * m[2] * m[5];
inv[3] = -m[1] * m[6] * m[11] + m[1] * m[7] * m[10] + m[5] * m[2] * m[11] - m[5] * m[3] * m[10] -
m[9] * m[2] * m[7] + m[9] * m[3] * m[6];
inv[7] = m[0] * m[6] * m[11] - m[0] * m[7] * m[10] - m[4] * m[2] * m[11] + m[4] * m[3] * m[10] +
m[8] * m[2] * m[7] - m[8] * m[3] * m[6];
inv[11] = -m[0] * m[5] * m[11] + m[0] * m[7] * m[9] + m[4] * m[1] * m[11] - m[4] * m[3] * m[9] -
m[8] * m[1] * m[7] + m[8] * m[3] * m[5];
inv[15] = m[0] * m[5] * m[10] - m[0] * m[6] * m[9] - m[4] * m[1] * m[10] + m[4] * m[2] * m[9] + m[8] * m[1] * m[6] -
m[8] * m[2] * m[5];
det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];
if (det == 0) {
return false;
}
det = 1.0 / det;
for (i = 0; i < 16; i++) {
invOut[i] = inv[i] * det;
}
return true;
}
FVector TransformVecByMatrix(const FVector& vec, const float mtx[4][4]) {
FVector result;
result.x = vec.x * mtx[0][0] + vec.y * mtx[1][0] + vec.z * mtx[2][0] + mtx[3][0];
result.y = vec.x * mtx[0][1] + vec.y * mtx[1][1] + vec.z * mtx[2][1] + mtx[3][1];
result.z = vec.x * mtx[0][2] + vec.y * mtx[1][2] + vec.z * mtx[2][2] + mtx[3][2];
return result;
}
FVector TransformVecDirection(const FVector& dir, const float mtx[4][4]) {
FVector result;
result.x = dir.x * mtx[0][0] + dir.y * mtx[1][0] + dir.z * mtx[2][0];
result.y = dir.x * mtx[0][1] + dir.y * mtx[1][1] + dir.z * mtx[2][1];
result.z = dir.x * mtx[0][2] + dir.y * mtx[1][2] + dir.z * mtx[2][2];
return result;
}
Ray RayToLocalSpace(MtxF mtx, const Ray& ray) {
MtxF inverse;
if (InverseMatrix((float*)&mtx, (float*)&inverse) != 2) {
FVector localRayOrigin = TransformVecByMatrix(ray.Origin, (float(*)[4])&inverse);
FVector localRayDir = TransformVecDirection(ray.Direction, (float(*)[4])&inverse);
return Ray{localRayOrigin, localRayDir.Normalize()};
}
return Ray{}; // Fail. Return empty ray
}
bool IntersectRayTriangle(const Ray& ray, const Triangle& tri, float& t) {
constexpr float EPSILON = 1e-6f;
// Adjust the triangle vertices by the object's position
FVector v0 = tri.v0;
FVector v1 = tri.v1;
FVector v2 = tri.v2;
FVector edge1 = v1 - v0;
FVector edge2 = v2 - v0;
FVector h = ray.Direction.Cross(edge2);
float a = edge1.Dot(h);
if (std::abs(a) < EPSILON)
return false; // Ray is parallel to triangle
float f = 1.0f / a;
FVector s = ray.Origin - v0;
float u = f * s.Dot(h);
if (u < 0.0f || u > 1.0f)
return false;
FVector q = s.Cross(edge1);
float v = f * ray.Direction.Dot(q);
if (v < 0.0f || u + v > 1.0f)
return false;
t = f * edge2.Dot(q);
return t > EPSILON;
}
bool IntersectRayTriangleAndTransform(const Ray& ray, FVector pos, const Triangle& tri, float& t) {
constexpr float EPSILON = 1e-6f;
// Adjust the triangle vertices by the object's position
FVector v0 = tri.v0 + pos;
FVector v1 = tri.v1 + pos;
FVector v2 = tri.v2 + pos;
FVector edge1 = v1 - v0;
FVector edge2 = v2 - v0;
FVector h = ray.Direction.Cross(edge2);
float a = edge1.Dot(h);
if (std::abs(a) < EPSILON)
return false; // Ray is parallel to triangle
float f = 1.0f / a;
FVector s = ray.Origin - v0;
float u = f * s.Dot(h);
if (u < 0.0f || u > 1.0f)
return false;
FVector q = s.Cross(edge1);
float v = f * ray.Direction.Dot(q);
if (v < 0.0f || u + v > 1.0f)
return false;
t = f * edge2.Dot(q);
return t > EPSILON;
}
std::optional<FVector> QueryHandleIntersection(MtxF mtx, Ray ray, const Triangle& tri) {
float t;
Ray localRay = RayToLocalSpace(mtx, ray);
if (IntersectRayTriangle(localRay, tri, t)) {
FVector localClickPosition = localRay.Origin + localRay.Direction * t;
FVector worldClickPosition = TransformVecByMatrix(localClickPosition, (float(*)[4])&mtx);
return worldClickPosition; // Stop checking objects if we selected a Gizmo handle
}
return std::nullopt;
}
bool IntersectRaySphere(const Ray& ray, const FVector& sphereCenter, float radius, float& t) {
const float EPSILON = 1e-6f;
// Vector from ray origin to sphere center
FVector oc = ray.Origin - sphereCenter;
// Quadratic equation coefficients
float a = ray.Direction.Dot(ray.Direction);
float b = 2.0f * oc.Dot(ray.Direction);
float c = oc.Dot(oc) - (radius * radius);
// Compute discriminant
float discriminant = (b * b) - (4 * a * c);
// No intersection if discriminant is negative
if (discriminant < 0) {
return false;
}
// Compute nearest intersection point
float sqrtD = sqrtf(discriminant);
float t0 = (-b - sqrtD) / (2.0f * a);
float t1 = (-b + sqrtD) / (2.0f * a);
// Select the closest valid intersection
if (t0 > EPSILON) {
t = t0;
return true;
} else if (t1 > EPSILON) {
t = t1;
return true;
}
return false; // Sphere is behind the ray origin
}
// bool FindClosestObject(const Ray& ray, const std::vector<GameObject*>& objects, GameObject* outObject, float& outDistance) {
// float closestDist = std::numeric_limits<float>::max();
// bool found = false;
// for (const auto& obj : objects) {
// for (const auto& tri : obj.Triangles) {
// float t;
// if (IntersectRayTriangle(ray, tri, *obj.Pos, t) && t < closestDist) {
// closestDist = t;
// outObject = obj;
// found = true;
// }
// }
// }
// if (found) {
// outDistance = closestDist;
// return true;
// }
// return false;
// }
// Transform a matrix to a matrix identity
void Editor_MatrixIdentity(Mat4 mtx) {
register s32 i;
register s32 k;
for (i = 0; i < 4; i++) {
for (k = 0; k < 4; k++) {
mtx[i][k] = (i == k) ? 1.0f : 0.0f;
}
}
}
void Editor_AddMatrix(Mat4 mtx, int32_t flags) {
EditorMatrix.emplace_back();
guMtxF2L(mtx, &EditorMatrix.back());
gSPMatrix(gDisplayListHead++, &EditorMatrix.back(), flags);
}
float CalculateAngle(const FVector& start, const FVector& end) {
float dot = start.Dot(end);
float magStart = start.Magnitude();
float magEnd = end.Magnitude();
float cosAngle = dot / (magStart * magEnd);
cosAngle = std::min(1.0f, std::max(-1.0f, cosAngle));
return acos(cosAngle);
}
void SetDirectionFromRotator(IRotator rot, s8 direction[3]) {
float yaw = (rot.yaw) * (M_PI / 32768.0f); // Convert from n64 binary angles 0-0xFFFF 0-360 degrees to radians
float pitch = rot.pitch * (M_PI / 32768.0f);
// Compute unit direction vector
float x = cosf(yaw) * cosf(pitch);
float y = -sinf(pitch);
float z = -sinf(yaw) * cosf(pitch);
// Scale into -127 to 127 range (not 128 to avoid overflow)
direction[0] = static_cast<s8>(x * 127.0f);
direction[1] = static_cast<s8>(y * 127.0f);
direction[2] = static_cast<s8>(z * 127.0f);
//printf("Light dir %d %d %d (from rot 0x%X 0x%X 0x%X)\n", direction[0], direction[1], direction[2], rotator[0], rotator[1], rotator[2]);
}
void SetRotatorFromDirection(FVector direction, IRotator* rot) {
// Compute pitch (inverse of -sinf(pitch))
float pitch = -asinf(direction.y);
// Compute yaw (inverse of cosf(yaw) * cosf(pitch))
float yaw = atan2f(-direction.z, direction.x);
// Convert back to N64 angles (0-0xFFFF range)
rot->pitch = (s16)(pitch * (32768.0f / M_PI));
rot->yaw = (s16)(yaw * (32768.0f / M_PI));
rot->roll = 0; // Assume no roll, since it's undefined from direction alone
}
FVector GetPositionAheadOfCamera(f32 dist) {
FVector pos = FVector(cameras[0].pos[0], cameras[0].pos[1], cameras[0].pos[2]);
f32 pitch = (cameras[0].rot[2] / 65535.0f) * 360.0f;
f32 yaw = (cameras[0].rot[1] / 65535.0f) * 360.0f;
// Convert degrees to radians
pitch = pitch * M_PI / 180.0f;
yaw = yaw * M_PI / 180.0f;
// Compute forward vector
FVector forward(
-sinf(yaw), // X
-sinf(pitch), // Y
cosf(yaw) // Z (vertical component)
);
// Move 1000 units forward from the camera position
return pos + (forward * dist);
}
+58
View File
@@ -0,0 +1,58 @@
#pragma once
#include <libultraship/libultraship.h>
#include <libultra/gbi.h>
#include <libultra/types.h>
#include "../CoreMath.h"
#include <vector>
#include "GameObject.h"
extern "C" {
#include "common_structs.h"
}
extern std::vector<Mtx> EditorMatrix;
struct Ray {
FVector Origin;
FVector Direction;
};
struct Triangle {
FVector v0, v1, v2;
};
/**
* Projects 2D cursor into the game world
*
* @return FVector ray direction
*
* ray.x = camera->pos[0] + direction.x * length;
* ray.y = camera->pos[1] + direction.y * length;
* ray.z = camera->pos[2] + direction.z * length;
*/
bool IsInGameScreen();
FVector ScreenRayTrace();
bool QueryCollisionRayActor(Vec3f rayOrigin, Vec3f rayDir, Vec3f actorMin, Vec3f actorMax, float* t);
FVector4 MultiplyMatrixVector(float matrix[4][4], float vector[4]);
static bool InverseMatrix(const float m[16], float invOut[16]);
void Copy(MtxF* src, MtxF* dest);
void Clear(MtxF* mf);
FVector TransformVecByMatrix(const FVector& vec, const float mtx[4][4]);
FVector TransformVecDirection(const FVector& dir, const float mtx[4][4]);
Ray RayToLocalSpace(MtxF mtx, const Ray& ray);
bool IntersectRayTriangle(const Ray& ray, const Triangle& tri, float& t); // Uses local space not global space.
bool IntersectRayTriangleAndTransform(const Ray& ray, FVector pos, const Triangle& tri, float& t); // Uses global space because no access to mtx
bool IntersectRaySphere(const Ray& ray, const FVector& sphereCenter, float radius, float& t);
/**
* optional used here so we can check for successful query and return the click position
*/
std::optional<FVector> QueryHandleIntersection(MtxF mtx, Ray ray, const Triangle& tri);
void Editor_MatrixIdentity(Mat4 mtx);
void Editor_AddMatrix(Mat4 mtx, int32_t flags);
float CalculateAngle(const FVector& start, const FVector& end);
void SetDirectionFromRotator(IRotator rot, s8 direction[3]);
void SetRotatorFromDirection(FVector direction, IRotator* rot);
FVector GetPositionAheadOfCamera(f32 dist);
+30
View File
@@ -0,0 +1,30 @@
#include <libultraship/libultraship.h>
#include "GameObject.h"
namespace Editor {
GameObject::GameObject(const char* name, FVector* pos, IRotator* rot, FVector* scale, Gfx* model, std::vector<Triangle> triangles, CollisionType collision, float boundingBoxSize, int32_t* despawnFlag, int32_t despawnValue) {
Name = name;
Pos = pos;
Rot = rot;
Scale = scale;
Model = model;
Triangles = triangles;
Collision = collision;
BoundingBoxSize = boundingBoxSize;
DespawnFlag = despawnFlag;
DespawnValue = despawnValue;
}
GameObject::GameObject(FVector* pos, Vec3s* rot) {
//Pos = pos;
//Rot = rot;
}
GameObject::GameObject() {};
void GameObject::Draw(){};
void GameObject::Tick(){};
} // namespace Editor
+44
View File
@@ -0,0 +1,44 @@
#pragma once
#include <libultraship/libultraship.h>
#include <libultra/gbi.h>
#include <libultra/types.h>
#include "../CoreMath.h"
#include "EditorMath.h"
#include <vector>
extern "C" {
#include "common_structs.h"
}
struct Triangle;
namespace Editor {
class GameObject {
public:
enum class CollisionType {
VTX_INTERSECT,
BOUNDING_BOX,
BOUNDING_SPHERE
};
GameObject(const char* name, FVector* pos, IRotator* rot, FVector* scale, Gfx* model, std::vector<Triangle> triangles, CollisionType collision, float boundingBoxSize, int32_t* despawnFlag, int32_t despawnValue);
GameObject(FVector* pos, Vec3s* rot);
GameObject();
virtual void Tick();
virtual void Draw();
virtual void Load() {};
const char* Name;
FVector* Pos;
IRotator* Rot;
FVector* Scale;
Gfx* Model;
std::vector<Triangle> Triangles;
CollisionType Collision;
float BoundingBoxSize;
int32_t* DespawnFlag;
int32_t DespawnValue;
};
}
+348
View File
@@ -0,0 +1,348 @@
#include <libultraship/libultraship.h>
#include <libultra/gbi.h>
#include "../CoreMath.h"
#include <libultra/types.h>
#include "../World.h"
#include "EditorMath.h"
#include "Gizmo.h"
#include "Collision.h"
#include "port/Engine.h"
#include <controller/controldevice/controller/mapping/keyboard/KeyboardScancodes.h>
#include <window/Window.h>
#include "engine/actors/Ship.h"
#include "port/Game.h"
#include "Handles.h"
extern "C" {
#include "common_structs.h"
#include "main.h"
#include "actors.h"
#include "camera.h"
#include "src/racing/collision.h"
#include "math_util.h"
}
namespace Editor {
void Gizmo::Load() {
/* Translate handle collision */
RedCollision.Pos = &Pos;
RedCollision.Model = (Gfx*)"__OTR__editor/gizmo/translate_handle_red";
GreenCollision.Pos = &Pos;
GreenCollision.Model = (Gfx*)"__OTR__editor/gizmo/translate_handle_green";
BlueCollision.Pos = &Pos;
BlueCollision.Model = (Gfx*)"__OTR__editor/gizmo/translate_handle_blue";
/* Rotate handle collision */
RedRotateCollision.Pos = &Pos;
RedRotateCollision.Model = (Gfx*)"__OTR__editor/gizmo/rot_handle_red";
GreenRotateCollision.Pos = &Pos;
GreenRotateCollision.Model = (Gfx*)"__OTR__editor/gizmo/rot_handle_green";
BlueRotateCollision.Pos = &Pos;
BlueRotateCollision.Model = (Gfx*)"__OTR__editor/gizmo/rot_handle_blue";
/* Scale handle collision */
RedScaleCollision.Pos = &Pos;
RedScaleCollision.Model = (Gfx*)"__OTR__editor/gizmo/scale_handle_red";
GreenScaleCollision.Pos = &Pos;
GreenScaleCollision.Model = (Gfx*)"__OTR__editor/gizmo/scale_handle_green";
BlueScaleCollision.Pos = &Pos;
BlueScaleCollision.Model = (Gfx*)"__OTR__editor/gizmo/scale_handle_blue";
GenerateCollisionMesh(&RedCollision, (Gfx*)LOAD_ASSET_RAW(RedCollision.Model), 1.0f);
GenerateCollisionMesh(&GreenCollision, (Gfx*)LOAD_ASSET_RAW(GreenCollision.Model), 1.0f);
GenerateCollisionMesh(&BlueCollision, (Gfx*)LOAD_ASSET_RAW(BlueCollision.Model), 1.0f);
GenerateCollisionMesh(&RedRotateCollision, (Gfx*)LOAD_ASSET_RAW(RedRotateCollision.Model), 1.0f);
GenerateCollisionMesh(&GreenRotateCollision, (Gfx*)LOAD_ASSET_RAW(GreenRotateCollision.Model), 1.0f);
GenerateCollisionMesh(&BlueRotateCollision, (Gfx*)LOAD_ASSET_RAW(BlueRotateCollision.Model), 1.0f);
GenerateCollisionMesh(&RedScaleCollision, (Gfx*)LOAD_ASSET_RAW(RedScaleCollision.Model), 1.0f);
GenerateCollisionMesh(&GreenScaleCollision, (Gfx*)LOAD_ASSET_RAW(GreenScaleCollision.Model), 1.0f);
GenerateCollisionMesh(&BlueScaleCollision, (Gfx*)LOAD_ASSET_RAW(BlueScaleCollision.Model), 1.0f);
}
void Gizmo::Tick() {
if (Enabled) {
TranslationMode mode = static_cast<TranslationMode>(CVarGetInteger("eGizmoMode", 0));
switch(mode) {
case TranslationMode::Move:
Gizmo::Translate();
break;
case TranslationMode::Rotate:
Gizmo::Rotate();
break;
case TranslationMode::Scale:
Gizmo::Scale();
break;
}
}
}
// Makes the gizmo visible
void Gizmo::SetGizmo(GameObject* object, Ray ray) {
_selected = object;
_ray = ray.Direction;
Pos = FVector(
object->Pos->x,
object->Pos->y,
object->Pos->z
);
}
void Gizmo::SetGizmoNoCursor(GameObject* object) {
_selected = object;
Pos = FVector(
object->Pos->x,
object->Pos->y,
object->Pos->z
);
}
void Gizmo::Translate() {
static float length = 180.0f; // Default value
// Prevent nullptr exceptions
if (_selected == NULL || _selected->Pos == NULL) {
return;
}
if (Enabled) {
length = sqrt(
pow(_selected->Pos->x - cameras[0].pos[0], 2) +
pow(_selected->Pos->y - cameras[0].pos[1], 2) +
pow(_selected->Pos->z - cameras[0].pos[2], 2)
);
switch(SelectedHandle) {
case GizmoHandle::All_Axis:
_selected->Pos->x = (cameras[0].pos[0] + _ray.x * PickDistance) + _cursorOffset.x;
_selected->Pos->y = (cameras[0].pos[1] + _ray.y * PickDistance) + _cursorOffset.y;
_selected->Pos->z = (cameras[0].pos[2] + _ray.z * PickDistance) + _cursorOffset.z;
if (CVarGetInteger("gEditorSnapToGround", 0) == true) {
_selected->Pos->y = SnapToSurface(_selected->Pos);
}
break;
case GizmoHandle::X_Axis:
_selected->Pos->x = (cameras[0].pos[0] + _ray.x * length) + _cursorOffset.x;
if (CVarGetInteger("gEditorSnapToGround", 0) == true) {
_selected->Pos->y = SnapToSurface(_selected->Pos);
}
break;
case GizmoHandle::Y_Axis:
_selected->Pos->y = (cameras[0].pos[1] + _ray.y * length) + _cursorOffset.y;
break;
case GizmoHandle::Z_Axis:
_selected->Pos->z = (cameras[0].pos[2] + _ray.z * length) + _cursorOffset.z;
if (CVarGetInteger("gEditorSnapToGround", 0) == true) {
_selected->Pos->y = SnapToSurface(_selected->Pos);
}
break;
}
if (CVarGetInteger("gEditorBoundary", 0) == true) {
_selected->Pos->x = MAX(_selected->Pos->x, dimensions.MinX);
_selected->Pos->x = MIN(_selected->Pos->x, dimensions.MaxX);
_selected->Pos->y = MAX(_selected->Pos->y, dimensions.MinY);
_selected->Pos->y = MIN(_selected->Pos->y, dimensions.MaxY);
_selected->Pos->z = MAX(_selected->Pos->z, dimensions.MinZ);
_selected->Pos->z = MIN(_selected->Pos->z, dimensions.MaxZ);
}
Pos = FVector(
_selected->Pos->x,
_selected->Pos->y,
_selected->Pos->z
);
}
}
f32 Gizmo::SnapToSurface(FVector* pos) {
float y;
y = spawn_actor_on_surface(pos->x, 2000.0f, pos->z);
if (y == 3000.0f || y == -3000.0f) {
y = pos->y;
}
return y;
}
void Gizmo::Rotate() {
FVector cam = FVector(cameras[0].pos[0], cameras[0].pos[1], cameras[0].pos[2]);
if (_selected == nullptr || _selected->Rot == nullptr) {
return;
}
// Store initial scale at the beginning of the drag
if (ManipulationStart) {
ManipulationStart = false;
InitialRotation = *_selected->Rot; // Store initial rotation
}
// Initial click position
FVector clickPos = *_selected->Pos - _cursorOffset;
// Calculate difference
FVector diff = (cam + _ray * PickDistance) - clickPos;
// Set rotation sensitivity
diff = diff * 100.0f;
switch (SelectedHandle) {
case GizmoHandle::X_Axis:
_selected->Rot->pitch = (uint16_t)InitialRotation.pitch + diff.x;
break;
case GizmoHandle::Y_Axis:
_selected->Rot->yaw = (uint16_t)InitialRotation.yaw + diff.y;
break;
case GizmoHandle::Z_Axis:
_selected->Rot->roll = (uint16_t)InitialRotation.roll + diff.z;
break;
}
}
void Gizmo::Scale() {
FVector cam = FVector(cameras[0].pos[0], cameras[0].pos[1], cameras[0].pos[2]);
if (_selected == nullptr || _selected->Scale == nullptr) {
return;
}
// Store initial scale at the beginning of the drag
if (ManipulationStart) {
ManipulationStart = false;
InitialScale = *_selected->Scale;
}
// Initial click position
FVector clickPos = *_selected->Pos - _cursorOffset;
// Calculate difference
FVector diff = (cam + _ray * PickDistance) - clickPos;
// Lower scaling sensitivity
diff = diff * 0.01f;
switch (SelectedHandle) {
case GizmoHandle::X_Axis:
_selected->Scale->x = InitialScale.x + -diff.x;
break;
case GizmoHandle::Y_Axis:
_selected->Scale->y = InitialScale.y + diff.y;
break;
case GizmoHandle::Z_Axis:
_selected->Scale->z = InitialScale.z + -diff.z;
break;
case GizmoHandle::All_Axis:
float uniformScale = (diff.x - diff.y - diff.z) / 3.0f;
uniformScale *= 1.8; // Increased sensitivity
_selected->Scale->x = uniformScale;
_selected->Scale->y = uniformScale;
_selected->Scale->z = uniformScale;
break;
}
}
void Gizmo::Draw() {
if (Enabled) {
DrawHandles();
//DebugCollision(&RedCollision, Pos, {0, 0, 0}, {0.05f, 0.05f, 0.05f}, RedCollision.Triangles);
//DebugCollision(&BlueCollision, Pos, {90, 0, 0}, {0.05f, 0.05f, 0.05f}, BlueCollision.Triangles);
//DebugCollision(&GreenCollision, Pos, {0, 90, 0}, {0.05f, 0.05f, 0.05f}, GreenCollision.Triangles);
//DebugCollision(&RedRotateCollision, Pos, {0, 0, 0}, {0.15f, 0.15f, 0.15f}, RedRotateCollision.Triangles);
//DebugCollision((uintptr_t)_selected, Pos, BlueRotateCollision.Triangles);
//DebugCollision((uintptr_t)_selected, Pos, GreenRotateCollision.Triangles);
}
}
void Gizmo::DrawHandles() {
Mat4 mainMtx;
Editor_MatrixIdentity((float(*)[4])&Mtx_RedX);
Editor_MatrixIdentity((float(*)[4])&Mtx_GreenY);
Editor_MatrixIdentity((float(*)[4])&Mtx_BlueZ);
const char* blueHandle;
const char* greenHandle;
const char* redHandle;
const char* center = nullptr;
IRotator blueRot;
IRotator greenRot;
IRotator redRot;
FVector scale = {0.05f, 0.05f, 0.05f};
switch(static_cast<TranslationMode>(CVarGetInteger("eGizmoMode", 0))) {
case TranslationMode::Move:
center = "__OTR__editor/gizmo/center_handle";
blueHandle = "__OTR__editor/gizmo/translate_handle_blue";
greenHandle = "__OTR__editor/gizmo/translate_handle_green";
redHandle = "__OTR__editor/gizmo/translate_handle_red";
_gizmoOffset = 8.0f;
greenRot = {0, 90, 0};
blueRot = {90, 0, 0};
scale = {0.3, 0.3, 0.3};
break;
case TranslationMode::Rotate:
center = nullptr; // No All_Axis drag button for Rotation
blueHandle = "__OTR__editor/gizmo/rot_handle_blue";
greenHandle = "__OTR__editor/gizmo/rot_handle_green";
redHandle = "__OTR__editor/gizmo/rot_handle_red";
_gizmoOffset = 0.0f;
scale = {0.15f, 0.15f, 0.15f};
break;
case TranslationMode::Scale:
center = "__OTR__editor/gizmo/center_handle";
blueHandle = "__OTR__editor/gizmo/scale_handle_blue";
greenHandle = "__OTR__editor/gizmo/scale_handle_green";
redHandle = "__OTR__editor/gizmo/scale_handle_red";
_gizmoOffset = 8.0f;
greenRot = {0, 90, 0};
blueRot = {90, 0, 0};
scale = {0.05f, 0.05f, 0.05f};
break;
}
ApplyMatrixTransformations(mainMtx, Pos, Rot, {1, 1, 1});
Editor_AddMatrix(mainMtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
if (center) {
Mat4 CenterMtx;
Editor_MatrixIdentity(CenterMtx);
// Calculate camera-to-object distance
FVector cameraDir = FVector(Pos.x - cameras[0].pos[0], Pos.y - cameras[0].pos[1], Pos.z - cameras[0].pos[2]);
cameraDir = cameraDir.Normalize();
IRotator centerRot;
SetRotatorFromDirection(cameraDir, &centerRot);
centerRot.pitch += 0x4000; // Align mesh to face camera since it was not exported facing the correct direction
centerRot.yaw += 0x4000;
ApplyMatrixTransformations(CenterMtx, Pos, centerRot, FVector(0.06f, 0.06f, 0.06f));
Editor_AddMatrix(CenterMtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(gDisplayListHead++, (Gfx*)center);
}
ApplyMatrixTransformations((float(*)[4])&Mtx_RedX, FVector(Pos.x, Pos.y, Pos.z - _gizmoOffset), Rot, scale);
Editor_AddMatrix((float(*)[4])&Mtx_RedX, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(gDisplayListHead++, (Gfx*)redHandle);
ApplyMatrixTransformations((float(*)[4])&Mtx_GreenY, FVector(Pos.x - _gizmoOffset, Pos.y, Pos.z), greenRot, scale);
Editor_AddMatrix((float(*)[4])&Mtx_GreenY, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(gDisplayListHead++, (Gfx*)greenHandle);
ApplyMatrixTransformations((float(*)[4])&Mtx_BlueZ, FVector(Pos.x, Pos.y + _gizmoOffset, Pos.z), blueRot, scale);
Editor_AddMatrix((float(*)[4])&Mtx_BlueZ, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(gDisplayListHead++, (Gfx*)blueHandle);
}
}
+85
View File
@@ -0,0 +1,85 @@
#pragma once
#include <libultraship/libultraship.h>
#include <libultra/gbi.h>
#include "Collision.h"
#include "GameObject.h"
namespace Editor {
class Gizmo {
public:
enum class GizmoHandle {
None,
All_Axis,
X_Axis,
Y_Axis,
Z_Axis
};
enum class TranslationMode {
Move,
Rotate,
Scale
};
void Tick();
void Draw();
void Load();
void SetGizmo(GameObject* object, Ray ray);
void SetGizmoNoCursor(GameObject* object); // Used for scene explorer selection
void Translate();
void Rotate();
void Scale();
void DrawHandles();
f32 SnapToSurface(FVector* pos);
struct TrackDimensions {
s16 MinX = -10000;
s16 MaxX = 10000;
s16 MinY = -3000;
s16 MaxY = 3000;
s16 MinZ = -10000;
s16 MaxZ = 10000;
};
TrackDimensions dimensions;
bool Enabled;
bool ManipulationStart = true;
FVector InitialScale = {1, 1, 1};
IRotator InitialRotation = {0, 0, 0};
GizmoHandle SelectedHandle;
GameObject RedCollision;
GameObject GreenCollision;
GameObject BlueCollision;
GameObject RedRotateCollision;
GameObject GreenRotateCollision;
GameObject BlueRotateCollision;
GameObject RedScaleCollision;
GameObject GreenScaleCollision;
GameObject BlueScaleCollision;
MtxF Mtx_RedX;
MtxF Mtx_GreenY;
MtxF Mtx_BlueZ;
FVector Pos; // Global scene view
IRotator Rot = {0, 0, 0};
float AllAxisRadius = 3.0f; // Free move selection radius
float PickDistance;
FVector _cursorOffset;
float _gizmoOffset = 8.0f;
float HandleSize = 2.0f;
FVector _ray;
GameObject* _selected = nullptr;
private:
bool _draw = false;
};
}
+23
View File
@@ -0,0 +1,23 @@
#include <libultraship/libultraship.h>
#include <libultra/gbi.h>
#include "Handles.h"
namespace Editor {
Handles::Handles() {
Pos = &pos;
Rot = &rot;
}
void Handles::Load() {
}
void Handles::Tick() {
}
void Handles::Draw() {
}
}
+19
View File
@@ -0,0 +1,19 @@
#pragma once
#include <libultraship/libultraship.h>
#include <libultra/gbi.h>
#include "GameObject.h"
namespace Editor {
class Handles : public GameObject {
Handles();
virtual void Tick() override;
virtual void Draw() override;
virtual void Load() override;
FVector pos;
IRotator rot;
};
}
+84
View File
@@ -0,0 +1,84 @@
#include <iostream>
#include <libultraship/libultraship.h>
#include <libultra/gbi.h>
#include "../CoreMath.h"
#include <libultra/types.h>
#include "../World.h"
#include "Light.h"
#include "port/Engine.h"
#include <controller/controldevice/controller/mapping/keyboard/KeyboardScancodes.h>
#include <window/Window.h>
#include "engine/actors/Ship.h"
#include "port/Game.h"
#include "Gizmo.h"
#include "EditorMath.h"
extern "C" {
#include "common_structs.h"
#include "main.h"
#include "defines.h"
#include "actors.h"
#include "camera.h"
#include "math_util.h"
#include "math_util_2.h"
}
namespace Editor {
size_t LightObject::NumLights = 0;
LightObject::LightObject(const char* name, FVector* pos, s8* direction) : GameObject(nullptr, nullptr) {
Name = name;
Pos = &LightPos;
Rot = &LightRot;
Scale = &LightScale;
DespawnFlag = &_despawnFlag;
DespawnValue = -1;
Direction = direction;
Collision = CollisionType::BOUNDING_BOX;
BoundingBoxSize = 4.0f;
NumLights += 1;
}
void LightObject::Load() {
}
void LightObject::Tick() {
SetDirectionFromRotator(*Rot, Direction);
}
void LightObject::Draw() {
Mat4 mtx_sun;
Editor_MatrixIdentity(mtx_sun);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
// Calculate camera-to-object distance
FVector cameraDir = FVector(LightPos.x - cameras[0].pos[0], LightPos.y - cameras[0].pos[1], LightPos.z - cameras[0].pos[2]);
cameraDir = cameraDir.Normalize();
IRotator centerRot;
SetRotatorFromDirection(cameraDir, &centerRot);
// Account for object not facing the correct direction when exported
centerRot.yaw += 0x4000;
ApplyMatrixTransformations(mtx_sun, LightPos, centerRot, LightScale);
Editor_AddMatrix(mtx_sun, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(gDisplayListHead++, sun_LightModel_mesh);
// Draw Arrow
Mat4 mtx_arrow;
IRotator rot = LightRot;
rot.yaw += 0x4000;
ApplyMatrixTransformations(mtx_arrow, LightPos, rot, LightScale);
Editor_AddMatrix(mtx_arrow, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(gDisplayListHead++, (Gfx*)"__OTR__editor/light/sun_arrow");
}
}
File diff suppressed because it is too large Load Diff
+207
View File
@@ -0,0 +1,207 @@
#include <libultraship/libultraship.h>
#include <libultra/gbi.h>
#include "../CoreMath.h"
#include <libultra/types.h>
#include "../World.h"
#include "ObjectPicker.h"
#include "port/Engine.h"
#include <controller/controldevice/controller/mapping/keyboard/KeyboardScancodes.h>
#include <window/Window.h>
#include "engine/actors/Ship.h"
#include "port/Game.h"
#include "Gizmo.h"
#include "EditorMath.h"
extern "C" {
#include "common_structs.h"
#include "main.h"
#include "defines.h"
#include "actors.h"
#include "camera.h"
}
namespace Editor {
void ObjectPicker::Load() {
eGizmo.Load();
}
void ObjectPicker::Tick() {
}
void ObjectPicker::SelectObject(std::vector<GameObject*> objects) {
Ray ray;
ray.Origin = FVector(cameras[0].pos[0], cameras[0].pos[1], cameras[0].pos[2]);
// This allows selection of objects in the scene explorer.
// Otherwise this would still run when selecting buttons in editor windows.
if (IsInGameScreen()) {
ray.Direction = ScreenRayTrace();
ObjectPicker::FindObject(ray, objects);
if (_selected != nullptr) {
eGizmo.SetGizmo(_selected, ray);
eGizmo.Enabled = true;
} else {
//eGizmo.Disable();
eGizmo.Enabled = false;
eGizmo._selected = nullptr;
}
}
}
void ObjectPicker::DragHandle() {
Ray ray;
ray.Origin = FVector(cameras[0].pos[0], cameras[0].pos[1], cameras[0].pos[2]);
ray.Direction = ScreenRayTrace();
// Skip if a drag is already in progress
if (eGizmo.SelectedHandle != Gizmo::GizmoHandle::None) {
eGizmo._ray = ray.Direction;
eGizmo.Tick();
return;
}
// Is the gizmo being dragged?
if (!eGizmo.Enabled) { return; }
float closestDistance = FLT_MAX;
std::optional<FVector> closestClickPos;
Gizmo::GizmoHandle closestHandle = Gizmo::GizmoHandle::None;
// All axis grab. Not used in rotate mode rotate
if (static_cast<Gizmo::TranslationMode>(CVarGetInteger("eGizmoMode", 0)) != Gizmo::TranslationMode::Rotate) {
float t;
if (IntersectRaySphere(ray, eGizmo.Pos, eGizmo.AllAxisRadius, t)) {
if (t < closestDistance) {
closestDistance = t;
closestClickPos = ray.Origin + ray.Direction * t;
closestHandle = Gizmo::GizmoHandle::All_Axis;
}
}
}
// Arrow handles
auto tryHandle = [&](Gizmo::GizmoHandle handle, MtxF mtx, const std::vector<Triangle>& tris) {
for (const auto& tri : tris) {
if (auto clickPos = QueryHandleIntersection(mtx, ray, tri)) {
float dist = (*clickPos - ray.Origin).Magnitude();
if (dist < closestDistance) {
closestDistance = dist;
closestClickPos = *clickPos;
closestHandle = handle;
}
}
}
};
switch(static_cast<Gizmo::TranslationMode>(CVarGetInteger("eGizmoMode", 0))) {
case Gizmo::TranslationMode::Move:
tryHandle(Gizmo::GizmoHandle::Z_Axis, eGizmo.Mtx_RedX, eGizmo.RedCollision.Triangles);
tryHandle(Gizmo::GizmoHandle::X_Axis, eGizmo.Mtx_GreenY, eGizmo.GreenCollision.Triangles);
tryHandle(Gizmo::GizmoHandle::Y_Axis, eGizmo.Mtx_BlueZ, eGizmo.BlueCollision.Triangles);
break;
case Gizmo::TranslationMode::Rotate:
tryHandle(Gizmo::GizmoHandle::X_Axis, eGizmo.Mtx_RedX, eGizmo.RedRotateCollision.Triangles);
tryHandle(Gizmo::GizmoHandle::Z_Axis, eGizmo.Mtx_GreenY, eGizmo.GreenRotateCollision.Triangles);
tryHandle(Gizmo::GizmoHandle::Y_Axis, eGizmo.Mtx_BlueZ, eGizmo.BlueRotateCollision.Triangles);
break;
case Gizmo::TranslationMode::Scale:
tryHandle(Gizmo::GizmoHandle::Z_Axis, eGizmo.Mtx_RedX, eGizmo.RedScaleCollision.Triangles);
tryHandle(Gizmo::GizmoHandle::X_Axis, eGizmo.Mtx_GreenY, eGizmo.GreenScaleCollision.Triangles);
tryHandle(Gizmo::GizmoHandle::Y_Axis, eGizmo.Mtx_BlueZ, eGizmo.BlueScaleCollision.Triangles);
break;
}
if (closestHandle != Gizmo::GizmoHandle::None && closestClickPos.has_value()) {
eGizmo.SelectedHandle = closestHandle;
eGizmo._ray = ray.Direction;
eGizmo._cursorOffset = eGizmo.Pos - *closestClickPos;
eGizmo.PickDistance = closestDistance;
}
}
void ObjectPicker::Draw() {
if (_selected != NULL) {
eGizmo.Draw();
}
if (Debug) {
Mat4 CursorMtx;
IRotator rot = IRotator(0,0,0);
FVector scale = FVector(0.1, 0.1, 0.1);
FVector ray = ScreenRayTrace();
float x = (cameras[0].pos[0] + ray.x * 800);
float y = (cameras[0].pos[1] + ray.y * 800);
float z = (cameras[0].pos[2] + ray.z * 800);
ApplyMatrixTransformations((float(*)[4])&CursorMtx, FVector(x, y, z), rot, scale);
Editor_AddMatrix((float(*)[4])&CursorMtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(gDisplayListHead++, (Gfx*)"__OTR__tracks/sphere");
}
}
void ObjectPicker::FindObject(Ray ray, std::vector<GameObject*> objects) {
bool found = false;
GameObject* closestObject = nullptr;
float closestDistance = FLT_MAX;
for (auto& object : objects) {
float boundingBox = object->BoundingBoxSize;
if (boundingBox == 0.0f) {
boundingBox = 2.0f;
}
switch(object->Collision) {
case GameObject::CollisionType::VTX_INTERSECT:
for (const auto& tri : object->Triangles) {
float t;
if (IntersectRayTriangleAndTransform(ray, *object->Pos, tri, t)) {
if (t < closestDistance) {
closestDistance = t;
closestObject = object;
printf("SELECTED OBJECT\n");
}
}
}
break;
case GameObject::CollisionType::BOUNDING_BOX: {
float max = 2.0f;
float min = -2.0f;
Vec3f boxMin = { object->Pos->x + boundingBox * min,
object->Pos->y + boundingBox * min,
object->Pos->z + boundingBox * min };
Vec3f boxMax = { object->Pos->x + boundingBox * max,
object->Pos->y + boundingBox * max,
object->Pos->z + boundingBox * max };
float t;
if (QueryCollisionRayActor(&ray.Origin.x, &ray.Direction.x, boxMin, boxMax, &t)) {
if (t < closestDistance) {
closestDistance = t;
closestObject = object;
printf("FOUND BOUNDING BOX OBJECT\n");
}
break;
}
break;
}
case GameObject::CollisionType::BOUNDING_SPHERE:
printf("Editor::ObjectPicker.cpp Bounding sphere collision type not yet supported\n");
break;
}
}
if (closestObject != nullptr) {
_selected = closestObject;
// printf("FOUND COLLISION %d\n", type);
} else {
// printf("NO COLLISION\n");
_selected = nullptr;
}
}
}

Some files were not shown because too many files have changed in this diff Show More