diff --git a/configure.py b/configure.py index 9509ae3..59c26d2 100644 --- a/configure.py +++ b/configure.py @@ -494,7 +494,7 @@ def MatchingFor(*versions): Object(NonMatching, "ty/source/props/TreasureChest.cpp"), Object(NonMatching, "ty/source/props/TriggerProp.cpp"), Object(NonMatching, "ty/source/props/TumbleWeed.cpp"), - Object(NonMatching, "ty/source/props/TurningPlatform.cpp"), + Object(Matching, "ty/source/props/TurningPlatform.cpp"), Object(NonMatching, "ty/source/props/WarpFlower.cpp"), Object(NonMatching, "ty/source/props/WaterPipe.cpp"), Object(Matching, "ty/source/props/WaterVolume.cpp"), diff --git a/include/common/StdMath.h b/include/common/StdMath.h index 5ad5176..933a2b8 100644 --- a/include/common/StdMath.h +++ b/include/common/StdMath.h @@ -107,7 +107,8 @@ inline float AdjustFloat(float x, float param_2, float t) { // Returns the smallest angle needed for ang1 to reach ang2 // Returns a value between [-PI, PI] inline float GetSmallestAngle(float ang1, float ang2) { - float ang = NormaliseAngle(ang2) - NormaliseAngle(ang1); + ang1 = NormaliseAngle(ang1); + float ang = NormaliseAngle(ang2) - ang1; if (ang > PI) { return ang - (2.0f * PI); diff --git a/include/ty/props/TurningPlatform.h b/include/ty/props/TurningPlatform.h new file mode 100644 index 0000000..6868389 --- /dev/null +++ b/include/ty/props/TurningPlatform.h @@ -0,0 +1,29 @@ +#ifndef TURNINGPLATFORM_H +#define TURNINGPLATFORM_H + +#include "ty/props/Platform.h" +#include "ty/tools.h" + +void TurningPlatform_LoadResources(KromeIni* pIni); + +// A platform that turns to face its next waypoint when hit by a boomerang or activated +struct TurningPlatform : Platform { + float angles[MAX_WAYPOINTS]; // Unofficial: unkD4. Yaw facing each waypoint from the first waypoint + int numAngles; // Unofficial: unk114 + int targetAngle; // Unofficial: unk118 + int currAngle; // Unofficial: unk11C + float turnSpeed; + int turnStartFrame; // Unofficial: unk124 + + static Tools_WayPoints loadPoints; + + virtual bool LoadLine(KromeIniLine* pLine); + virtual void LoadDone(void); + virtual void Reset(void); + virtual void Update(void); + virtual void Message(MKMessage* pMsg); + virtual void Init(GameObjDesc* pDesc); + void TurnToNext(void); +}; + +#endif // TURNINGPLATFORM_H diff --git a/src/ty/source/props/TurningPlatform.cpp b/src/ty/source/props/TurningPlatform.cpp new file mode 100644 index 0000000..58e994f --- /dev/null +++ b/src/ty/source/props/TurningPlatform.cpp @@ -0,0 +1,93 @@ +#include "ty/props/TurningPlatform.h" +#include "ty/GameObjectManager.h" +#include "ty/global.h" +#include "common/StdMath.h" +#include "common/System_GC.h" + +extern "C" double atan2(double, double); + +static ModuleInfo turnPlatformModuleInfo; +Tools_WayPoints TurningPlatform::loadPoints; + +void TurningPlatform_LoadResources(KromeIni* pIni) { // Unofficial: pIni + PlatformDesc defaultTurningPlatformDesc; // Unofficial + defaultTurningPlatformDesc.Init(&turnPlatformModuleInfo, "", "", GOID_Platform, 1); + LoadDescriptors(pIni, "TurningPlatforms", &defaultTurningPlatformDesc); +} + +void TurningPlatform::Init(GameObjDesc* pDesc) { + Platform::Init(pDesc); + loadPoints.Init(); + mCurrRot.Set(0.0f, 0.0f, 0.0f); + targetAngle = 0; + currAngle = 0; + turnStartFrame = -1; + turnSpeed = 0.2f; +} + +bool TurningPlatform::LoadLine(KromeIniLine* pLine) { + return loadPoints.LoadLine(pLine, Tools_WayPoints::LOAD_MODE_1) || + LoadLevel_LoadFloat(pLine, "turnSpeed", &turnSpeed) || + Platform::LoadLine(pLine); +} + +void TurningPlatform::LoadDone(void) { + GetPos()->Copy(&loadPoints.vecs[0]); + GetPos()->w = 1.0f; + + numAngles = loadPoints.unk104 - 1; + + for (int i = 1; i < loadPoints.unk104; i++) { // Unofficial: i + angles[i - 1] = PI2 + (float)atan2(loadPoints.vecs[i].z - GetPos()->z, loadPoints.vecs[i].x - GetPos()->x); + } + + if (numAngles > 0) { + StaticProp::loadInfo.defaultRot.y = angles[0]; + } + + Platform::LoadDone(); +} + +void TurningPlatform::Update(void) { + BeginUpdate(); + UpdateTilt(); + + if (currAngle != targetAngle) { + float delta = GetSmallestAngle(angles[currAngle], angles[targetAngle]); // Unofficial + + float t = (float)(gb.logicGameCount - turnStartFrame) / Abs(gDisplay.fps * (delta / turnSpeed)); // Unofficial: t + t = Clamp(0.0f, t, 1.0f); + + mCurrRot.y = angles[currAngle] + delta * _table_sinf(PI * (0.5f * t)); + + if (t == 1.0f) { + currAngle = targetAngle; + } + } + + EndUpdate(); +} + +void TurningPlatform::Reset(void) { + mCurrRot = mDefaultRot; + pModel->matrices[0].SetRotationPYR(&mCurrRot); + unk58 = NULL; +} + +void TurningPlatform::Message(MKMessage* pMsg) { + switch (pMsg->unk0) { + case MSG_BoomerangMsg: + case MSG_Activate: + if (currAngle == targetAngle) { + TurnToNext(); + } + break; + } + + Platform::Message(pMsg); +} + +void TurningPlatform::TurnToNext(void) { + targetAngle = (targetAngle + 1) % numAngles; + turnStartFrame = gb.logicGameCount; +}