diff --git a/Runtime/Camera/CBallCamera.hpp b/Runtime/Camera/CBallCamera.hpp index 11682b51e..152e44496 100644 --- a/Runtime/Camera/CBallCamera.hpp +++ b/Runtime/Camera/CBallCamera.hpp @@ -18,6 +18,10 @@ public: Four, Five }; + enum class EBallCameraBehaviour + { + + }; private: TUniqueId x3dc_tooCloseActorId = kInvalidUniqueId; float x3e0_ = 10000.f; diff --git a/Runtime/Camera/CCameraManager.cpp b/Runtime/Camera/CCameraManager.cpp index 50cbb1093..1084424a4 100644 --- a/Runtime/Camera/CCameraManager.cpp +++ b/Runtime/Camera/CCameraManager.cpp @@ -1,22 +1,15 @@ #include "CCameraManager.hpp" #include "CCameraShakeData.hpp" #include "CFirstPersonCamera.hpp" -#include "Audio/CSfxManager.hpp" -#include "CGameCamera.hpp" #include "CStateManager.hpp" -#include "Input/CRumbleManager.hpp" #include "World/CScriptWater.hpp" #include "World/CPlayer.hpp" -#include "World/CScriptWater.hpp" -#include "CPlayerState.hpp" #include "GameGlobalObjects.hpp" -#include "Graphics/CGraphics.hpp" -#include "Particle/CGenDescription.hpp" -#include "CObjectList.hpp" #include "TCastTo.hpp" #include "CCinematicCamera.hpp" #include "CBallCamera.hpp" #include "CInterpolationCamera.hpp" +#include "World/CScriptCameraHint.hpp" namespace urde { @@ -219,6 +212,7 @@ float CCameraManager::sub80009148() const void CCameraManager::UpdateCameraHints(float, CStateManager& mgr) { + } void CCameraManager::ThinkCameras(float dt, CStateManager& mgr) @@ -335,4 +329,44 @@ void CCameraManager::RemoveCinemaCamera(TUniqueId uid, CStateManager& mgr) { x4_cineCameras.erase(std::remove(x4_cineCameras.begin(), x4_cineCameras.end(), uid)); } + +void CCameraManager::DeleteCameraHint(TUniqueId id, CStateManager& mgr) +{ + if (TCastToPtr hint = mgr.ObjectById(id)) + { + auto search = std::find_if(x2b0_inactiveCameraHints.begin(), x2b0_inactiveCameraHints.end(), + [id](TUniqueId tid) { return tid == id; }); + if (search == x2b0_inactiveCameraHints.end()) + { + hint->ClearIdList(); + hint->SetInactive(true); + if (x2b0_inactiveCameraHints.size() != 64) + x2b0_inactiveCameraHints.push_back(id); + } + } +} + +void CCameraManager::AddInactiveCameraHint(TUniqueId id, CStateManager& mgr) +{ + if (TCastToPtr hint = mgr.ObjectById(id)) + { + auto search = std::find_if(x2b0_inactiveCameraHints.begin(), x2b0_inactiveCameraHints.end(), + [id](TUniqueId tid) { return tid == id; }); + if (search == x2b0_inactiveCameraHints.end() && + x2b0_inactiveCameraHints.size() != 64) + x2b0_inactiveCameraHints.push_back(id); + } +} + +void CCameraManager::AddActiveCameraHint(TUniqueId id, CStateManager& mgr) +{ + if (TCastToPtr hint = mgr.ObjectById(id)) + { + auto search = std::find_if(x334_activeCameraHints.begin(), x334_activeCameraHints.end(), + [id](TUniqueId tid) { return tid == id; }); + if (search == x334_activeCameraHints.end() && xac_ != 64 && + x334_activeCameraHints.size() != 64) + x334_activeCameraHints.push_back(id); + } +} } diff --git a/Runtime/Camera/CCameraManager.hpp b/Runtime/Camera/CCameraManager.hpp index 09f33517c..7dac5f2e1 100644 --- a/Runtime/Camera/CCameraManager.hpp +++ b/Runtime/Camera/CCameraManager.hpp @@ -57,6 +57,9 @@ class CCameraManager u32 xa8_ = 1000; u32 xac_ = 0; + rstl::reserved_vector x2b0_inactiveCameraHints; + rstl::reserved_vector x334_activeCameraHints; + union { struct @@ -110,7 +113,6 @@ public: CFirstPersonCamera* GetFirstPersonCamera() { return x7c_fpCamera; } CBallCamera* GetBallCamera() { return x80_ballCamera; } - CBallCamera* BallCamera(CStateManager&) const; CGameArea::CAreaFog& Fog() { return x3c_fog; } float sub80009148() const; @@ -131,6 +133,11 @@ public: int GetFluidCounter() const { return x74_fluidCounter; } float GetCameraBobMagnitude() const; bool HasBallCameraInitialPositionHint(CStateManager& mgr) const; + + void DeleteCameraHint(TUniqueId id, CStateManager& mgr); + void AddInactiveCameraHint(TUniqueId id, CStateManager& mgr); + void AddActiveCameraHint(TUniqueId id, CStateManager& mgr); + }; } diff --git a/Runtime/World/CEntity.hpp b/Runtime/World/CEntity.hpp index 75aff72df..25b07f632 100644 --- a/Runtime/World/CEntity.hpp +++ b/Runtime/World/CEntity.hpp @@ -65,6 +65,9 @@ public: TUniqueId GetUniqueId() const {return x8_uid;} TEditorId GetEditorId() const {return xc_editorId;} void SendScriptMsgs(EScriptObjectState state, CStateManager& stateMgr, EScriptObjectMessage msg); + + const std::vector& GetConnectionList() const { return x20_conns; } + std::vector& ConnectionList() { return x20_conns; } }; } diff --git a/Runtime/World/CScriptCameraHint.cpp b/Runtime/World/CScriptCameraHint.cpp index fdcaa783a..41d8630a2 100644 --- a/Runtime/World/CScriptCameraHint.cpp +++ b/Runtime/World/CScriptCameraHint.cpp @@ -1,17 +1,21 @@ #include "CScriptCameraHint.hpp" -#include "Character/CModelData.hpp" #include "CActorParameters.hpp" +#include "CStateManager.hpp" #include "TCastTo.hpp" namespace urde { CScriptCameraHint::CScriptCameraHint(TUniqueId uid, const std::string& name, const CEntityInfo& info, - const zeus::CTransform& xf, bool active, u32, u32, u32, float, float, float, - const zeus::CVector3f&, const zeus::CVector3f&, const zeus::CVector3f&, float, - float, float, float, float, float, float, float, float, float) + const zeus::CTransform& xf, bool active, s32 w1, + CBallCamera::EBallCameraBehaviour behaviour, s32 r4, float f1, + float f2, float f3, const zeus::CVector3f& r6, const zeus::CVector3f& r7, + const zeus::CVector3f& r8, float f4, float f5, float f6, float f7, + float f8, float f9, float f10, float f11, float f12, float f13) : CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::Unknown), - CActorParameters::None(), kInvalidUniqueId) + CActorParameters::None(), kInvalidUniqueId), xe8_w1(w1), + xec_hint(r4, behaviour, f1, f2, f3, r6, r7, r8, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13), + x168_origXf(xf) { } @@ -20,4 +24,114 @@ void CScriptCameraHint::Accept(IVisitor& visitor) visitor.Visit(this); } +void CScriptCameraHint::InitializeInArea(CStateManager& mgr) +{ + x164_delegatedCamera = kInvalidUniqueId; + for (CEntity* e : mgr.GetAllObjectList()) + { + if (TCastToPtr ent = e) + { + for (const SConnection& conn : ent->GetConnectionList()) + { + if (mgr.GetIdForScript(conn.x8_objId) != GetUniqueId()) + continue; + if (conn.x4_msg != EScriptObjectMessage::Increment && + conn.x4_msg != EScriptObjectMessage::Decrement) + continue; + + for (auto it = ent->GetConnectionList().begin() ; it != ent->GetConnectionList().cend() ; ++it) + { + const SConnection& conn2 = *it; + if (conn2.x4_msg != EScriptObjectMessage::Increment && + conn2.x4_msg != EScriptObjectMessage::Decrement) + continue; + TUniqueId id = mgr.GetIdForScript(conn2.x8_objId); + if (TCastToPtr(mgr.ObjectById(id)) || + TCastToPtr(mgr.ObjectById((id)))) + { + ent->ConnectionList().erase(it); + if (x164_delegatedCamera != id) + x164_delegatedCamera = id; + break; + } + } + break; + } + } + } +} + +void CScriptCameraHint::AddHelper(TUniqueId id) +{ + auto search = std::find_if(x150_helpers.begin(), x150_helpers.end(), + [id](TUniqueId tid) { return tid == id; }); + if (search == x150_helpers.end()) + x150_helpers.push_back(id); +} + +void CScriptCameraHint::RemoveHelper(TUniqueId id) +{ + auto search = std::find_if(x150_helpers.begin(), x150_helpers.end(), + [id](TUniqueId tid) { return tid == id; }); + if (search != x150_helpers.end()) + x150_helpers.erase(search); +} + +void CScriptCameraHint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) +{ + switch (msg) + { + case EScriptObjectMessage::Deleted: + case EScriptObjectMessage::Deactivate: + mgr.GetCameraManager()->DeleteCameraHint(GetUniqueId(), mgr); + break; + case EScriptObjectMessage::InitializedInArea: + InitializeInArea(mgr); + break; + default: + break; + } + + if (GetActive()) + { + switch (msg) + { + case EScriptObjectMessage::Increment: + AddHelper(sender); + mgr.GetCameraManager()->AddActiveCameraHint(GetUniqueId(), mgr); + x166_inactive = false; + break; + case EScriptObjectMessage::Decrement: + RemoveHelper(sender); + mgr.GetCameraManager()->AddInactiveCameraHint(GetUniqueId(), mgr); + break; + default: + break; + } + } + + if (msg == EScriptObjectMessage::Follow) + { + if (!GetActive()) + { + if (TCastToConstPtr act = mgr.GetObjectById(sender)) + { + zeus::CVector3f followerToThisFlat = x168_origXf.origin - act->GetTranslation(); + followerToThisFlat.z = 0.f; + if (followerToThisFlat.canBeNormalized()) + followerToThisFlat.normalize(); + else + followerToThisFlat = act->GetTransform().basis[1]; + zeus::CVector3f target = act->GetTranslation() + followerToThisFlat; + target.z = x168_origXf.origin.z + followerToThisFlat.z; + SetTransform(zeus::lookAt(act->GetTranslation(), target)); + } + } + AddHelper(sender); + mgr.GetCameraManager()->AddActiveCameraHint(GetUniqueId(), mgr); + } + + CActor::AcceptScriptMsg(msg, sender, mgr); +} + } diff --git a/Runtime/World/CScriptCameraHint.hpp b/Runtime/World/CScriptCameraHint.hpp index ad1930929..0e797b5db 100644 --- a/Runtime/World/CScriptCameraHint.hpp +++ b/Runtime/World/CScriptCameraHint.hpp @@ -2,18 +2,65 @@ #define __URDE_CSCRIPTCAMERAHINT_HPP__ #include "CActor.hpp" +#include "Camera/CBallCamera.hpp" namespace urde { +class CCameraHint +{ + s32 x4_r4; + CBallCamera::EBallCameraBehaviour x8_behaviour; + float xc_f1; + float x10_f2; + float x14_f3; + zeus::CVector3f x18_r6; + zeus::CVector3f x24_r7; + zeus::CVector3f x30_r8; + float x3c_f4; + float x40_f5; + float x44_f6; + float x48_f7; + float x4c_f8; + float x50_f9; + float x54_f10; + float x58_f11; + float x5c_f12; + float x60_f13; + +public: + CCameraHint(s32 r4, CBallCamera::EBallCameraBehaviour behaviour, float f1, float f2, float f3, + const zeus::CVector3f& r6, const zeus::CVector3f& r7, const zeus::CVector3f& r8, float f4, + float f5, float f6, float f7, float f8, float f9, float f10, float f11, float f12, float f13) + : x4_r4(r4), x8_behaviour(behaviour), xc_f1(f1), x10_f2(f2), x14_f3(f3), x18_r6(r6), x24_r7(r7), + x30_r8(r8), x3c_f4(f4), x40_f5(f5), x44_f6(f6), x48_f7(f7), x4c_f8(f8), x50_f9(f9), x54_f10(f10), + x58_f11(f11), x5c_f12(f12), x60_f13(f13) {} +}; + class CScriptCameraHint : public CActor { + s32 xe8_w1; + CCameraHint xec_hint; + rstl::reserved_vector x150_helpers; + TUniqueId x164_delegatedCamera = kInvalidUniqueId; + bool x166_inactive = false; + zeus::CTransform x168_origXf; + void InitializeInArea(CStateManager& mgr); + void AddHelper(TUniqueId id); + void RemoveHelper(TUniqueId id); public: - CScriptCameraHint(TUniqueId, const std::string& name, const CEntityInfo& info, const zeus::CTransform& xf, bool, - u32, u32, u32, float, float, float, const zeus::CVector3f&, const zeus::CVector3f&, - const zeus::CVector3f&, float, float, float, float, float, float, float, float, float, float); + CScriptCameraHint(TUniqueId, const std::string& name, const CEntityInfo& info, const zeus::CTransform& xf, + bool active, s32 w1, CBallCamera::EBallCameraBehaviour behaviour, s32 r4, float f1, float f2, + float f3, const zeus::CVector3f& r6, const zeus::CVector3f& r7, const zeus::CVector3f& r8, + float f4, float f5, float f6, float f7, float f8, float f9, float f10, float f11, float f12, + float f13); void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr); + + void ClearIdList() { x150_helpers.clear(); } + void SetInactive(bool inactive) { x166_inactive = inactive; } + TUniqueId GetFirstHelper() const { return x150_helpers.empty() ? kInvalidUniqueId : x150_helpers[0]; } }; } diff --git a/Runtime/World/ScriptLoader.cpp b/Runtime/World/ScriptLoader.cpp index ee4e68e16..bc6d97a47 100644 --- a/Runtime/World/ScriptLoader.cpp +++ b/Runtime/World/ScriptLoader.cpp @@ -849,7 +849,7 @@ CEntity* ScriptLoader::LoadCameraHint(CStateManager& mgr, CInputStream& in, int bool active = in.readBool(); u32 w1 = in.readUint32Big(); - u32 w2 = in.readUint32Big(); + auto behaviour = CBallCamera::EBallCameraBehaviour(in.readUint32Big()); u32 pf = LoadParameterFlags(in); pf |= in.readBool() << 6; float f1 = in.readFloatBig(); @@ -880,8 +880,9 @@ CEntity* ScriptLoader::LoadCameraHint(CStateManager& mgr, CInputStream& in, int float f12 = in.readFloatBig(); float f13 = in.readFloatBig(); - return new CScriptCameraHint(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, active, w1, w2, pf, f1, - f2, f3, vec1, vec2, vec3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13); + return new CScriptCameraHint(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, active, w1, + behaviour, pf, f1, f2, f3, vec1, vec2, vec3, f4, f5, f6, f7, f8, f9, f10, + f11, f12, f13); } CEntity* ScriptLoader::LoadPickup(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)