diff --git a/Runtime/CSortedLists.cpp b/Runtime/CSortedLists.cpp index d45c819ca..1a526c08e 100644 --- a/Runtime/CSortedLists.cpp +++ b/Runtime/CSortedLists.cpp @@ -4,6 +4,13 @@ namespace urde { +template +static std::remove_reference_t()[0])>& AccessElement(T& arr, S idx) +{ + assert(std::extent::value > idx && idx >= 0); + return arr[idx]; +} + CSortedListManager::CSortedListManager() { Reset(); @@ -20,17 +27,17 @@ void CSortedListManager::AddToLinkedList(s16 nodeId, s16& headId, s16& tailId) c { if (headId == -1) { - const_cast(x0_nodes[nodeId]).x28_next = headId; + const_cast(AccessElement(x0_nodes, nodeId)).x28_next = headId; headId = nodeId; tailId = nodeId; } else { - if (x0_nodes[nodeId].x28_next != -1) + if (AccessElement(x0_nodes, nodeId).x28_next != -1) return; if (tailId == nodeId) return; - const_cast(x0_nodes[nodeId]).x28_next = headId; + const_cast(AccessElement(x0_nodes, nodeId)).x28_next = headId; headId = nodeId; } } @@ -40,8 +47,8 @@ void CSortedListManager::RemoveFromList(ESortedList list, s16 idx) SSortedList& sl = xb000_sortedLists[u32(list)]; while (idx < sl.x800_size - 1) { - x0_nodes[sl.x0_ids[idx+1]].x1c_selfIdxs[int(list)] = idx; - sl.x0_ids[idx] = sl.x0_ids[idx+1]; + AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + 1)).x1c_selfIdxs[int(list)] = idx; + AccessElement(sl.x0_ids, idx) = AccessElement(sl.x0_ids, idx + 1); ++idx; } --sl.x800_size; @@ -52,22 +59,24 @@ void CSortedListManager::MoveInList(ESortedList list, s16 idx) SSortedList& sl = xb000_sortedLists[int(list)]; while (true) { - if (idx > 0 || - x0_nodes[sl.x0_ids[idx-1]].x4_box[idx] > x0_nodes[sl.x0_ids[idx]].x4_box[idx]) + if (idx > 0 && + AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx - 1)).x4_box[int(list)] > + AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx)).x4_box[int(list)]) { - x0_nodes[sl.x0_ids[idx-1]].x1c_selfIdxs[int(list)] = idx; - x0_nodes[sl.x0_ids[idx]].x1c_selfIdxs[int(list)] = idx - 1; - std::swap(sl.x0_ids[idx], sl.x0_ids[idx-1]); + AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx - 1)).x1c_selfIdxs[int(list)] = idx; + AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx)).x1c_selfIdxs[int(list)] = idx - 1; + std::swap(AccessElement(sl.x0_ids, idx), AccessElement(sl.x0_ids, idx - 1)); --idx; } else { if (idx >= sl.x800_size - 1) return; - if (x0_nodes[sl.x0_ids[idx+1]].x4_box[int(list)] >= x0_nodes[sl.x0_ids[idx]].x4_box[int(list)]) + if (AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + 1)).x4_box[int(list)] >= + AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx)).x4_box[int(list)]) return; - x0_nodes[sl.x0_ids[idx+1]].x1c_selfIdxs[int(list)] = idx + 1; - std::swap(sl.x0_ids[idx], sl.x0_ids[idx+1]); + AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + 1)).x1c_selfIdxs[int(list)] = idx + 1; + std::swap(AccessElement(sl.x0_ids, idx), AccessElement(sl.x0_ids, idx + 1)); } } } @@ -76,14 +85,14 @@ void CSortedListManager::InsertInList(ESortedList list, SNode& node) { SSortedList& sl = xb000_sortedLists[int(list)]; int insIdx = 0; - for (int i=sl.x800_size ; i>0 ;) + for (int i = sl.x800_size ; i > 0 ;) { /* Binary search cycle to find insert index */ - if (x0_nodes[sl.x0_ids[insIdx+i/2]].x4_box[int(list)] < node.x4_box[int(list)]) + if (AccessElement(x0_nodes, AccessElement(sl.x0_ids, insIdx + i / 2)).x4_box[int(list)] < node.x4_box[int(list)]) { /* Upper */ - insIdx += i / 2 + 1; - i -= i / 2 - 1; + insIdx = insIdx + i / 2 + 1; + i = i - i / 2 - 1; } else { @@ -93,14 +102,14 @@ void CSortedListManager::InsertInList(ESortedList list, SNode& node) } /* Shift ids for insert */ - for (int i=sl.x800_size ; i>insIdx ; --i) + for (int i = sl.x800_size ; i > insIdx ; --i) { - x0_nodes[sl.x0_ids[i]].x1c_selfIdxs[int(list)] = i; - sl.x0_ids[i] = sl.x0_ids[i-1]; + AccessElement(x0_nodes, AccessElement(sl.x0_ids, i - 1)).x1c_selfIdxs[int(list)] = i; + AccessElement(sl.x0_ids, i) = AccessElement(sl.x0_ids, i - 1); } /* Do insert */ - sl.x0_ids[insIdx] = node.x0_actor->GetUniqueId().Value(); + AccessElement(sl.x0_ids, insIdx) = node.x0_actor->GetUniqueId().Value(); node.x1c_selfIdxs[int(list)] = insIdx; ++sl.x800_size; } @@ -109,14 +118,14 @@ s16 CSortedListManager::FindInListUpper(ESortedList list, float val) const { const SSortedList& sl = xb000_sortedLists[int(list)]; int idx = 0; - for (int i=sl.x800_size ; i>0 ;) + for (int i = sl.x800_size ; i > 0 ;) { /* Binary search cycle to find index */ - if (!(val < x0_nodes[sl.x0_ids[idx+i/2]].x4_box[int(list)])) + if (!(val < AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + i / 2)).x4_box[int(list)])) { /* Upper */ - idx += i / 2 + 1; - i -= i / 2 - 1; + idx = idx + i / 2 + 1; + i = i - i / 2 - 1; } else { @@ -131,14 +140,14 @@ s16 CSortedListManager::FindInListLower(ESortedList list, float val) const { const SSortedList& sl = xb000_sortedLists[int(list)]; int idx = 0; - for (int i=sl.x800_size ; i>0 ;) + for (int i = sl.x800_size ; i > 0 ;) { /* Binary search cycle to find index */ - if (x0_nodes[sl.x0_ids[idx+i/2]].x4_box[int(list)] < val) + if (AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + i / 2)).x4_box[int(list)] < val) { /* Upper */ - idx += i / 2 + 1; - i -= i / 2 - 1; + idx = idx + i / 2 + 1; + i = i - i / 2 - 1; } else { @@ -187,22 +196,22 @@ s16 CSortedListManager::ConstructIntersectionArray(const zeus::CAABox& aabb) } s16 CSortedListManager::CalculateIntersections(ESortedList la, ESortedList lb, s16 a, s16 b, s16 c, s16 d, - ESortedList slA, ESortedList slB, ESortedList slC, ESortedList slD, - const zeus::CAABox& aabb) + ESortedList slA, ESortedList slB, ESortedList slC, ESortedList slD, + const zeus::CAABox& aabb) { s16 headId = -1; s16 tailId = -1; for (int i=a ; i aabb[int(lb)]) + s16 id = AccessElement(xb000_sortedLists[int(la)].x0_ids, i); + if (AccessElement(x0_nodes, id).x1c_selfIdxs[lb] > aabb[int(lb)]) AddToLinkedList(id, headId, tailId); } } @@ -210,15 +219,15 @@ s16 CSortedListManager::CalculateIntersections(ESortedList la, ESortedList lb, s { for (int i=d ; i aabb[int(slB)] || node.x4_box[int(slB)] < aabb[int(slA)] || node.x4_box[int(slC)] > aabb[int(slD)] || @@ -255,7 +264,7 @@ void CSortedListManager::BuildNearList(rstl::reserved_vector& o s16 id = const_cast(*this).ConstructIntersectionArray(aabb); while (id != -1) { - const SNode& node = x0_nodes[id]; + const SNode& node = AccessElement(x0_nodes, id); if (&actor != node.x0_actor && filter.Passes(node.x0_actor->GetMaterialList()) && node.x0_actor->GetMaterialFilter().Passes(actor.GetMaterialList())) out.push_back(node.x0_actor->GetUniqueId()); @@ -271,7 +280,7 @@ void CSortedListManager::BuildNearList(rstl::reserved_vector& o s16 id = const_cast(*this).ConstructIntersectionArray(aabb); while (id != -1) { - const SNode& node = x0_nodes[id]; + const SNode& node = AccessElement(x0_nodes, id); if (actor != node.x0_actor && filter.Passes(node.x0_actor->GetMaterialList())) out.push_back(node.x0_actor->GetUniqueId()); @@ -282,7 +291,7 @@ void CSortedListManager::BuildNearList(rstl::reserved_vector& o void CSortedListManager::Remove(const CActor* act) { - SNode& node = x0_nodes[act->GetUniqueId().Value()]; + SNode& node = AccessElement(x0_nodes, act->GetUniqueId().Value()); if (!node.x2a_populated) return; @@ -297,7 +306,7 @@ void CSortedListManager::Remove(const CActor* act) void CSortedListManager::Move(const CActor* act, const zeus::CAABox& aabb) { - SNode& node = x0_nodes[act->GetUniqueId().Value()]; + SNode& node = AccessElement(x0_nodes, act->GetUniqueId().Value()); node.x4_box = aabb; MoveInList(ESortedList::MinX, node.x1c_selfIdxs[0]); @@ -310,7 +319,7 @@ void CSortedListManager::Move(const CActor* act, const zeus::CAABox& aabb) void CSortedListManager::Insert(const CActor* act, const zeus::CAABox& aabb) { - SNode& node = x0_nodes[act->GetUniqueId().Value()]; + SNode& node = AccessElement(x0_nodes, act->GetUniqueId().Value()); if (node.x2a_populated) { Move(act, aabb); @@ -331,7 +340,7 @@ bool CSortedListManager::ActorInLists(const CActor* act) const { if (!act) return false; - const SNode& node = x0_nodes[act->GetUniqueId().Value()]; + const SNode& node = AccessElement(x0_nodes, act->GetUniqueId().Value()); return node.x2a_populated; } diff --git a/Runtime/CSortedLists.hpp b/Runtime/CSortedLists.hpp index 3f487f93d..471211bad 100644 --- a/Runtime/CSortedLists.hpp +++ b/Runtime/CSortedLists.hpp @@ -50,7 +50,7 @@ class CSortedListManager s16 FindInListLower(ESortedList, float) const; s16 ConstructIntersectionArray(const zeus::CAABox&); s16 CalculateIntersections(ESortedList, ESortedList, s16, s16, s16, s16, - ESortedList, ESortedList, ESortedList, ESortedList, const zeus::CAABox&); + ESortedList, ESortedList, ESortedList, ESortedList, const zeus::CAABox&); public: CSortedListManager(); void BuildNearList(rstl::reserved_vector&, const zeus::CVector3f&, const zeus::CVector3f&, diff --git a/Runtime/CStateManager.cpp b/Runtime/CStateManager.cpp index 13acf17d9..e49bf5767 100644 --- a/Runtime/CStateManager.cpp +++ b/Runtime/CStateManager.cpp @@ -271,25 +271,25 @@ void CStateManager::UpdateThermalVisor() void CStateManager::RendererDrawCallback(const void* drawable, const void* ctx, int type) { - CStateManager& mgr = reinterpret_cast(ctx); + const CStateManager& mgr = *reinterpret_cast(ctx); switch (type) { case 0: { - CActor& actor = reinterpret_cast(drawable); + const CActor& actor = *reinterpret_cast(drawable); if (actor.xc8_drawnToken == mgr.x8dc_objectDrawToken) break; if (actor.xc6_nextDrawNode != kInvalidUniqueId) mgr.RecursiveDrawTree(actor.xc6_nextDrawNode); actor.Render(mgr); - actor.xc8_drawnToken = mgr.x8dc_objectDrawToken; + const_cast(actor).xc8_drawnToken = mgr.x8dc_objectDrawToken; break; } case 1: - reinterpret_cast(drawable).Render(mgr.x8f0_shadowTex.GetObj()); + reinterpret_cast(drawable)->Render(mgr.x8f0_shadowTex.GetObj()); break; case 2: - reinterpret_cast(drawable).Render(); + reinterpret_cast(drawable)->Render(); break; default: break; } @@ -711,7 +711,7 @@ void CStateManager::DrawWorld() const for (TUniqueId id : x86c_stateManagerContainer->xf370_) if (const CActor* ent = static_cast(GetObjectById(id))) - if (!thermal || ent->xe6_27_renderVisorFlags & 0x2) + if (!thermal || ent->xe6_27_renderVisorFlags & 0x1) ent->Render(*this); bool morphingPlayerVisible = false; @@ -728,7 +728,7 @@ void CStateManager::DrawWorld() const { if (TCastToPtr actor = ent) { - if (!actor->xe7_29_) + if (!actor->xe7_29_actorActive) continue; TUniqueId actorId = actor->GetUniqueId(); if (!thermal && area.LookupPVSUniqueID(actorId) == actorId) @@ -749,9 +749,9 @@ void CStateManager::DrawWorld() const continue; } } - if (!thermal || actor->xe6_27_renderVisorFlags & 0x2) + if (!thermal || actor->xe6_27_renderVisorFlags & 0x1) actor->AddToRenderer(frustum, *this); - if (thermal && actor->xe6_27_renderVisorFlags & 0x4) + if (thermal && actor->xe6_27_renderVisorFlags & 0x2) thermalActorArr[thermalActorCount++] = actor.GetPtr(); } } @@ -787,7 +787,7 @@ void CStateManager::DrawWorld() const CGraphics::SetDepthRange(0.015625f, 0.03125f); for (TUniqueId id : x86c_stateManagerContainer->xf39c_renderLast) if (const CActor* actor = static_cast(GetObjectById(id))) - if (actor->xe6_27_renderVisorFlags & 0x2) + if (actor->xe6_27_renderVisorFlags & 0x1) actor->Render(*this); CGraphics::SetDepthRange(0.125f, 1.f); } @@ -795,7 +795,7 @@ void CStateManager::DrawWorld() const for (TUniqueId id : x86c_stateManagerContainer->xf370_) if (const CActor* actor = static_cast(GetObjectById(id))) - if (actor->xe6_27_renderVisorFlags & 0x4) + if (actor->xe6_27_renderVisorFlags & 0x2) actor->Render(*this); for (int i=areaCount-1 ; i>=0 ; --i) @@ -858,7 +858,7 @@ void CStateManager::DrawWorld() const CGraphics::SetDepthRange(0.015625f, 0.03125f); for (TUniqueId id : x86c_stateManagerContainer->xf39c_renderLast) if (const CActor* actor = static_cast(GetObjectById(id))) - if (actor->xe6_27_renderVisorFlags & 0x4) + if (actor->xe6_27_renderVisorFlags & 0x2) actor->Render(*this); CGraphics::SetDepthRange(0.125f, 1.f); } @@ -943,7 +943,7 @@ void CStateManager::PreRender() { if (TCastToPtr act = ent) { - if (act->GetE7_29()) + if (act->IsActorActive()) { act->CalculateRenderBounds(); act->PreRender(*this, frustum); @@ -2071,7 +2071,7 @@ void CStateManager::CrossTouchActors() continue; rstl::optional_object touchAABB2 = ent2->GetTouchBounds(); - if (!ent2->GetActive() || touchAABB2) + if (!ent2->GetActive() || !touchAABB2) continue; if (visits[ent2->GetUniqueId().Value()]) diff --git a/Runtime/Camera/CCameraManager.cpp b/Runtime/Camera/CCameraManager.cpp index 7b7616581..ebb0aa467 100644 --- a/Runtime/Camera/CCameraManager.cpp +++ b/Runtime/Camera/CCameraManager.cpp @@ -12,6 +12,7 @@ #include "World/CScriptCameraHint.hpp" #include "CPathCamera.hpp" #include "World/CScriptSpindleCamera.hpp" +#include "World/CExplosion.hpp" namespace urde { @@ -80,7 +81,54 @@ int CCameraManager::AddCameraShaker(const CCameraShakeData& data, bool sfx) return x2c_lastShakeId; } -void CCameraManager::AddCinemaCamera(TUniqueId id, CStateManager& stateMgr) { x4_cineCameras.push_back(id); } +void CCameraManager::EnterCinematic(CStateManager& mgr) +{ + mgr.GetPlayer().GetPlayerGun()->CancelFiring(mgr); + mgr.GetPlayer().Stop(mgr); + + for (CEntity* ent : mgr.GetAllObjectList()) + { + if (TCastToPtr explo = ent) + { + mgr.FreeScriptObject(explo->GetUniqueId()); + } + else if (TCastToPtr weap = ent) + { + if (weap->GetActive()) + { + if ((weap->GetAttribField() & CWeapon::EProjectileAttrib::KeepInCinematic) == + CWeapon::EProjectileAttrib::None) + { + if (TCastToConstPtr(mgr.GetObjectById(weap->GetOwnerId())) || + TCastToConstPtr(mgr.GetObjectById(weap->GetOwnerId()))) + mgr.FreeScriptObject(weap->GetUniqueId()); + } + } + } + } +} + +void CCameraManager::AddCinemaCamera(TUniqueId id, CStateManager& stateMgr) +{ + if (x4_cineCameras.empty()) + EnterCinematic(stateMgr); + RemoveCinemaCamera(id, stateMgr); + x4_cineCameras.push_back(id); + if (TCastToPtr cam = stateMgr.ObjectById(id)) + { + if (cam->GetFlags() & 0x4) // into player eye + { + float time = 4.f; + float delayTime = cam->GetDuration() - 4.f; + if (delayTime < 0.f) + { + delayTime = 0.f; + time = cam->GetDuration(); + } + cam->SetFovInterpolation(cam->GetFov(), 55.f, time, delayTime); + } + } +} void CCameraManager::SetInsideFluid(bool val, TUniqueId fluidId) { diff --git a/Runtime/Camera/CCameraManager.hpp b/Runtime/Camera/CCameraManager.hpp index 30c5df11d..be9206b8e 100644 --- a/Runtime/Camera/CCameraManager.hpp +++ b/Runtime/Camera/CCameraManager.hpp @@ -82,6 +82,8 @@ class CCameraManager void SkipBallCameraCinematic(CStateManager& mgr); void ApplyCameraHint(const CScriptCameraHint& hint, CStateManager& mgr); + void EnterCinematic(CStateManager& mgr); + public: CCameraManager(TUniqueId curCameraId=kInvalidUniqueId); diff --git a/Runtime/Camera/CCinematicCamera.cpp b/Runtime/Camera/CCinematicCamera.cpp index 79436b333..07eac2f52 100644 --- a/Runtime/Camera/CCinematicCamera.cpp +++ b/Runtime/Camera/CCinematicCamera.cpp @@ -3,6 +3,9 @@ #include "World/CPlayer.hpp" #include "World/CScriptActor.hpp" #include "TCastTo.hpp" +#include "World/CScriptCameraWaypoint.hpp" +#include "GameGlobalObjects.hpp" +#include "Character/CAnimTreeNode.hpp" namespace urde { @@ -11,7 +14,7 @@ CCinematicCamera::CCinematicCamera(TUniqueId uid, std::string_view name, const C const zeus::CTransform& xf, bool active, float shotDuration, float fovy, float znear, float zfar, float aspect, u32 flags) : CGameCamera(uid, active, name, info, xf, fovy, znear, zfar, aspect, kInvalidUniqueId, flags & 0x20, 0), - x1e8_duration(shotDuration), x1f0_origFovy(fovy), x1fc_(zeus::CQuaternion(xf.basis)), x21c_flags(flags) + x1e8_duration(shotDuration), x1f0_origFovy(fovy), x1fc_origOrientation(zeus::CQuaternion(xf.basis)), x21c_flags(flags) { x220_24_ = false; } @@ -37,12 +40,194 @@ void CCinematicCamera::WasDeactivated(CStateManager& mgr) mgr.GetPlayer().GetMorphBall()->LoadMorphBallModel(mgr); if (x21c_flags & 0x100) mgr.SetCinematicPause(false); - x188_.clear(); - x198_.clear(); - x1a8_.clear(); - x1b8_.clear(); - x1c8_.clear(); - x1d8_.clear(); + x188_viewPoints.clear(); + x198_viewOrientations.clear(); + x1a8_viewPointArrivals.clear(); + x1b8_targets.clear(); + x1c8_targetArrivals.clear(); + x1d8_viewHFovs.clear(); +} + +zeus::CVector3f +CCinematicCamera::GetInterpolatedSplinePoint(const std::vector& points, int& idxOut, float tin) const +{ + if (points.size() > 0) + { + float cycleT = std::fmod(tin, x1e8_duration); + float durPerPoint = x1e8_duration / float(points.size() - 1); + idxOut = int(cycleT / durPerPoint); + float t = (cycleT - idxOut * durPerPoint) / durPerPoint; + + if (points.size() == 1) + return points.front(); + else if (points.size() == 2) + return (points[1] - points[0]) * t + points[0]; + + zeus::CVector3f ptA; + if (idxOut > 0) + ptA = points[idxOut - 1]; + else + ptA = points[0] - (points[1] - points[0]); + + zeus::CVector3f ptB = points[idxOut]; + zeus::CVector3f ptC; + if (idxOut + 1 >= points.size()) + { + const zeus::CVector3f& tmpA = points[points.size() - 1]; + const zeus::CVector3f& tmpB = points[points.size() - 2]; + ptC = tmpA - (tmpB - tmpA); + } + else + { + ptC = points[idxOut + 1]; + } + + zeus::CVector3f ptD; + if (idxOut + 2 >= points.size()) + { + const zeus::CVector3f& tmpA = points[points.size() - 1]; + const zeus::CVector3f& tmpB = points[points.size() - 2]; + ptD = tmpA - (tmpB - tmpA); + } + else + { + ptD = points[idxOut + 2]; + } + + return zeus::getCatmullRomSplinePoint(ptA, ptB, ptC, ptD, t); + } + + return {}; +} + +zeus::CQuaternion +CCinematicCamera::GetInterpolatedOrientation(const std::vector& rotations, float tin) const +{ + if (rotations.size() == 0) + return x1fc_origOrientation; + else if (rotations.size() == 1) + return rotations.front(); + + float cycleT = std::fmod(tin, x1e8_duration); + float durPerPoint = x1e8_duration / float(rotations.size() - 1); + int idx = int(cycleT / durPerPoint); + float t = (cycleT - idx * durPerPoint) / durPerPoint; + return zeus::CQuaternion::slerp(rotations[idx], rotations[idx + 1], t); +} + +float CCinematicCamera::GetInterpolatedHFov(const std::vector& fovs, float tin) const +{ + if (fovs.size() == 0) + return x1f0_origFovy; + else if (fovs.size() == 1) + return fovs.front(); + + float cycleT = std::fmod(tin, x1e8_duration); + float durPerPoint = x1e8_duration / float(fovs.size() - 1); + int idx = int(cycleT / durPerPoint); + float t = (cycleT - idx * durPerPoint) / durPerPoint; + return (fovs[idx + 1] - fovs[idx]) * t + fovs[idx]; +} + +float CCinematicCamera::GetMoveOutofIntoAlpha() const +{ + float startDist = 0.25f + x160_znear; + float endDist = 1.f * startDist; + float deltaMag = (GetTranslation() - x210_moveIntoEyePos).magnitude(); + if (deltaMag >= startDist && deltaMag <= endDist) + return (deltaMag - startDist) / (endDist - startDist); + if (deltaMag > endDist) + return 1.f; + return 0.f; +} + +void CCinematicCamera::DeactivateSelf(CStateManager& mgr) +{ + SetActive(false); + SendScriptMsgs(EScriptObjectState::Inactive, mgr, EScriptObjectMessage::None); + WasDeactivated(mgr); +} + +void CCinematicCamera::Think(float dt, CStateManager& mgr) +{ + if (GetActive()) + { + zeus::CVector3f viewPoint = GetTranslation(); + if (x188_viewPoints.size() > 0) + { + int idx = 0; + viewPoint = GetInterpolatedSplinePoint(x188_viewPoints, idx, x1ec_t); + if (idx > x1f4_passedViewPoint) + { + x1f4_passedViewPoint = idx; + SendArrivedMsg(x1a8_viewPointArrivals[x1f4_passedViewPoint], mgr); + } + } + + zeus::CQuaternion orientation = GetInterpolatedOrientation(x198_viewOrientations, x1ec_t); + + if ((x21c_flags & 0x1) == 0) + { + if (x1b8_targets.size() > 0) + { + int idx = 0; + zeus::CVector3f target = GetInterpolatedSplinePoint(x1b8_targets, idx, x1ec_t); + if (x1b8_targets.size() == 1) + { + if (TCastToConstPtr act = mgr.GetObjectById(x1c8_targetArrivals.front())) + target = act->GetTranslation(); + else + x1ec_t = x1e8_duration; + } + if (idx > x1f8_passedTarget) + { + x1f8_passedTarget = idx; + SendArrivedMsg(x1c8_targetArrivals[x1f8_passedTarget], mgr); + } + zeus::CVector3f upVec = orientation.transform(zeus::CVector3f::skUp); + if ((target - viewPoint).toVec2f().magnitude() < 0.0011920929f) + SetTranslation(target); + else + SetTransform(zeus::lookAt(viewPoint, target, upVec)); + } + else + { + SetTransform(zeus::CTransform(orientation, viewPoint)); + } + } + else + { + zeus::CVector3f target = mgr.GetPlayer().GetTranslation(); + if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) + target.z += mgr.GetPlayer().GetMorphBall()->GetBallRadius(); + else + target.z += mgr.GetPlayer().GetEyeHeight(); + + zeus::CVector3f upVec = orientation.transform(zeus::CVector3f::skUp); + if ((target - viewPoint).toVec2f().magnitude() < 0.0011920929f) + SetTranslation(target); + else + SetTransform(zeus::lookAt(viewPoint, target, upVec)); + } + + x15c_currentFov = GetInterpolatedHFov(x1d8_viewHFovs, x1ec_t) / x168_aspect; + x170_24_perspDirty = true; + + if (x20c_lookAtId != kInvalidUniqueId) + if (TCastToPtr act = mgr.ObjectById(x20c_lookAtId)) + if (act->IsCameraMoveIntoAlpha()) + act->SetDrawFlags({5, 0, 3, zeus::CColor(1.f, GetMoveOutofIntoAlpha())}); + + x1ec_t += dt; + if (x1ec_t > x1e8_duration) + { + for (int i = x1f4_passedViewPoint + 1; i < x1a8_viewPointArrivals.size() ; ++i) + SendArrivedMsg(x1a8_viewPointArrivals[i], mgr); + for (int i = x1f8_passedTarget + 1; i < x1c8_targetArrivals.size() ; ++i) + SendArrivedMsg(x1c8_targetArrivals[i], mgr); + DeactivateSelf(mgr); + } + } } void CCinematicCamera::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) @@ -58,7 +243,7 @@ void CCinematicCamera::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, TUniqueId id = mgr.GetIdForScript(conn.x8_objId); if (TCastToPtr act = mgr.ObjectById(id)) { - if (act->GetX2E3_24()) + if (act->IsCameraMoveIntoAlpha()) { x20c_lookAtId = id; if (conn.x4_msg != EScriptObjectMessage::Deactivate && @@ -71,17 +256,17 @@ void CCinematicCamera::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, break; case EScriptObjectMessage::Activate: CalculateWaypoints(mgr); - if ((x21c_flags & 1) == 0 && x220_24_ && x1b8_.empty()) + if ((x21c_flags & 1) == 0 && x220_24_ && x1b8_targets.empty()) break; - x1ec_ = 0.f; + x1ec_t = 0.f; Think(0.f, mgr); mgr.GetCameraManager()->AddCinemaCamera(GetUniqueId(), mgr); - x1f4_ = 0; - if (x1a8_.size() > 0) - SendArrivedMsg(x1a8_[x1f4_], mgr); - x1f8_ = 0; - if (x1c8_.size() > 0) - SendArrivedMsg(x1c8_[x1f8_], mgr); + x1f4_passedViewPoint = 0; + if (x1a8_viewPointArrivals.size() > 0) + SendArrivedMsg(x1a8_viewPointArrivals[x1f4_passedViewPoint], mgr); + x1f8_passedTarget = 0; + if (x1c8_targetArrivals.size() > 0) + SendArrivedMsg(x1c8_targetArrivals[x1f8_passedTarget], mgr); if (x21c_flags & 0x100) mgr.SetCinematicPause(true); break; @@ -93,9 +278,193 @@ void CCinematicCamera::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, } } +void CCinematicCamera::CalculateMoveOutofIntoEyePosition(bool outOfEye, CStateManager& mgr) +{ + zeus::CQuaternion q(mgr.GetPlayer().GetTransform().basis); + zeus::CVector3f eyePos = mgr.GetPlayer().GetEyePosition(); + if (x20c_lookAtId != kInvalidUniqueId) + { + if (TCastToConstPtr act = mgr.GetObjectById(x20c_lookAtId)) + { + if (act->IsCameraMoveIntoAlpha()) + { + if (const CModelData* mData = act->GetModelData()) + { + if (const CAnimData* aData = mData->GetAnimationData()) + { + if (const CAnimTreeNode* root = aData->GetRootAnimationTree().get()) + { + CSegId lEye = aData->GetLocatorSegId("L_eye"sv); + CSegId rEye = aData->GetLocatorSegId("R_eye"sv); + if (lEye != 0xff && rEye != 0xff) + { + CCharAnimTime time = + outOfEye ? CCharAnimTime(0.f) : root->VGetSteadyStateAnimInfo().GetDuration(); + CCharAnimTime* pTime = outOfEye ? nullptr : &time; + eyePos = + ((act->GetTransform() * mData->GetScaledLocatorTransformDynamic("L_eye"sv, pTime)).origin + + (act->GetTransform() * mData->GetScaledLocatorTransformDynamic("R_eye"sv, pTime)).origin) * 0.5f; + q = zeus::CQuaternion(act->GetTransform().basis); + } + } + } + } + } + } + } + + zeus::CVector3f behindPos = eyePos; + zeus::CVector3f behindDelta = q.transform({0.f, -g_tweakPlayerRes->xf0_cinematicMoveOutofIntoPlayerDistance, 0.f}); + if (!outOfEye) + { + behindPos += behindDelta; + behindDelta = -behindDelta; + } + + for (int i=0 ; i<2 ; ++i) + { + x188_viewPoints[outOfEye ? i : x188_viewPoints.size() - (2 - i)] = behindPos; + x198_viewOrientations[outOfEye ? i : x198_viewOrientations.size() - (2 - i)] = q; + x1b8_targets[outOfEye ? i : x1b8_targets.size() - (2 - i)] = eyePos; + behindPos += behindDelta; + } + + x210_moveIntoEyePos = eyePos; +} + +void CCinematicCamera::GenerateMoveOutofIntoPoints(bool outOfEye, CStateManager& mgr) +{ + zeus::CQuaternion q(mgr.GetPlayer().GetTransform().basis); + zeus::CVector3f eyePos = mgr.GetPlayer().GetEyePosition(); + zeus::CVector3f behindDelta = q.transform({0.f, -g_tweakPlayerRes->xf0_cinematicMoveOutofIntoPlayerDistance, 0.f}); + zeus::CVector3f behindPos = eyePos; + if (!outOfEye) + { + behindPos += behindDelta; + behindDelta = -behindDelta; + } + for (int i=0 ; i<2 ; ++i) + { + x188_viewPoints.push_back(behindPos); + x198_viewOrientations.push_back(q); + x1a8_viewPointArrivals.push_back(mgr.GetPlayer().GetUniqueId()); + x1b8_targets.push_back(eyePos); + x1c8_targetArrivals.push_back(kInvalidUniqueId); + behindPos += behindDelta; + } + CalculateMoveOutofIntoEyePosition(outOfEye, mgr); +} + +bool CCinematicCamera::PickRandomActiveConnection(const std::vector& conns, + SConnection& randConn, CStateManager& mgr) +{ + int count = 0; + for (const SConnection& conn : conns) + if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Next) + if (TCastToConstPtr act = mgr.GetObjectById(mgr.GetIdForScript(conn.x8_objId))) + if (act->GetActive()) + ++count; + + if (!count) + return false; + + int randIdx = mgr.GetActiveRandom()->Next() % count; + int idx = 0; + for (const SConnection& conn : conns) + if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Next) + if (TCastToConstPtr act = mgr.GetObjectById(mgr.GetIdForScript(conn.x8_objId))) + if (act->GetActive()) + { + if (randIdx == idx) + { + randConn = conn; + break; + } + ++idx; + } + + return true; +} + void CCinematicCamera::CalculateWaypoints(CStateManager& mgr) { + const SConnection* firstVP = nullptr; + const SConnection* firstTarget = nullptr; + for (const SConnection& conn : x20_conns) + { + if (conn.x0_state == EScriptObjectState::CameraPath && conn.x4_msg == EScriptObjectMessage::Activate) + firstVP = &conn; + else if (conn.x0_state == EScriptObjectState::CameraTarget && conn.x4_msg == EScriptObjectMessage::Activate) + firstTarget = &conn; + } + x188_viewPoints.clear(); + x188_viewPoints.reserve(3); + x198_viewOrientations.clear(); + x198_viewOrientations.reserve(3); + x1a8_viewPointArrivals.clear(); + x1a8_viewPointArrivals.reserve(3); + x1b8_targets.clear(); + x1b8_targets.reserve(3); + x1c8_targetArrivals.clear(); + x1c8_targetArrivals.reserve(3); + x1d8_viewHFovs.clear(); + x1d8_viewHFovs.reserve(3); + + x220_24_ = false; + + if ((x21c_flags & 0x2) != 0 && (x21c_flags & 0x200) == 0) + GenerateMoveOutofIntoPoints(true, mgr); + + if (firstVP) + { + TCastToConstPtr wp = mgr.GetObjectById(mgr.GetIdForScript(firstVP->x8_objId)); + while (wp) + { + x188_viewPoints.push_back(wp->GetTranslation()); + x198_viewOrientations.emplace_back(wp->GetTransform().basis); + if (TCastToConstPtr cwp = wp.GetPtr()) + x1d8_viewHFovs.push_back(cwp->GetHFov()); + auto search = std::find_if(x1a8_viewPointArrivals.begin(), x1a8_viewPointArrivals.end(), + [&](TUniqueId id) { return id == wp->GetUniqueId(); }); + if (search == x1a8_viewPointArrivals.end()) + { + x1a8_viewPointArrivals.push_back(wp->GetUniqueId()); + SConnection randConn; + if (PickRandomActiveConnection(wp->GetConnectionList(), randConn, mgr)) + wp = mgr.GetObjectById(mgr.GetIdForScript(randConn.x8_objId)); + else + break; + } + else + break; + } + } + + if (firstTarget) + { + TCastToConstPtr tgt = mgr.GetObjectById(mgr.GetIdForScript(firstTarget->x8_objId)); + while (tgt) + { + x1b8_targets.push_back(tgt->GetTranslation()); + auto search = std::find_if(x1c8_targetArrivals.begin(), x1c8_targetArrivals.end(), + [&](TUniqueId id) { return id == tgt->GetUniqueId(); }); + if (search == x1c8_targetArrivals.end()) + { + x1c8_targetArrivals.push_back(tgt->GetUniqueId()); + SConnection randConn; + if (PickRandomActiveConnection(tgt->GetConnectionList(), randConn, mgr)) + tgt = mgr.GetObjectById(mgr.GetIdForScript(randConn.x8_objId)); + else + break; + } + else + break; + } + } + + if ((x21c_flags & 0x4) != 0 && (x21c_flags & 0x200) == 0) + GenerateMoveOutofIntoPoints(false, mgr); } void CCinematicCamera::SendArrivedMsg(TUniqueId reciever, CStateManager& mgr) diff --git a/Runtime/Camera/CCinematicCamera.hpp b/Runtime/Camera/CCinematicCamera.hpp index 1d53f758d..b5e79a358 100644 --- a/Runtime/Camera/CCinematicCamera.hpp +++ b/Runtime/Camera/CCinematicCamera.hpp @@ -8,35 +8,48 @@ namespace urde class CCinematicCamera : public CGameCamera { - std::vector x188_; - std::vector x198_; - std::vector x1a8_; - std::vector x1b8_; - std::vector x1c8_; - std::vector x1d8_; + std::vector x188_viewPoints; + std::vector x198_viewOrientations; + std::vector x1a8_viewPointArrivals; + std::vector x1b8_targets; + std::vector x1c8_targetArrivals; + std::vector x1d8_viewHFovs; float x1e8_duration; - float x1ec_ = 0.f; + float x1ec_t = 0.f; float x1f0_origFovy; - u32 x1f4_ = 0; - u32 x1f8_ = 0; - zeus::CQuaternion x1fc_; + int x1f4_passedViewPoint = 0; + int x1f8_passedTarget = 0; + zeus::CQuaternion x1fc_origOrientation; TUniqueId x20c_lookAtId = kInvalidUniqueId; - zeus::CVector3f x210_; - u32 x21c_flags; + zeus::CVector3f x210_moveIntoEyePos; + u32 x21c_flags; // 0x1: look at player, 0x2: out of player eye, 0x4: into player eye, 0x10: finish cine skip, + // 0x20: disable input, 0x40: draw player, 0x80: check failsafe, 0x100: cinematic pause, + // 0x200: disable out of into bool x220_24_; + zeus::CVector3f GetInterpolatedSplinePoint(const std::vector& points, int& idxOut, float t) const; + zeus::CQuaternion GetInterpolatedOrientation(const std::vector& rotations, float t) const; + float GetInterpolatedHFov(const std::vector& fovs, float t) const; + float GetMoveOutofIntoAlpha() const; + void DeactivateSelf(CStateManager& mgr); + void CalculateMoveOutofIntoEyePosition(bool outOfEye, CStateManager& mgr); + void GenerateMoveOutofIntoPoints(bool outOfEye, CStateManager& mgr); + static bool PickRandomActiveConnection(const std::vector& conns, + SConnection& randConn, CStateManager& mgr); + void CalculateWaypoints(CStateManager& mgr); public: CCinematicCamera(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, bool active, float shotDuration, float fovy, float znear, float zfar, float aspect, u32 flags); void Accept(IVisitor& visitor); + void Think(float dt, CStateManager& mgr); void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr); void ProcessInput(const CFinalInput&, CStateManager& mgr); void Reset(const zeus::CTransform&, CStateManager& mgr); u32 GetFlags() const { return x21c_flags; } void WasDeactivated(CStateManager& mgr); - void CalculateWaypoints(CStateManager& mgr); void SendArrivedMsg(TUniqueId reciever, CStateManager& mgr); + float GetDuration() const { return x1e8_duration; } }; } diff --git a/Runtime/Camera/CGameCamera.cpp b/Runtime/Camera/CGameCamera.cpp index 9cdb44af0..9fda232c1 100644 --- a/Runtime/Camera/CGameCamera.cpp +++ b/Runtime/Camera/CGameCamera.cpp @@ -24,7 +24,7 @@ CGameCamera::CGameCamera(TUniqueId uid, bool active, std::string_view name, cons , x184_fov(fovy) { - xe7_29_ = false; + xe7_29_actorActive = false; } void CGameCamera::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) @@ -46,7 +46,7 @@ void CGameCamera::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStat void CGameCamera::SetActive(bool active) { CActor::SetActive(active); - xe7_29_ = false; + xe7_29_actorActive = false; } zeus::CMatrix4f CGameCamera::GetPerspectiveMatrix() const @@ -103,9 +103,9 @@ zeus::CTransform CGameCamera::ValidateCameraTransform(const zeus::CTransform& a, void CGameCamera::UpdatePerspective(float dt) { - if (x174_ > 0.f) + if (x174_delayTime > 0.f) { - x174_ -= dt; + x174_delayTime -= dt; return; } @@ -125,18 +125,18 @@ void CGameCamera::UpdatePerspective(float dt) } } -void CGameCamera::SetFovInterpolation(float start, float fov, float time, float f4) +void CGameCamera::SetFovInterpolation(float start, float fov, float time, float delayTime) { if (time < 0.f) { x15c_currentFov = fov; x170_24_perspDirty = true; x184_fov = fov; - x178_ = x174_ = 0.f; + x178_ = x174_delayTime = 0.f; } else { - x174_ = std::max(0.f, f4); + x174_delayTime = std::max(0.f, delayTime); x17c_ = time; x178_ = time; x180_ = start; @@ -154,6 +154,6 @@ void CGameCamera::SkipFovInterpolation() x170_24_perspDirty = true; } - x178_ = x174_ = 0.f; + x178_ = x174_delayTime = 0.f; } } diff --git a/Runtime/Camera/CGameCamera.hpp b/Runtime/Camera/CGameCamera.hpp index 3580a9da5..b5091f953 100644 --- a/Runtime/Camera/CGameCamera.hpp +++ b/Runtime/Camera/CGameCamera.hpp @@ -24,7 +24,7 @@ protected: u32 x16c_controllerIdx; bool x170_24_perspDirty : 1; bool x170_25_disablesInput : 1; - float x174_ = 0.f; + float x174_delayTime = 0.f; float x178_ = 0.f; float x17c_ = 0.f; float x180_; @@ -51,7 +51,7 @@ public: void GetControllerNumber() const; bool DisablesInput() const; void UpdatePerspective(float); - void SetFovInterpolation(float start, float end, float time, float f4); + void SetFovInterpolation(float start, float end, float time, float delayTime); void SkipFovInterpolation(); }; } diff --git a/Runtime/Character/CAnimData.hpp b/Runtime/Character/CAnimData.hpp index 5b30e50e6..980d5b6f1 100644 --- a/Runtime/Character/CAnimData.hpp +++ b/Runtime/Character/CAnimData.hpp @@ -172,6 +172,7 @@ public: SAdvancementDeltas UpdateAdditiveAnims(float); bool IsAdditiveAnimation(u32) const; bool IsAdditiveAnimationAdded(u32) const; + const std::shared_ptr& GetRootAnimationTree() const { return x1f8_animRoot; } const std::shared_ptr& GetAdditiveAnimationTree(u32) const; bool IsAdditiveAnimationActive(u32) const; void DelAdditiveAnimation(u32); diff --git a/Runtime/Collision/CCollisionActor.cpp b/Runtime/Collision/CCollisionActor.cpp index da26c55ab..e3914f163 100644 --- a/Runtime/Collision/CCollisionActor.cpp +++ b/Runtime/Collision/CCollisionActor.cpp @@ -146,7 +146,7 @@ rstl::optional_object CCollisionActor::GetTouchBounds() const else if (x258_primitiveType == EPrimitiveType::AABox) aabox = {x280_aaboxPrimitive->CalculateAABox(x34_transform)}; else if (x258_primitiveType == EPrimitiveType::Sphere) - aabox = {x280_aaboxPrimitive->CalculateAABox(x34_transform)}; + aabox = {x284_spherePrimitive->CalculateAABox(x34_transform)}; aabox->accumulateBounds(aabox->max + x304_extendedTouchBounds); aabox->accumulateBounds(aabox->min - x304_extendedTouchBounds); diff --git a/Runtime/Graphics/CSimpleShadow.cpp b/Runtime/Graphics/CSimpleShadow.cpp index 458e48369..14562faf5 100644 --- a/Runtime/Graphics/CSimpleShadow.cpp +++ b/Runtime/Graphics/CSimpleShadow.cpp @@ -7,7 +7,7 @@ CSimpleShadow::CSimpleShadow(float, float, float, float) } -void CSimpleShadow::Render(const CTexture* tex) +void CSimpleShadow::Render(const CTexture* tex) const { } diff --git a/Runtime/Graphics/CSimpleShadow.hpp b/Runtime/Graphics/CSimpleShadow.hpp index c1eff7374..64f42af07 100644 --- a/Runtime/Graphics/CSimpleShadow.hpp +++ b/Runtime/Graphics/CSimpleShadow.hpp @@ -10,7 +10,7 @@ class CSimpleShadow public: CSimpleShadow() = default; CSimpleShadow(float, float, float, float); - void Render(const CTexture* tex); + void Render(const CTexture* tex) const; }; } diff --git a/Runtime/Graphics/Shaders/CFluidPlaneShader.cpp b/Runtime/Graphics/Shaders/CFluidPlaneShader.cpp index 536832011..b3d04b35f 100644 --- a/Runtime/Graphics/Shaders/CFluidPlaneShader.cpp +++ b/Runtime/Graphics/Shaders/CFluidPlaneShader.cpp @@ -150,7 +150,7 @@ void CFluidPlaneShader::PrepareBinding(const boo::ObjToken [&](boo::IGraphicsDataFactory::Context& ctx) { m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(Vertex), maxVertCount); - m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, 1024, 1); + m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); switch (ctx.platform()) { diff --git a/Runtime/Graphics/Shaders/CFluidPlaneShaderGLSL.cpp b/Runtime/Graphics/Shaders/CFluidPlaneShaderGLSL.cpp index e53e0b285..5aee50be6 100644 --- a/Runtime/Graphics/Shaders/CFluidPlaneShaderGLSL.cpp +++ b/Runtime/Graphics/Shaders/CFluidPlaneShaderGLSL.cpp @@ -460,8 +460,15 @@ static void _BuildShader(std::string& finalVS, std::string& finalFS, int& nextTe combiner += " colorOut.a = kColor0.a;\n"; - finalVS = hecl::Format(VS, additionalTCGs.c_str()); - finalFS = hecl::Format(FS, textures.c_str(), combiner.c_str()); + char *finalVSs, *finalFSs; + asprintf(&finalVSs, VS, additionalTCGs.c_str()); + asprintf(&finalFSs, FS, textures.c_str(), combiner.c_str()); + + finalVS = finalVSs; + finalFS = finalFSs; + + free(finalVSs); + free(finalFSs); } static void _BuildShader(std::string& finalVS, std::string& finalFS, int& nextTex, const char* texNames[3], @@ -505,8 +512,15 @@ static void _BuildShader(std::string& finalVS, std::string& finalFS, int& nextTe combiner += " colorOut.a = kColor0.a;\n"; - finalVS = hecl::Format(VS, additionalTCGs.c_str()); - finalFS = hecl::Format(FSDoor, textures.c_str(), combiner.c_str()); + char *finalVSs, *finalFSs; + asprintf(&finalVSs, VS, additionalTCGs.c_str()); + asprintf(&finalFSs, FSDoor, textures.c_str(), combiner.c_str()); + + finalVS = finalVSs; + finalFS = finalFSs; + + free(finalVSs); + free(finalFSs); } boo::ObjToken diff --git a/Runtime/Graphics/Shaders/CFluidPlaneShaderHLSL.cpp b/Runtime/Graphics/Shaders/CFluidPlaneShaderHLSL.cpp index 4e688cbb4..afa801673 100644 --- a/Runtime/Graphics/Shaders/CFluidPlaneShaderHLSL.cpp +++ b/Runtime/Graphics/Shaders/CFluidPlaneShaderHLSL.cpp @@ -456,14 +456,20 @@ CFluidPlaneShader::BuildShader(boo::ID3DDataFactory::Context& ctx, const SFluidP combiner += " colorOut.a = kColor0.a;\n"; - std::string finalVS = hecl::Format(VS, additionalTCGs.c_str()); - std::string finalFS = hecl::Format(FS, textures.c_str(), combiner.c_str()); + char *finalVS, *finalFS; + asprintf(&finalVS, VS, additionalTCGs.c_str()); + asprintf(&finalFS, FS, textures.c_str(), combiner.c_str()); - return ctx.newShaderPipeline(finalVS.c_str(), finalFS.c_str(), nullptr, nullptr, nullptr, s_vtxFmt, - info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::SrcAlpha, - info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::InvSrcAlpha, - boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false, - boo::CullMode::None); + auto ret = ctx.newShaderPipeline(finalVS, finalFS, nullptr, nullptr, nullptr, s_vtxFmt, + info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::SrcAlpha, + info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false, + boo::CullMode::None); + + free(finalVS); + free(finalFS); + + return ret; } boo::ObjToken @@ -512,13 +518,19 @@ CFluidPlaneShader::BuildShader(boo::ID3DDataFactory::Context& ctx, const SFluidP combiner += " colorOut.a = kColor0.a;\n"; - std::string finalVS = hecl::Format(VS, additionalTCGs.c_str()); - std::string finalFS = hecl::Format(FSDoor, textures.c_str(), combiner.c_str()); + char *finalVS, *finalFS; + asprintf(&finalVS, VS, additionalTCGs.c_str()); + asprintf(&finalFS, FSDoor, textures.c_str(), combiner.c_str()); - return ctx.newShaderPipeline(finalVS.c_str(), finalFS.c_str(), nullptr, nullptr, nullptr, s_vtxFmt, - boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, - boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false, - boo::CullMode::None); + auto ret = ctx.newShaderPipeline(finalVS, finalFS, nullptr, nullptr, nullptr, s_vtxFmt, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false, + boo::CullMode::None); + + free(finalVS); + free(finalFS); + + return ret; } boo::ObjToken diff --git a/Runtime/Graphics/Shaders/CFluidPlaneShaderMetal.cpp b/Runtime/Graphics/Shaders/CFluidPlaneShaderMetal.cpp index 10bb495af..04077d523 100644 --- a/Runtime/Graphics/Shaders/CFluidPlaneShaderMetal.cpp +++ b/Runtime/Graphics/Shaders/CFluidPlaneShaderMetal.cpp @@ -17,7 +17,7 @@ static const char* VS = " float4 colorIn [[ attribute(4) ]];\n" "};\n" "\n" -"UBINDING0 uniform FluidPlaneUniform\n" +"struct FluidPlaneUniform\n" "{\n" " float4x4 mv;\n" " float4x4 mvNorm;\n" @@ -27,13 +27,19 @@ static const char* VS = "\n" "struct VertToFrag\n" "{\n" -" float4 pos : [[ position ]];\n" +" float4 pos [[ position ]];\n" " float4 mvPos;\n" " float4 mvNorm;\n" " float4 mvBinorm;\n" " float4 mvTangent;\n" " float4 color;\n" -" float2 uvs[7];\n" +" float2 uv0;\n" +" float2 uv1;\n" +" float2 uv2;\n" +" float2 uv3;\n" +" float2 uv4;\n" +" float2 uv5;\n" +" float2 uv6;\n" "};\n" "\n" "vertex VertToFrag vmain(VertData v [[ stage_in ]],\n" @@ -46,9 +52,9 @@ static const char* VS = " vtf.mvBinorm = fu.mvNorm * v.binormalIn;\n" " vtf.mvTangent = fu.mvNorm * v.tangentIn;\n" " vtf.color = v.colorIn;\n" -" vtf.uvs[0] = (fu.texMtxs[0] * v.posIn).xy;\n" -" vtf.uvs[1] = (fu.texMtxs[1] * v.posIn).xy;\n" -" vtf.uvs[2] = (fu.texMtxs[2] * v.posIn).xy;\n" +" vtf.uv0 = (fu.texMtxs[0] * v.posIn).xy;\n" +" vtf.uv1 = (fu.texMtxs[1] * v.posIn).xy;\n" +" vtf.uv2 = (fu.texMtxs[2] * v.posIn).xy;\n" "%s" // Additional TCGs here " return vtf;\n" "}\n"; @@ -107,13 +113,19 @@ static const char* FS = "\n" "struct VertToFrag\n" "{\n" -" float4 pos : [[ position ]];\n" +" float4 pos [[ position ]];\n" " float4 mvPos;\n" " float4 mvNorm;\n" " float4 mvBinorm;\n" " float4 mvTangent;\n" " float4 color;\n" -" float2 uvs[7];\n" +" float2 uv0;\n" +" float2 uv1;\n" +" float2 uv2;\n" +" float2 uv3;\n" +" float2 uv4;\n" +" float2 uv5;\n" +" float2 uv6;\n" "};\n" "\n" "fragment float4 fmain(VertToFrag vtf [[ stage_in ]],\n" @@ -130,18 +142,51 @@ static const char* FSDoor = "using namespace metal;\n" "constexpr sampler samp(address::repeat, filter::linear);\n" "\n" +"struct Light\n" +"{\n" +" float4 pos;\n" +" float4 dir;\n" +" float4 color;\n" +" float4 linAtt;\n" +" float4 angAtt;\n" +"};\n" +"struct Fog\n" // Reappropriated for indirect texture scaling +"{\n" +" float4 color;\n" +" float indScale;\n" +" float start;\n" +"};\n" +"\n" +"struct LightingUniform\n" +"{\n" +" Light lights[" _XSTR(URDE_MAX_LIGHTS) "];\n" +" float4 ambient;\n" +" float4 kColor0;\n" +" float4 kColor1;\n" +" float4 kColor2;\n" +" float4 kColor3;\n" +" Fog fog;\n" +"};\n" +"\n" "struct VertToFrag\n" "{\n" -" float4 pos : [[ position ]];\n" +" float4 pos [[ position ]];\n" " float4 mvPos;\n" " float4 mvNorm;\n" " float4 mvBinorm;\n" " float4 mvTangent;\n" " float4 color;\n" -" float2 uvs[7];\n" +" float2 uv0;\n" +" float2 uv1;\n" +" float2 uv2;\n" +" float2 uv3;\n" +" float2 uv4;\n" +" float2 uv5;\n" +" float2 uv6;\n" "};\n" "\n" -"fragment float4 fmain(VertToFrag vtf [[ stage_in ]]%s)\n" // Textures here +"fragment float4 fmain(VertToFrag vtf [[ stage_in ]],\n" +" constant LightingUniform& lu [[ buffer(4) ]]%s)\n" // Textures here "{\n" " float4 colorOut;\n" "%s" // Combiner expression here @@ -190,22 +235,22 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid if (info.m_hasBumpMap) { bumpMapUv = nextTCG; - additionalTCGs += hecl::Format(" vtf.uvs[%d] = (fu.texMtxs[0] * v.posIn).xy;\n", nextTCG++); + additionalTCGs += hecl::Format(" vtf.uv%d = (fu.texMtxs[0] * v.posIn).xy;\n", nextTCG++); } if (info.m_hasEnvBumpMap) { envBumpMapUv = nextTCG; - additionalTCGs += hecl::Format(" vtf.uvs[%d] = (fu.texMtxs[3] * v.posIn).xy;\n", nextTCG++); + additionalTCGs += hecl::Format(" vtf.uv%d = (fu.texMtxs[3] * v.posIn).xy;\n", nextTCG++); } if (info.m_hasEnvMap) { envMapUv = nextTCG; - additionalTCGs += hecl::Format(" vtf.uvs[%d] = (fu.texMtxs[%d] * v.posIn).xy;\n", nextTCG++, nextMtx++); + additionalTCGs += hecl::Format(" vtf.uv%d = (fu.texMtxs[%d] * v.posIn).xy;\n", nextTCG++, nextMtx++); } if (info.m_hasLightmap) { lightmapUv = nextTCG; - additionalTCGs += hecl::Format(" vtf.uvs[%d] = (fu.texMtxs[%d] * v.posIn).xy;\n", nextTCG++, nextMtx++); + additionalTCGs += hecl::Format(" vtf.uv%d = (fu.texMtxs[%d] * v.posIn).xy;\n", nextTCG++, nextMtx++); } switch (info.m_type) @@ -215,7 +260,7 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid case CFluidPlane::EFluidType::Four: if (info.m_hasLightmap) { - combiner += hecl::Format(" float4 lightMapTexel = lightMap.sample(samp, vtf.uvs[%d]);\n", lightmapUv); + combiner += hecl::Format(" float4 lightMapTexel = lightMap.sample(samp, vtf.uv%d);\n", lightmapUv); // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1 // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS // Output reg 2 @@ -253,10 +298,10 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid if (info.m_hasPatternTex2) { if (info.m_hasPatternTex1) - combiner += " colorOut = (patternTex1.sample(samp, vtf.uvs[0]) * lu.kColor0 + lighting) *\n" - " patternTex2.sample(samp, vtf.uvs[1]) + vtf.color;\n"; + combiner += " colorOut = (patternTex1.sample(samp, vtf.uv0) * lu.kColor0 + lighting) *\n" + " patternTex2.sample(samp, vtf.uv1) + vtf.color;\n"; else - combiner += " colorOut = lighting * patternTex2.sample(samp, vtf.uvs[1]) + vtf.color;\n"; + combiner += " colorOut = lighting * patternTex2.sample(samp, vtf.uv1) + vtf.color;\n"; } else { @@ -267,9 +312,9 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid if (info.m_hasColorTex && !info.m_hasEnvMap && info.m_hasEnvBumpMap) { // Make previous stage indirect, mtx0 - combiner += hecl::Format(" float2 indUvs = (envBumpMap.sample(samp, vtf.uvs[%d]).ra - float2(0.5, 0.5)) *\n" + combiner += hecl::Format(" float2 indUvs = (envBumpMap.sample(samp, vtf.uv%d).ra - float2(0.5, 0.5)) *\n" " float2(lu.fog.indScale, -lu.fog.indScale);", envBumpMapUv); - combiner += " colorOut += colorTex.sample(samp, indUvs + vtf.uvs[2]) * lighting;\n"; + combiner += " colorOut += colorTex.sample(samp, indUvs + vtf.uv2) * lighting;\n"; } else if (info.m_hasEnvMap) { @@ -280,15 +325,15 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid // Make previous stage indirect, mtx0 if (info.m_hasColorTex) - combiner += " colorOut += colorTex.sample(samp, vtf.uvs[2]) * lighting;\n"; - combiner += hecl::Format(" float2 indUvs = (envBumpMap.sample(samp, vtf.uvs[%d]).ra - float2(0.5, 0.5)) *\n" + combiner += " colorOut += colorTex.sample(samp, vtf.uv2) * lighting;\n"; + combiner += hecl::Format(" float2 indUvs = (envBumpMap.sample(samp, vtf.uv%d).ra - float2(0.5, 0.5)) *\n" " float2(lu.fog.indScale, -lu.fog.indScale);", envBumpMapUv); - combiner += hecl::Format(" colorOut = mix(colorOut, envMap.sample(samp, indUvs + vtf.uvs[%d]), lu.kColor1);\n", + combiner += hecl::Format(" colorOut = mix(colorOut, envMap.sample(samp, indUvs + vtf.uv%d), lu.kColor1);\n", envMapUv); } else if (info.m_hasColorTex) { - combiner += " colorOut += colorTex.sample(samp, vtf.uvs[2]) * lighting;\n"; + combiner += " colorOut += colorTex.sample(samp, vtf.uv2) * lighting;\n"; } break; @@ -296,7 +341,7 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid case CFluidPlane::EFluidType::PoisonWater: if (info.m_hasLightmap) { - combiner += hecl::Format(" float4 lightMapTexel = lightMap.sample(samp, vtf.uvs[%d]);\n", lightmapUv); + combiner += hecl::Format(" float4 lightMapTexel = lightMap.sample(samp, vtf.uv%d);\n", lightmapUv); // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1 // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS // Output reg 2 @@ -334,10 +379,10 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid if (info.m_hasPatternTex2) { if (info.m_hasPatternTex1) - combiner += " colorOut = (patternTex1.sample(samp, vtf.uvs[0]) * lu.kColor0 + lighting) *\n" - " patternTex2.sample(samp, vtf.uvs[1]) + vtf.color;\n"; + combiner += " colorOut = (patternTex1.sample(samp, vtf.uv0) * lu.kColor0 + lighting) *\n" + " patternTex2.sample(samp, vtf.uv1) + vtf.color;\n"; else - combiner += " colorOut = lighting * patternTex2.sample(samp, vtf.uvs[1]) + vtf.color;\n"; + combiner += " colorOut = lighting * patternTex2.sample(samp, vtf.uv1) + vtf.color;\n"; } else { @@ -349,13 +394,13 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid if (info.m_hasEnvBumpMap) { // Make previous stage indirect, mtx0 - combiner += hecl::Format(" float2 indUvs = (envBumpMap.sample(samp, vtf.uvs[%d]).ra - float2(0.5, 0.5)) *\n" + combiner += hecl::Format(" float2 indUvs = (envBumpMap.sample(samp, vtf.uv%d).ra - float2(0.5, 0.5)) *\n" " float2(lu.fog.indScale, -lu.fog.indScale);", envBumpMapUv); - combiner += " colorOut += colorTex.sample(samp, indUvs + vtf.uvs[2]) * lighting;\n"; + combiner += " colorOut += colorTex.sample(samp, indUvs + vtf.uv2) * lighting;\n"; } else { - combiner += " colorOut += colorTex.sample(samp, vtf.uvs[2]) * lighting;\n"; + combiner += " colorOut += colorTex.sample(samp, vtf.uv2) * lighting;\n"; } } @@ -379,10 +424,10 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid if (info.m_hasPatternTex2) { if (info.m_hasPatternTex1) - combiner += " colorOut = (patternTex1.sample(samp, vtf.uvs[0]) * lu.kColor0 + vtf.color) *\n" - " patternTex2.sample(samp, vtf.uvs[1]) + vtf.color;\n"; + combiner += " colorOut = (patternTex1.sample(samp, vtf.uv0) * lu.kColor0 + vtf.color) *\n" + " patternTex2.sample(samp, vtf.uv1) + vtf.color;\n"; else - combiner += " colorOut = vtf.color * patternTex2.sample(samp, vtf.uvs[1]) + vtf.color;\n"; + combiner += " colorOut = vtf.color * patternTex2.sample(samp, vtf.uv1) + vtf.color;\n"; } else { @@ -390,7 +435,7 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid } if (info.m_hasColorTex) - combiner += " colorOut += colorTex.sample(samp, vtf.uvs[2]);\n"; + combiner += " colorOut += colorTex.sample(samp, vtf.uv2);\n"; if (info.m_hasBumpMap) { @@ -405,8 +450,8 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid combiner += " float3 lightVec = lights[3].pos.xyz - vtf.mvPos.xyz;\n" " float lx = dot(vtf.mvTangent.xyz, lightVec);\n" " float ly = dot(vtf.mvBinorm.xyz, lightVec);\n"; - combiner += hecl::Format(" float4 emboss1 = bumpMap.sample(samp, vtf.uvs[%d]) + float4(0.5);\n" - " float4 emboss2 = bumpMap.sample(samp, vtf.uvs[%d] + float2(lx, ly));\n", + combiner += hecl::Format(" float4 emboss1 = bumpMap.sample(samp, vtf.uv%d) + float4(0.5);\n" + " float4 emboss2 = bumpMap.sample(samp, vtf.uv%d + float2(lx, ly));\n", bumpMapUv, bumpMapUv); // 5: NULL, NULL, NULL @@ -437,10 +482,10 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid if (info.m_hasPatternTex2) { if (info.m_hasPatternTex1) - combiner += " colorOut = (patternTex1.sample(samp, vtf.uvs[0]) * lu.kColor0 + vtf.color) *\n" - " patternTex2.sample(samp, vtf.uvs[1]) + vtf.color;\n"; + combiner += " colorOut = (patternTex1.sample(samp, vtf.uv0) * lu.kColor0 + vtf.color) *\n" + " patternTex2.sample(samp, vtf.uv1) + vtf.color;\n"; else - combiner += " colorOut = vtf.color * patternTex2.sample(samp, vtf.uvs[1]) + vtf.color;\n"; + combiner += " colorOut = vtf.color * patternTex2.sample(samp, vtf.uv1) + vtf.color;\n"; } else { @@ -448,31 +493,37 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid } if (info.m_hasColorTex) - combiner += " colorOut += colorTex.sample(samp, vtf.uvs[2]);\n"; + combiner += " colorOut += colorTex.sample(samp, vtf.uv2);\n"; if (info.m_hasBumpMap) { // 3: bumpMapTCG, bumpMap, NULL // ZERO, TEX, PREV, ZERO // Output reg prev, scale 2 - combiner += hecl::Format(" float4 emboss1 = bumpMap.sample(samp, vtf.uvs[%d]) + float4(0.5);\n", bumpMapUv); + combiner += hecl::Format(" float4 emboss1 = bumpMap.sample(samp, vtf.uv%d) + float4(0.5);\n", bumpMapUv); combiner += "colorOut *= emboss1 * float4(2.0);\n"; } break; } - combiner += " colorOut.a = kColor0.a;\n"; + combiner += " colorOut.a = lu.kColor0.a;\n"; - std::string finalVS = hecl::Format(VS, additionalTCGs.c_str()); - std::string finalFS = hecl::Format(FS, textures.c_str(), combiner.c_str()); + char *finalVS, *finalFS; + asprintf(&finalVS, VS, additionalTCGs.c_str()); + asprintf(&finalFS, FS, textures.c_str(), combiner.c_str()); - return ctx.newShaderPipeline(finalVS.c_str(), finalFS.c_str(), nullptr, nullptr, - s_vtxFmt, CGraphics::g_ViewportSamples, - info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::SrcAlpha, - info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::InvSrcAlpha, - boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false, - boo::CullMode::None); + auto ret = ctx.newShaderPipeline(finalVS, finalFS, nullptr, nullptr, + s_vtxFmt, CGraphics::g_ViewportSamples, + info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::SrcAlpha, + info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false, + boo::CullMode::None); + + free(finalVS); + free(finalFS); + + return ret; } boo::ObjToken @@ -506,8 +557,8 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid // Tex0 * kColor0 * Tex1 + Tex2 if (info.m_hasPatternTex1 && info.m_hasPatternTex2) { - combiner += " colorOut = patternTex1.sample(samp, vtf.uvs[0]) * lu.kColor0 *\n" - " patternTex2.sample(samp, vtf.uvs[1]);\n"; + combiner += " colorOut = patternTex1.sample(samp, vtf.uv0) * lu.kColor0 *\n" + " patternTex2.sample(samp, vtf.uv1);\n"; } else { @@ -516,19 +567,25 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid if (info.m_hasColorTex) { - combiner += " colorOut += colorTex.sample(samp, vtf.uvs[2]);\n"; + combiner += " colorOut += colorTex.sample(samp, vtf.uv2);\n"; } - combiner += " colorOut.a = kColor0.a;\n"; + combiner += " colorOut.a = lu.kColor0.a;\n"; - std::string finalVS = hecl::Format(VS, additionalTCGs.c_str()); - std::string finalFS = hecl::Format(FSDoor, textures.c_str(), combiner.c_str()); + char *finalVS, *finalFS; + asprintf(&finalVS, VS, additionalTCGs.c_str()); + asprintf(&finalFS, FSDoor, textures.c_str(), combiner.c_str()); - return ctx.newShaderPipeline(finalVS.c_str(), finalFS.c_str(), nullptr, nullptr, - s_vtxFmt, CGraphics::g_ViewportSamples, - boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, - boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false, - boo::CullMode::None); + auto ret = ctx.newShaderPipeline(finalVS, finalFS, nullptr, nullptr, + s_vtxFmt, CGraphics::g_ViewportSamples, + boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, + boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false, + boo::CullMode::None); + + free(finalVS); + free(finalFS); + + return ret; } boo::ObjToken CFluidPlaneShader::BuildBinding(boo::MetalDataFactory::Context& ctx, diff --git a/Runtime/RetroTypes.hpp b/Runtime/RetroTypes.hpp index 285b73288..a15ecfdf6 100644 --- a/Runtime/RetroTypes.hpp +++ b/Runtime/RetroTypes.hpp @@ -10,6 +10,8 @@ #include "IOStreams.hpp" #include "hecl/hecl.hpp" +using namespace std::literals; + namespace urde { diff --git a/Runtime/Weapon/CWeapon.hpp b/Runtime/Weapon/CWeapon.hpp index 9bd1faa91..3d114efd5 100644 --- a/Runtime/Weapon/CWeapon.hpp +++ b/Runtime/Weapon/CWeapon.hpp @@ -27,11 +27,12 @@ public: ArmCannon = (1 << 11), BigStrike = (1 << 12), StaticInterference = (1 << 14), + KeepInCinematic = (1 << 17), }; private: EProjectileAttrib xe8_projectileAttribs; - TUniqueId xec_uid; + TUniqueId xec_ownerId; EWeaponType xf0_weaponType; u32 xf4_; CMaterialFilter xf8_; @@ -52,8 +53,8 @@ public: EProjectileAttrib GetAttribField() const { return xe8_projectileAttribs; } const CMaterialFilter& GetFilter() const; void SetFilter(const CMaterialFilter&); - TUniqueId GetOwnerId() const; - void SetOwnerId(TUniqueId); + TUniqueId GetOwnerId() const { return xec_ownerId; } + void SetOwnerId(TUniqueId oid) { xec_ownerId = oid; } EWeaponType GetType() const; const CDamageInfo& GetDamageInfo() const; CDamageInfo& DamageInfo(); diff --git a/Runtime/World/CActor.cpp b/Runtime/World/CActor.cpp index 195be6b12..ec7396509 100644 --- a/Runtime/World/CActor.cpp +++ b/Runtime/World/CActor.cpp @@ -7,6 +7,8 @@ #include "Character/IAnimReader.hpp" #include "Character/CActorLights.hpp" #include "Camera/CGameCamera.hpp" +#include "GameGlobalObjects.hpp" +#include "CSimplePool.hpp" namespace urde { @@ -27,9 +29,38 @@ CActor::CActor(TUniqueId uid, bool active, std::string_view name, const CEntityI , x70_materialFilter(CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {0ull})) , xc6_nextDrawNode(otherUid) { + x90_actorLights = mData.IsNull() ? std::unique_ptr() : params.x0_lightParms.MakeActorLights(); if (mData.x10_animData || mData.x1c_normalModel) x64_modelData = std::make_unique(std::move(mData)); + xd0_ = params.x64_; xd8_nonLoopingSfxHandles.resize(2); + xe4_27_ = true; + xe4_28_ = true; + xe4_29_actorLightsDirty = true; + xe4_31_lightsDirty = true; + xe5_27_useInSortedLists = true; + xe5_28_callTouch = true; + xe5_29_ = params.x58_24_; + xe5_30_ = params.x58_26_; + xe6_27_renderVisorFlags = u8(params.x58_25_thermalHeat ? 2 : 1); + xe6_29_ = true; + xe6_31_targetableVisorFlags = params.GetVisorParameters().GetMask(); + xe7_27_ = true; + xe7_29_actorActive = active; + xe7_30_doTargetDistanceTest = true; + xe7_31_targetable = true; + if (x64_modelData) + { + if (params.x44_xrayAssets.first.IsValid()) + x64_modelData->SetXRayModel(params.x44_xrayAssets); + if (params.x4c_thermalAssets.first.IsValid()) + x64_modelData->SetInfraModel(params.x4c_thermalAssets); + if (!params.x0_lightParms.x1c_makeLights || params.x0_lightParms.x3c_maxAreaLights == 0) + x64_modelData->x18_ambientColor = params.x0_lightParms.x18_noLightsAmbient; + x64_modelData->x14_25_sortThermal = !params.x58_27_noSortThermal; + } + if (params.x40_scanParms.GetScanId().IsValid()) + x98_scanObjectInfo = g_SimplePool->GetObj(SObjectTag{FOURCC('SCAN'), params.x40_scanParms.GetScanId()}); } void CActor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) @@ -499,14 +530,9 @@ bool CActor::CanDrawStatic() const const CScannableObjectInfo* CActor::GetScannableObjectInfo() const { - if (!x98_scanObjectInfo) + if (!x98_scanObjectInfo || !x98_scanObjectInfo.IsLoaded()) return nullptr; - - TToken& info = *x98_scanObjectInfo; - if (!info || !info.IsLoaded()) - return nullptr; - - return info.GetObj(); + return x98_scanObjectInfo.GetObj(); } void CActor::SetCalculateLighting(bool c) diff --git a/Runtime/World/CActor.hpp b/Runtime/World/CActor.hpp index b5e46809c..88776e4e1 100644 --- a/Runtime/World/CActor.hpp +++ b/Runtime/World/CActor.hpp @@ -36,15 +36,15 @@ protected: CSfxHandle x8c_loopingSfxHandle; std::unique_ptr x90_actorLights; std::unique_ptr x94_simpleShadow; - std::unique_ptr> x98_scanObjectInfo; + TLockedToken x98_scanObjectInfo; zeus::CAABox x9c_renderBounds; CModelFlags xb4_drawFlags; float xbc_time = 0.f; float xc0_pitchBend = 0.f; TUniqueId xc4_fluidId = kInvalidUniqueId; - TUniqueId xc6_nextDrawNode = kInvalidUniqueId; - u32 xc8_drawnToken = -1; - u32 xcc_addedToken = -1; + TUniqueId xc6_nextDrawNode; + int xc8_drawnToken = -1; + int xcc_addedToken = -1; float xd0_; float xd4_maxVol = 1.f; rstl::reserved_vector xd8_nonLoopingSfxHandles; @@ -63,14 +63,17 @@ protected: bool xe5_26_muted : 1; bool xe5_27_useInSortedLists : 1; bool xe5_28_callTouch : 1; + bool xe5_29_ : 1; + bool xe5_30_ : 1; bool xe5_31_ : 1; u8 xe6_24_fluidCounter : 3; - u8 xe6_27_renderVisorFlags : 3; // 2: thermal cold, 4: thermal hot + u8 xe6_27_renderVisorFlags : 2; // 1: thermal cold, 2: thermal hot + bool xe6_29_ : 1; bool xe6_30_enablePitchBend : 1; u8 xe6_31_targetableVisorFlags : 4; bool xe7_27_ : 1; bool xe7_28_worldLightingDirty : 1; - bool xe7_29_ : 1; + bool xe7_29_actorActive : 1; bool xe7_30_doTargetDistanceTest : 1; bool xe7_31_targetable : 1; }; @@ -94,8 +97,8 @@ public: Done, }; - CActor(TUniqueId, bool, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, - const CMaterialList&, const CActorParameters&, TUniqueId); + CActor(TUniqueId uid, bool active, std::string_view name, const CEntityInfo& info, const zeus::CTransform&, + CModelData&& mData, const CMaterialList& list, const CActorParameters& params, TUniqueId otherUid); virtual void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); virtual void SetActive(bool active) @@ -103,7 +106,7 @@ public: xe4_27_ = true; xe4_28_ = true; xe4_29_actorLightsDirty = true; - xe7_29_ = true; + xe7_29_actorActive = active; CEntity::SetActive(active); } virtual void PreRender(CStateManager&, const zeus::CFrustum&) {} @@ -177,7 +180,7 @@ public: const CActorLights* GetActorLights() const { return x90_actorLights.get(); } CActorLights* ActorLights() { return x90_actorLights.get(); } bool CanDrawStatic() const; - bool GetE7_29() const { return xe7_29_; } + bool IsActorActive() const { return xe7_29_actorActive; } void SetWorldLightingDirty(bool b) { xe7_28_worldLightingDirty = b; } const CScannableObjectInfo* GetScannableObjectInfo() const; const CHealthInfo* GetHealthInfo(const CStateManager& mgr) const diff --git a/Runtime/World/CActorParameters.hpp b/Runtime/World/CActorParameters.hpp index 5e535efba..8d1fc6d79 100644 --- a/Runtime/World/CActorParameters.hpp +++ b/Runtime/World/CActorParameters.hpp @@ -11,6 +11,7 @@ namespace urde class CActorParameters { friend class ScriptLoader; + friend class CActor; CLightParameters x0_lightParms; CScannableParameters x40_scanParms; std::pair x44_xrayAssets = {}; @@ -23,7 +24,7 @@ class CActorParameters bool x58_24_ : 1; bool x58_25_thermalHeat : 1; bool x58_26_ : 1; - bool x58_27_ : 1; + bool x58_27_noSortThermal : 1; }; u32 _dummy = 0; }; @@ -32,7 +33,7 @@ class CActorParameters float x64_ = 0.f; public: - CActorParameters() : x58_24_(true), x58_25_thermalHeat(false), x58_26_(false), x58_27_(false) {} + CActorParameters() : x58_24_(true), x58_25_thermalHeat(false), x58_26_(false), x58_27_noSortThermal(false) {} CActorParameters(const CLightParameters& lightParms, const CScannableParameters& scanParms, const std::pair& xrayAssets, const std::pair& thermalAssets, const CVisorParameters& visorParms, bool b1, bool thermalHeat, bool c, bool d) @@ -44,7 +45,7 @@ public: , x58_24_(b1) , x58_25_thermalHeat(thermalHeat) , x58_26_(c) - , x58_27_(d) + , x58_27_noSortThermal(d) { } CActorParameters Scannable(const CScannableParameters& sParms) const diff --git a/Runtime/World/CLightParameters.hpp b/Runtime/World/CLightParameters.hpp index df13ea36f..62cd3444f 100644 --- a/Runtime/World/CLightParameters.hpp +++ b/Runtime/World/CLightParameters.hpp @@ -10,6 +10,7 @@ namespace urde class CLightParameters { + friend class CActor; public: enum class EShadowTesselation { diff --git a/Runtime/World/CScannableParameters.hpp b/Runtime/World/CScannableParameters.hpp index 8c2680e77..3729235ce 100644 --- a/Runtime/World/CScannableParameters.hpp +++ b/Runtime/World/CScannableParameters.hpp @@ -13,6 +13,7 @@ class CScannableParameters public: CScannableParameters() = default; CScannableParameters(CAssetId id) : x0_scanId(id) {} + CAssetId GetScanId() const { return x0_scanId; } }; } diff --git a/Runtime/World/CScriptActor.cpp b/Runtime/World/CScriptActor.cpp index 02f748842..17f822ac9 100644 --- a/Runtime/World/CScriptActor.cpp +++ b/Runtime/World/CScriptActor.cpp @@ -30,7 +30,7 @@ CScriptActor::CScriptActor(TUniqueId uid, std::string_view name, const CEntityIn , x2e2_29_((x2e2_24_ && x2e2_25_dead && x2d8_ != 0)) , x2e2_30_transposeRotate(b4) , x2e2_31_(b5) -, x2e3_24_(false) +, x2e3_24_cameraMoveIntoAlpha(false) { if (x64_modelData && (x64_modelData->HasAnimData() || x64_modelData->HasNormalModel()) && castsShadow) CreateShadow(true); diff --git a/Runtime/World/CScriptActor.hpp b/Runtime/World/CScriptActor.hpp index 7a524a70a..cce54311a 100644 --- a/Runtime/World/CScriptActor.hpp +++ b/Runtime/World/CScriptActor.hpp @@ -27,7 +27,7 @@ protected: bool x2e2_29_ : 1; bool x2e2_30_transposeRotate : 1; bool x2e2_31_ : 1; - bool x2e3_24_ : 1; + bool x2e3_24_cameraMoveIntoAlpha : 1; public: CScriptActor(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, @@ -44,7 +44,7 @@ public: void Touch(CActor&, CStateManager&); const CDamageVulnerability* GetDamageVulnerability() const { return &x268_damageVulnerability; } CHealthInfo* HealthInfo(CStateManager&) { return &x260_currentHealth; } - bool GetX2E3_24() const { return x2e3_24_; } + bool IsCameraMoveIntoAlpha() const { return x2e3_24_cameraMoveIntoAlpha; } }; }; diff --git a/Runtime/World/CScriptAiJumpPoint.cpp b/Runtime/World/CScriptAiJumpPoint.cpp index 4f162c76f..af1974c6a 100644 --- a/Runtime/World/CScriptAiJumpPoint.cpp +++ b/Runtime/World/CScriptAiJumpPoint.cpp @@ -45,9 +45,7 @@ void CScriptAiJumpPoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId oth if (wpnt) { x10c_currentWaypoint = wpnt->GetUniqueId(); - const CScriptWaypoint* nextWpnt = wpnt->NextWaypoint(mgr); - if (nextWpnt) - x10e_nextWaypoint = nextWpnt->GetUniqueId(); + x10e_nextWaypoint = wpnt->NextWaypoint(mgr); } } } diff --git a/Runtime/World/CScriptCameraWaypoint.cpp b/Runtime/World/CScriptCameraWaypoint.cpp index a3d1cad15..e97216808 100644 --- a/Runtime/World/CScriptCameraWaypoint.cpp +++ b/Runtime/World/CScriptCameraWaypoint.cpp @@ -7,10 +7,10 @@ namespace urde { CScriptCameraWaypoint::CScriptCameraWaypoint(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, bool active, float f1, u32 w1) + const zeus::CTransform& xf, bool active, float hfov, u32 w1) : CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::Unknown), CActorParameters::None(), kInvalidUniqueId) -, xe8_(f1) +, xe8_hfov(hfov) , xec_(w1) { diff --git a/Runtime/World/CScriptCameraWaypoint.hpp b/Runtime/World/CScriptCameraWaypoint.hpp index 77c15f90a..882d90c11 100644 --- a/Runtime/World/CScriptCameraWaypoint.hpp +++ b/Runtime/World/CScriptCameraWaypoint.hpp @@ -8,17 +8,18 @@ namespace urde class CScriptCameraWaypoint : public CActor { - float xe8_; + float xe8_hfov; u32 xec_; public: CScriptCameraWaypoint(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, bool active, float, u32); + const zeus::CTransform& xf, bool active, float hfov, u32); void Accept(IVisitor& visitor); void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const {} void Render(const CStateManager&) const {} TUniqueId GetRandomNextWaypointId(CStateManager& mgr) const; + float GetHFov() const { return xe8_hfov; } }; } diff --git a/Runtime/World/CScriptPlayerActor.cpp b/Runtime/World/CScriptPlayerActor.cpp index cbea0e42d..df5f91371 100644 --- a/Runtime/World/CScriptPlayerActor.cpp +++ b/Runtime/World/CScriptPlayerActor.cpp @@ -38,7 +38,7 @@ void CScriptPlayerActor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid void CScriptPlayerActor::SetActive(bool active) { CActor::SetActive(active); - xe7_29_ = true; + xe7_29_actorActive = true; } void CScriptPlayerActor::PreRender(CStateManager&, const zeus::CFrustum&) diff --git a/Runtime/World/CScriptTrigger.cpp b/Runtime/World/CScriptTrigger.cpp index 8304645cb..6c3fdee59 100644 --- a/Runtime/World/CScriptTrigger.cpp +++ b/Runtime/World/CScriptTrigger.cpp @@ -23,6 +23,7 @@ CScriptTrigger::CScriptTrigger(TUniqueId uid, std::string_view name, const CEnti { x148_26_deactivateOnEntered = deactivateOnEntered; x148_27_deactivateOnExited = deactivateOnExited; + SetCallTouch(false); } void CScriptTrigger::Accept(IVisitor& visitor) { visitor.Visit(this); } diff --git a/Runtime/World/CScriptWaypoint.cpp b/Runtime/World/CScriptWaypoint.cpp index 4a087b1f1..31159dbc7 100644 --- a/Runtime/World/CScriptWaypoint.cpp +++ b/Runtime/World/CScriptWaypoint.cpp @@ -1,18 +1,20 @@ #include "CScriptWaypoint.hpp" -#include "Character/CModelData.hpp" -#include "Collision/CMaterialList.hpp" #include "CActorParameters.hpp" #include "TCastTo.hpp" +#include "CStateManager.hpp" namespace urde { CScriptWaypoint::CScriptWaypoint(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, bool active, float, float, - u32, u32, u32, u32, u32, u32, u32) + const zeus::CTransform& xf, bool active, float f1, float f2, + u32 w1, u32 w2, u32 w3, u32 w4, u32 w5, u32 w6, u32 w7) : CActor(uid, active, name, info, xf, CModelData(), CMaterialList(), - CActorParameters::None(), kInvalidUniqueId) + CActorParameters::None(), kInvalidUniqueId), + xe8_(f1), xec_(w7), xf0_(f2), xf4_(w1), xf5_(w2), xf6_(w3), xf7_(w4), xf8_(w5), xfa_jumpFlags(w6) { + SetUseInSortedLists(false); + SetCallTouch(false); } void CScriptWaypoint::Accept(IVisitor& visitor) @@ -20,4 +22,46 @@ void CScriptWaypoint::Accept(IVisitor& visitor) visitor.Visit(this); } +void CScriptWaypoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) +{ + CActor::AcceptScriptMsg(msg, sender, mgr); + if (GetActive()) + if (msg == EScriptObjectMessage::Arrived) + SendScriptMsgs(EScriptObjectState::Arrived, mgr, EScriptObjectMessage::None); +} + +void CScriptWaypoint::AddToRenderer(const zeus::CFrustum&, const CStateManager&) const +{ + // Empty +} + +TUniqueId CScriptWaypoint::FollowWaypoint(CStateManager& mgr) const +{ + for (const SConnection& conn : x20_conns) + if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Follow) + return mgr.GetIdForScript(conn.x8_objId); + return kInvalidUniqueId; +} + +TUniqueId CScriptWaypoint::NextWaypoint(CStateManager& mgr) const +{ + rstl::reserved_vector ids; + for (const SConnection& conn : x20_conns) + { + if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Next) + { + TUniqueId id = mgr.GetIdForScript(conn.x8_objId); + if (id != kInvalidUniqueId) + if (TCastToConstPtr wp = mgr.GetObjectById(id)) + if (wp->GetActive()) + ids.push_back(wp->GetUniqueId()); + } + } + + if (ids.size() == 0) + return kInvalidUniqueId; + + return ids[int(mgr.GetActiveRandom()->Float() * ids.size() * 0.99f)]; +} + } diff --git a/Runtime/World/CScriptWaypoint.hpp b/Runtime/World/CScriptWaypoint.hpp index 7125b0053..565fad12a 100644 --- a/Runtime/World/CScriptWaypoint.hpp +++ b/Runtime/World/CScriptWaypoint.hpp @@ -8,6 +8,14 @@ namespace urde class CScriptWaypoint : public CActor { + float xe8_; + u32 xec_; + float xf0_; + bool xf4_; + bool xf5_; + bool xf6_; + bool xf7_; + bool xf8_; u16 xfa_jumpFlags; public: CScriptWaypoint(TUniqueId, std::string_view, const CEntityInfo&, @@ -15,8 +23,10 @@ public: u32, u32, u32, u32, u32, u32, u32); void Accept(IVisitor& visitor); - - const CScriptWaypoint* NextWaypoint(CStateManager&) const { return nullptr; } + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr); + void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; + TUniqueId FollowWaypoint(CStateManager& mgr) const; + TUniqueId NextWaypoint(CStateManager& mgr) const; }; } diff --git a/Runtime/World/CVisorParameters.hpp b/Runtime/World/CVisorParameters.hpp index 49be372bc..999f891f1 100644 --- a/Runtime/World/CVisorParameters.hpp +++ b/Runtime/World/CVisorParameters.hpp @@ -9,15 +9,16 @@ namespace urde class CVisorParameters { public: - u32 x0_mask : 4; + u8 x0_mask : 4; bool x0_4_b1 : 1; bool x0_5_b2 : 1; bool x0_28_b3 : 1; bool x0_29_b4 : 1; CVisorParameters() : x0_mask(0xf), x0_4_b1(false), x0_5_b2(false) {} - CVisorParameters(u32 mask, bool b1, bool b2) + CVisorParameters(u8 mask, bool b1, bool b2) : x0_mask(mask), x0_4_b1(b1), x0_5_b2(b2) {} + u8 GetMask() const { return x0_mask; } }; } diff --git a/hecl b/hecl index 2bfe803bf..2064c5ed2 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit 2bfe803bf63aa17af34adac7c7b317dc8c646467 +Subproject commit 2064c5ed258337bf71a2c855ab17592abf86e0d1 diff --git a/specter b/specter index 155d45537..726c42873 160000 --- a/specter +++ b/specter @@ -1 +1 @@ -Subproject commit 155d4553794a7428090c453c30dd15e17d0961f0 +Subproject commit 726c42873311435b263e6bc41444b393f13abee2