diff --git a/Runtime/World/CScriptActorRotate.cpp b/Runtime/World/CScriptActorRotate.cpp index a1757f0e6..948035bd0 100644 --- a/Runtime/World/CScriptActorRotate.cpp +++ b/Runtime/World/CScriptActorRotate.cpp @@ -1,4 +1,7 @@ #include "CScriptActorRotate.hpp" +#include "CStateManager.hpp" +#include "CScriptPlatform.hpp" +#include "CScriptSpiderBallWaypoint.hpp" #include "TCastTo.hpp" namespace urde @@ -7,11 +10,11 @@ CScriptActorRotate::CScriptActorRotate(TUniqueId uid, const std::string& name, c const zeus::CVector3f& rotation, float f1, bool b1, bool b2, bool active) : CEntity(uid, info, active, name) , x34_rotation(rotation) -, x40_(f1) -, x58_24_(false) -, x58_25_(false) -, x58_26_(b1) -, x58_27_(b2) +, x40_maxTime(f1) +, x58_24_updateRotation(false) +, x58_25_skipSpiderBallWaypoints(false) +, x58_26_updateActors(b1) +, x58_27_updateOnCreation(b2) { } @@ -22,7 +25,139 @@ void CScriptActorRotate::Accept(IVisitor& visitor) void CScriptActorRotate::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + if (msg == EScriptObjectMessage::Activate) + { + CEntity::AcceptScriptMsg(msg, uid, mgr); + return; + } + + if (msg == EScriptObjectMessage::Action || msg == EScriptObjectMessage::Next + || (msg == EScriptObjectMessage::Registered && x58_27_updateOnCreation)) + UpdateActors(msg == EScriptObjectMessage::Next, mgr); + CEntity::AcceptScriptMsg(msg, uid, mgr); } +void CScriptActorRotate::Think(float dt, CStateManager& mgr) +{ + if (x58_24_updateRotation && GetActive()) + { + x44_currentTime += dt; + if (x44_currentTime >= x40_maxTime) + { + x58_24_updateRotation = false; + x44_currentTime = x40_maxTime; + } + + float timeOffset = x44_currentTime / x40_maxTime; + + for (const auto& actorPair : x48_actors) + { + if (TCastToPtr act = mgr.ObjectById(actorPair.first)) + { + zeus::CTransform xf = + zeus::CTransform::RotateX(zeus::degToRad(timeOffset * x34_rotation.x)) * + zeus::CTransform::RotateY(zeus::degToRad(timeOffset * x34_rotation.y)) * + zeus::CTransform::RotateZ(zeus::degToRad(timeOffset * x34_rotation.z)); + act->SetTransform({xf.basis, act->GetTranslation()}); + + if (TCastToPtr plat = mgr.ObjectById(actorPair.first)) + UpdatePlatformRiders(*plat.GetPtr(), xf, mgr); + } + } + + if (x58_24_updateRotation) + { + if (!x58_25_skipSpiderBallWaypoints) + UpdateSpiderBallWaypoints(mgr); + if (x58_26_updateActors) + UpdateActors(false, mgr); + } + } +} + +void CScriptActorRotate::UpdatePlatformRiders(CScriptPlatform& plat, const zeus::CTransform& xf, CStateManager& mgr) +{ + UpdatePlatformRiders(plat.GetX328(), plat, xf, mgr); + UpdatePlatformRiders(plat.GetX338(), plat, xf, mgr); +} + +void CScriptActorRotate::UpdatePlatformRiders(std::vector& riders, CScriptPlatform& plat, + const zeus::CTransform& xf, CStateManager& mgr) +{ + for (SRiders& rider : riders) + { + if (TCastToPtr act = mgr.ObjectById(rider.x0_uid)) + { + zeus::CTransform& riderXf = rider.x8_transform; + act->SetTransform(rider.x8_transform); + act->SetTranslation(act->GetTranslation() + plat.GetTranslation()); + + if (x58_24_updateRotation) + { + riderXf = {act->GetTransform().basis, act->GetTranslation() - plat.GetTranslation()}; + + if (TCastToPtr wp = act.GetPtr()) + x58_25_skipSpiderBallWaypoints = true; + } + + if (TCastToPtr plat2 = mgr.ObjectById(rider.x0_uid)) + UpdatePlatformRiders(*plat2.GetPtr(), xf, mgr); + } + } +} + +void CScriptActorRotate::UpdateActors(bool next, CStateManager& mgr) +{ + if (x58_24_updateRotation) + return; + + x48_actors.clear(); + + for (const SConnection& conn : x20_conns) + { + if (conn.x0_state == EScriptObjectState::Play && conn.x4_msg == EScriptObjectMessage::Play) + { + auto search = mgr.GetIdListForScript(conn.x8_objId); + for (auto it = search.first ; it != search.second ; ++it) + { + if (TCastToPtr act = mgr.ObjectById(it->second)) + x48_actors[it->second] = act->GetTransform().getRotation(); + } + } + } + + SendScriptMsgs(EScriptObjectState::Play, mgr, EScriptObjectMessage::None); + + if (!x48_actors.empty()) + { + x58_24_updateRotation = true; + x44_currentTime = (next ? 0.f : x40_maxTime); + } +} + +void CScriptActorRotate::UpdateSpiderBallWaypoints(CStateManager& mgr) +{ + rstl::prereserved_vector waypointIds; + CObjectList& objectList = mgr.GetAllObjectList(); + for (CEntity* ent : objectList) + { + if (TCastToPtr wp = ent) + waypointIds.push_back(wp->GetUniqueId()); + } + + for (const TUniqueId& uid : waypointIds) + { + CScriptSpiderBallWaypoint* wp = static_cast(mgr.ObjectById(uid)); + if (wp) + { +#if 0 + wp->sub_801187B4(mgr); + wp->xe4_27_ = true; +#endif + } + } + + x58_25_skipSpiderBallWaypoints = false; +} } diff --git a/Runtime/World/CScriptActorRotate.hpp b/Runtime/World/CScriptActorRotate.hpp index f26f469f3..c098461d4 100644 --- a/Runtime/World/CScriptActorRotate.hpp +++ b/Runtime/World/CScriptActorRotate.hpp @@ -6,32 +6,42 @@ namespace urde { +struct SRiders; +class CScriptPlatform; class CScriptActorRotate : public CEntity { zeus::CVector3f x34_rotation; - float x40_; - float x44_; + float x40_maxTime; + float x44_currentTime; std::map x48_actors; union { struct { - bool x58_24_ : 1; - bool x58_25_ : 1; - bool x58_26_ : 1; - bool x58_27_ : 1; + bool x58_24_updateRotation : 1; + bool x58_25_skipSpiderBallWaypoints : 1; + bool x58_26_updateActors : 1; + bool x58_27_updateOnCreation : 1; }; u32 dummy = 0; }; + void UpdateActors(bool, CStateManager&); + void UpdateSpiderBallWaypoints(CStateManager&); + void UpdatePlatformRiders(CScriptPlatform&, const zeus::CTransform&, CStateManager&); + void UpdatePlatformRiders(std::vector&, CScriptPlatform&, + const zeus::CTransform&, CStateManager&); public: CScriptActorRotate(TUniqueId, const std::string&, const CEntityInfo&, const zeus::CVector3f&, float, bool, bool, bool); void Accept(IVisitor& visitor); void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Think(float, CStateManager&); + }; + } #endif // CSCRIPTACTORROTATE_HPP diff --git a/Runtime/World/CScriptPlatform.hpp b/Runtime/World/CScriptPlatform.hpp index e1f2457a5..3b93cd9d7 100644 --- a/Runtime/World/CScriptPlatform.hpp +++ b/Runtime/World/CScriptPlatform.hpp @@ -37,6 +37,8 @@ class CScriptPlatform : public CPhysicsActor rstl::optional_object> x304_treeGroupContainer; std::unique_ptr x314_treeGroup; std::vector x318_riders; + std::vector x328_; + std::vector x338_; float x348_; u32 x34c_; u32 x350_; @@ -66,6 +68,10 @@ public: void Accept(IVisitor& visitor); rstl::optional_object GetTouchBounds() const; bool IsRider(TUniqueId id) const; + std::vector& GetX328() { return x328_; } + const std::vector& GetX328() const { return x328_; } + std::vector& GetX338() { return x338_; } + const std::vector& GetX338() const { return x338_; } }; }