mirror of
https://github.com/HarbourMasters/SpaghettiKart
synced 2026-08-28 01:16:47 -04:00
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:
+27
-2
@@ -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]);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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();
|
||||
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,4 +8,5 @@
|
||||
|
||||
void RunGarbageCollector();
|
||||
void CleanActors();
|
||||
void CleanStaticMeshActors();
|
||||
void CleanObjects();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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; }
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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};
|
||||
};
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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;
|
||||
@@ -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++;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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() { }
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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() { }
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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() {
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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() { }
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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() { }
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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() { }
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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() { }
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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__
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
};
|
||||
}
|
||||
@@ -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, ¢erRot);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
@@ -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, ¢erRot);
|
||||
|
||||
// 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
@@ -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
Reference in New Issue
Block a user