Various bug fixes

This commit is contained in:
Jack Andersen 2017-11-23 22:23:28 -10:00
parent 41edf5a226
commit 6854cb9df7
36 changed files with 843 additions and 228 deletions

View File

@ -4,6 +4,13 @@
namespace urde namespace urde
{ {
template <typename T, typename S>
static std::remove_reference_t<decltype(std::declval<T>()[0])>& AccessElement(T& arr, S idx)
{
assert(std::extent<T>::value > idx && idx >= 0);
return arr[idx];
}
CSortedListManager::CSortedListManager() CSortedListManager::CSortedListManager()
{ {
Reset(); Reset();
@ -20,17 +27,17 @@ void CSortedListManager::AddToLinkedList(s16 nodeId, s16& headId, s16& tailId) c
{ {
if (headId == -1) if (headId == -1)
{ {
const_cast<SNode&>(x0_nodes[nodeId]).x28_next = headId; const_cast<SNode&>(AccessElement(x0_nodes, nodeId)).x28_next = headId;
headId = nodeId; headId = nodeId;
tailId = nodeId; tailId = nodeId;
} }
else else
{ {
if (x0_nodes[nodeId].x28_next != -1) if (AccessElement(x0_nodes, nodeId).x28_next != -1)
return; return;
if (tailId == nodeId) if (tailId == nodeId)
return; return;
const_cast<SNode&>(x0_nodes[nodeId]).x28_next = headId; const_cast<SNode&>(AccessElement(x0_nodes, nodeId)).x28_next = headId;
headId = nodeId; headId = nodeId;
} }
} }
@ -40,8 +47,8 @@ void CSortedListManager::RemoveFromList(ESortedList list, s16 idx)
SSortedList& sl = xb000_sortedLists[u32(list)]; SSortedList& sl = xb000_sortedLists[u32(list)];
while (idx < sl.x800_size - 1) while (idx < sl.x800_size - 1)
{ {
x0_nodes[sl.x0_ids[idx+1]].x1c_selfIdxs[int(list)] = idx; AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + 1)).x1c_selfIdxs[int(list)] = idx;
sl.x0_ids[idx] = sl.x0_ids[idx+1]; AccessElement(sl.x0_ids, idx) = AccessElement(sl.x0_ids, idx + 1);
++idx; ++idx;
} }
--sl.x800_size; --sl.x800_size;
@ -52,22 +59,24 @@ void CSortedListManager::MoveInList(ESortedList list, s16 idx)
SSortedList& sl = xb000_sortedLists[int(list)]; SSortedList& sl = xb000_sortedLists[int(list)];
while (true) while (true)
{ {
if (idx > 0 || if (idx > 0 &&
x0_nodes[sl.x0_ids[idx-1]].x4_box[idx] > x0_nodes[sl.x0_ids[idx]].x4_box[idx]) 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; AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx - 1)).x1c_selfIdxs[int(list)] = idx;
x0_nodes[sl.x0_ids[idx]].x1c_selfIdxs[int(list)] = idx - 1; AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx)).x1c_selfIdxs[int(list)] = idx - 1;
std::swap(sl.x0_ids[idx], sl.x0_ids[idx-1]); std::swap(AccessElement(sl.x0_ids, idx), AccessElement(sl.x0_ids, idx - 1));
--idx; --idx;
} }
else else
{ {
if (idx >= sl.x800_size - 1) if (idx >= sl.x800_size - 1)
return; 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; return;
x0_nodes[sl.x0_ids[idx+1]].x1c_selfIdxs[int(list)] = idx + 1; AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + 1)).x1c_selfIdxs[int(list)] = idx + 1;
std::swap(sl.x0_ids[idx], sl.x0_ids[idx+1]); std::swap(AccessElement(sl.x0_ids, idx), AccessElement(sl.x0_ids, idx + 1));
} }
} }
} }
@ -79,11 +88,11 @@ void CSortedListManager::InsertInList(ESortedList list, SNode& node)
for (int i = sl.x800_size ; i > 0 ;) for (int i = sl.x800_size ; i > 0 ;)
{ {
/* Binary search cycle to find insert index */ /* 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 */ /* Upper */
insIdx += i / 2 + 1; insIdx = insIdx + i / 2 + 1;
i -= i / 2 - 1; i = i - i / 2 - 1;
} }
else else
{ {
@ -95,12 +104,12 @@ void CSortedListManager::InsertInList(ESortedList list, SNode& node)
/* Shift ids for insert */ /* 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; AccessElement(x0_nodes, AccessElement(sl.x0_ids, i - 1)).x1c_selfIdxs[int(list)] = i;
sl.x0_ids[i] = sl.x0_ids[i-1]; AccessElement(sl.x0_ids, i) = AccessElement(sl.x0_ids, i - 1);
} }
/* Do insert */ /* 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; node.x1c_selfIdxs[int(list)] = insIdx;
++sl.x800_size; ++sl.x800_size;
} }
@ -112,11 +121,11 @@ s16 CSortedListManager::FindInListUpper(ESortedList list, float val) const
for (int i = sl.x800_size ; i > 0 ;) for (int i = sl.x800_size ; i > 0 ;)
{ {
/* Binary search cycle to find index */ /* 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 */ /* Upper */
idx += i / 2 + 1; idx = idx + i / 2 + 1;
i -= i / 2 - 1; i = i - i / 2 - 1;
} }
else else
{ {
@ -134,11 +143,11 @@ s16 CSortedListManager::FindInListLower(ESortedList list, float val) const
for (int i = sl.x800_size ; i > 0 ;) for (int i = sl.x800_size ; i > 0 ;)
{ {
/* Binary search cycle to find index */ /* 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 */ /* Upper */
idx += i / 2 + 1; idx = idx + i / 2 + 1;
i -= i / 2 - 1; i = i - i / 2 - 1;
} }
else else
{ {
@ -193,16 +202,16 @@ s16 CSortedListManager::CalculateIntersections(ESortedList la, ESortedList lb, s
s16 headId = -1; s16 headId = -1;
s16 tailId = -1; s16 tailId = -1;
for (int i=a ; i<b ; ++i) for (int i=a ; i<b ; ++i)
AddToLinkedList(xb000_sortedLists[int(la)].x0_ids[i], headId, tailId); AddToLinkedList(AccessElement(xb000_sortedLists[int(la)].x0_ids, i), headId, tailId);
for (int i=c ; i<d ; ++i) for (int i=c ; i<d ; ++i)
AddToLinkedList(xb000_sortedLists[int(lb)].x0_ids[i], headId, tailId); AddToLinkedList(AccessElement(xb000_sortedLists[int(lb)].x0_ids, i), headId, tailId);
if (a < xb000_sortedLists[int(lb)].x800_size - d) if (a < xb000_sortedLists[int(lb)].x800_size - d)
{ {
for (int i=0 ; i<a ; ++i) for (int i=0 ; i<a ; ++i)
{ {
s16 id = xb000_sortedLists[int(la)].x0_ids[i]; s16 id = AccessElement(xb000_sortedLists[int(la)].x0_ids, i);
if (x0_nodes[id].x1c_selfIdxs[lb] > aabb[int(lb)]) if (AccessElement(x0_nodes, id).x1c_selfIdxs[lb] > aabb[int(lb)])
AddToLinkedList(id, headId, tailId); AddToLinkedList(id, headId, tailId);
} }
} }
@ -210,15 +219,15 @@ s16 CSortedListManager::CalculateIntersections(ESortedList la, ESortedList lb, s
{ {
for (int i=d ; i<xb000_sortedLists[int(lb)].x800_size ; ++i) for (int i=d ; i<xb000_sortedLists[int(lb)].x800_size ; ++i)
{ {
s16 id = xb000_sortedLists[int(lb)].x0_ids[i]; s16 id = AccessElement(xb000_sortedLists[int(lb)].x0_ids, i);
if (x0_nodes[id].x1c_selfIdxs[la] < aabb[int(la)]) if (AccessElement(x0_nodes, id).x1c_selfIdxs[la] < aabb[int(la)])
AddToLinkedList(id, headId, tailId); AddToLinkedList(id, headId, tailId);
} }
} }
for (s16* id = &headId ; *id != -1 ;) for (s16* id = &headId ; *id != -1 ;)
{ {
SNode& node = x0_nodes[*id]; SNode& node = AccessElement(x0_nodes, *id);
if (node.x4_box[int(slA)] > aabb[int(slB)] || if (node.x4_box[int(slA)] > aabb[int(slB)] ||
node.x4_box[int(slB)] < aabb[int(slA)] || node.x4_box[int(slB)] < aabb[int(slA)] ||
node.x4_box[int(slC)] > aabb[int(slD)] || node.x4_box[int(slC)] > aabb[int(slD)] ||
@ -255,7 +264,7 @@ void CSortedListManager::BuildNearList(rstl::reserved_vector<TUniqueId, 1024>& o
s16 id = const_cast<CSortedListManager&>(*this).ConstructIntersectionArray(aabb); s16 id = const_cast<CSortedListManager&>(*this).ConstructIntersectionArray(aabb);
while (id != -1) 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()) && if (&actor != node.x0_actor && filter.Passes(node.x0_actor->GetMaterialList()) &&
node.x0_actor->GetMaterialFilter().Passes(actor.GetMaterialList())) node.x0_actor->GetMaterialFilter().Passes(actor.GetMaterialList()))
out.push_back(node.x0_actor->GetUniqueId()); out.push_back(node.x0_actor->GetUniqueId());
@ -271,7 +280,7 @@ void CSortedListManager::BuildNearList(rstl::reserved_vector<TUniqueId, 1024>& o
s16 id = const_cast<CSortedListManager&>(*this).ConstructIntersectionArray(aabb); s16 id = const_cast<CSortedListManager&>(*this).ConstructIntersectionArray(aabb);
while (id != -1) 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())) if (actor != node.x0_actor && filter.Passes(node.x0_actor->GetMaterialList()))
out.push_back(node.x0_actor->GetUniqueId()); out.push_back(node.x0_actor->GetUniqueId());
@ -282,7 +291,7 @@ void CSortedListManager::BuildNearList(rstl::reserved_vector<TUniqueId, 1024>& o
void CSortedListManager::Remove(const CActor* act) 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) if (!node.x2a_populated)
return; return;
@ -297,7 +306,7 @@ void CSortedListManager::Remove(const CActor* act)
void CSortedListManager::Move(const CActor* act, const zeus::CAABox& aabb) 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; node.x4_box = aabb;
MoveInList(ESortedList::MinX, node.x1c_selfIdxs[0]); 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) 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) if (node.x2a_populated)
{ {
Move(act, aabb); Move(act, aabb);
@ -331,7 +340,7 @@ bool CSortedListManager::ActorInLists(const CActor* act) const
{ {
if (!act) if (!act)
return false; return false;
const SNode& node = x0_nodes[act->GetUniqueId().Value()]; const SNode& node = AccessElement(x0_nodes, act->GetUniqueId().Value());
return node.x2a_populated; return node.x2a_populated;
} }

View File

@ -271,25 +271,25 @@ void CStateManager::UpdateThermalVisor()
void CStateManager::RendererDrawCallback(const void* drawable, const void* ctx, int type) void CStateManager::RendererDrawCallback(const void* drawable, const void* ctx, int type)
{ {
CStateManager& mgr = reinterpret_cast<CStateManager&>(ctx); const CStateManager& mgr = *reinterpret_cast<const CStateManager*>(ctx);
switch (type) switch (type)
{ {
case 0: case 0:
{ {
CActor& actor = reinterpret_cast<CActor&>(drawable); const CActor& actor = *reinterpret_cast<const CActor*>(drawable);
if (actor.xc8_drawnToken == mgr.x8dc_objectDrawToken) if (actor.xc8_drawnToken == mgr.x8dc_objectDrawToken)
break; break;
if (actor.xc6_nextDrawNode != kInvalidUniqueId) if (actor.xc6_nextDrawNode != kInvalidUniqueId)
mgr.RecursiveDrawTree(actor.xc6_nextDrawNode); mgr.RecursiveDrawTree(actor.xc6_nextDrawNode);
actor.Render(mgr); actor.Render(mgr);
actor.xc8_drawnToken = mgr.x8dc_objectDrawToken; const_cast<CActor&>(actor).xc8_drawnToken = mgr.x8dc_objectDrawToken;
break; break;
} }
case 1: case 1:
reinterpret_cast<CSimpleShadow&>(drawable).Render(mgr.x8f0_shadowTex.GetObj()); reinterpret_cast<const CSimpleShadow*>(drawable)->Render(mgr.x8f0_shadowTex.GetObj());
break; break;
case 2: case 2:
reinterpret_cast<CDecal&>(drawable).Render(); reinterpret_cast<const CDecal*>(drawable)->Render();
break; break;
default: break; default: break;
} }
@ -711,7 +711,7 @@ void CStateManager::DrawWorld() const
for (TUniqueId id : x86c_stateManagerContainer->xf370_) for (TUniqueId id : x86c_stateManagerContainer->xf370_)
if (const CActor* ent = static_cast<const CActor*>(GetObjectById(id))) if (const CActor* ent = static_cast<const CActor*>(GetObjectById(id)))
if (!thermal || ent->xe6_27_renderVisorFlags & 0x2) if (!thermal || ent->xe6_27_renderVisorFlags & 0x1)
ent->Render(*this); ent->Render(*this);
bool morphingPlayerVisible = false; bool morphingPlayerVisible = false;
@ -728,7 +728,7 @@ void CStateManager::DrawWorld() const
{ {
if (TCastToPtr<CActor> actor = ent) if (TCastToPtr<CActor> actor = ent)
{ {
if (!actor->xe7_29_) if (!actor->xe7_29_actorActive)
continue; continue;
TUniqueId actorId = actor->GetUniqueId(); TUniqueId actorId = actor->GetUniqueId();
if (!thermal && area.LookupPVSUniqueID(actorId) == actorId) if (!thermal && area.LookupPVSUniqueID(actorId) == actorId)
@ -749,9 +749,9 @@ void CStateManager::DrawWorld() const
continue; continue;
} }
} }
if (!thermal || actor->xe6_27_renderVisorFlags & 0x2) if (!thermal || actor->xe6_27_renderVisorFlags & 0x1)
actor->AddToRenderer(frustum, *this); actor->AddToRenderer(frustum, *this);
if (thermal && actor->xe6_27_renderVisorFlags & 0x4) if (thermal && actor->xe6_27_renderVisorFlags & 0x2)
thermalActorArr[thermalActorCount++] = actor.GetPtr(); thermalActorArr[thermalActorCount++] = actor.GetPtr();
} }
} }
@ -787,7 +787,7 @@ void CStateManager::DrawWorld() const
CGraphics::SetDepthRange(0.015625f, 0.03125f); CGraphics::SetDepthRange(0.015625f, 0.03125f);
for (TUniqueId id : x86c_stateManagerContainer->xf39c_renderLast) for (TUniqueId id : x86c_stateManagerContainer->xf39c_renderLast)
if (const CActor* actor = static_cast<const CActor*>(GetObjectById(id))) if (const CActor* actor = static_cast<const CActor*>(GetObjectById(id)))
if (actor->xe6_27_renderVisorFlags & 0x2) if (actor->xe6_27_renderVisorFlags & 0x1)
actor->Render(*this); actor->Render(*this);
CGraphics::SetDepthRange(0.125f, 1.f); CGraphics::SetDepthRange(0.125f, 1.f);
} }
@ -795,7 +795,7 @@ void CStateManager::DrawWorld() const
for (TUniqueId id : x86c_stateManagerContainer->xf370_) for (TUniqueId id : x86c_stateManagerContainer->xf370_)
if (const CActor* actor = static_cast<const CActor*>(GetObjectById(id))) if (const CActor* actor = static_cast<const CActor*>(GetObjectById(id)))
if (actor->xe6_27_renderVisorFlags & 0x4) if (actor->xe6_27_renderVisorFlags & 0x2)
actor->Render(*this); actor->Render(*this);
for (int i=areaCount-1 ; i>=0 ; --i) for (int i=areaCount-1 ; i>=0 ; --i)
@ -858,7 +858,7 @@ void CStateManager::DrawWorld() const
CGraphics::SetDepthRange(0.015625f, 0.03125f); CGraphics::SetDepthRange(0.015625f, 0.03125f);
for (TUniqueId id : x86c_stateManagerContainer->xf39c_renderLast) for (TUniqueId id : x86c_stateManagerContainer->xf39c_renderLast)
if (const CActor* actor = static_cast<const CActor*>(GetObjectById(id))) if (const CActor* actor = static_cast<const CActor*>(GetObjectById(id)))
if (actor->xe6_27_renderVisorFlags & 0x4) if (actor->xe6_27_renderVisorFlags & 0x2)
actor->Render(*this); actor->Render(*this);
CGraphics::SetDepthRange(0.125f, 1.f); CGraphics::SetDepthRange(0.125f, 1.f);
} }
@ -943,7 +943,7 @@ void CStateManager::PreRender()
{ {
if (TCastToPtr<CActor> act = ent) if (TCastToPtr<CActor> act = ent)
{ {
if (act->GetE7_29()) if (act->IsActorActive())
{ {
act->CalculateRenderBounds(); act->CalculateRenderBounds();
act->PreRender(*this, frustum); act->PreRender(*this, frustum);
@ -2071,7 +2071,7 @@ void CStateManager::CrossTouchActors()
continue; continue;
rstl::optional_object<zeus::CAABox> touchAABB2 = ent2->GetTouchBounds(); rstl::optional_object<zeus::CAABox> touchAABB2 = ent2->GetTouchBounds();
if (!ent2->GetActive() || touchAABB2) if (!ent2->GetActive() || !touchAABB2)
continue; continue;
if (visits[ent2->GetUniqueId().Value()]) if (visits[ent2->GetUniqueId().Value()])

View File

@ -12,6 +12,7 @@
#include "World/CScriptCameraHint.hpp" #include "World/CScriptCameraHint.hpp"
#include "CPathCamera.hpp" #include "CPathCamera.hpp"
#include "World/CScriptSpindleCamera.hpp" #include "World/CScriptSpindleCamera.hpp"
#include "World/CExplosion.hpp"
namespace urde namespace urde
{ {
@ -80,7 +81,54 @@ int CCameraManager::AddCameraShaker(const CCameraShakeData& data, bool sfx)
return x2c_lastShakeId; 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<CExplosion> explo = ent)
{
mgr.FreeScriptObject(explo->GetUniqueId());
}
else if (TCastToPtr<CWeapon> weap = ent)
{
if (weap->GetActive())
{
if ((weap->GetAttribField() & CWeapon::EProjectileAttrib::KeepInCinematic) ==
CWeapon::EProjectileAttrib::None)
{
if (TCastToConstPtr<CAi>(mgr.GetObjectById(weap->GetOwnerId())) ||
TCastToConstPtr<CPlayer>(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<CCinematicCamera> 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) void CCameraManager::SetInsideFluid(bool val, TUniqueId fluidId)
{ {

View File

@ -82,6 +82,8 @@ class CCameraManager
void SkipBallCameraCinematic(CStateManager& mgr); void SkipBallCameraCinematic(CStateManager& mgr);
void ApplyCameraHint(const CScriptCameraHint& hint, CStateManager& mgr); void ApplyCameraHint(const CScriptCameraHint& hint, CStateManager& mgr);
void EnterCinematic(CStateManager& mgr);
public: public:
CCameraManager(TUniqueId curCameraId=kInvalidUniqueId); CCameraManager(TUniqueId curCameraId=kInvalidUniqueId);

View File

@ -3,6 +3,9 @@
#include "World/CPlayer.hpp" #include "World/CPlayer.hpp"
#include "World/CScriptActor.hpp" #include "World/CScriptActor.hpp"
#include "TCastTo.hpp" #include "TCastTo.hpp"
#include "World/CScriptCameraWaypoint.hpp"
#include "GameGlobalObjects.hpp"
#include "Character/CAnimTreeNode.hpp"
namespace urde namespace urde
{ {
@ -11,7 +14,7 @@ CCinematicCamera::CCinematicCamera(TUniqueId uid, std::string_view name, const C
const zeus::CTransform& xf, bool active, float shotDuration, const zeus::CTransform& xf, bool active, float shotDuration,
float fovy, float znear, float zfar, float aspect, u32 flags) float fovy, float znear, float zfar, float aspect, u32 flags)
: CGameCamera(uid, active, name, info, xf, fovy, znear, zfar, aspect, kInvalidUniqueId, flags & 0x20, 0), : 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; x220_24_ = false;
} }
@ -37,12 +40,194 @@ void CCinematicCamera::WasDeactivated(CStateManager& mgr)
mgr.GetPlayer().GetMorphBall()->LoadMorphBallModel(mgr); mgr.GetPlayer().GetMorphBall()->LoadMorphBallModel(mgr);
if (x21c_flags & 0x100) if (x21c_flags & 0x100)
mgr.SetCinematicPause(false); mgr.SetCinematicPause(false);
x188_.clear(); x188_viewPoints.clear();
x198_.clear(); x198_viewOrientations.clear();
x1a8_.clear(); x1a8_viewPointArrivals.clear();
x1b8_.clear(); x1b8_targets.clear();
x1c8_.clear(); x1c8_targetArrivals.clear();
x1d8_.clear(); x1d8_viewHFovs.clear();
}
zeus::CVector3f
CCinematicCamera::GetInterpolatedSplinePoint(const std::vector<zeus::CVector3f>& 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<zeus::CQuaternion>& 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<float>& 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<CActor> 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<CScriptActor> 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) 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); TUniqueId id = mgr.GetIdForScript(conn.x8_objId);
if (TCastToPtr<CScriptActor> act = mgr.ObjectById(id)) if (TCastToPtr<CScriptActor> act = mgr.ObjectById(id))
{ {
if (act->GetX2E3_24()) if (act->IsCameraMoveIntoAlpha())
{ {
x20c_lookAtId = id; x20c_lookAtId = id;
if (conn.x4_msg != EScriptObjectMessage::Deactivate && if (conn.x4_msg != EScriptObjectMessage::Deactivate &&
@ -71,17 +256,17 @@ void CCinematicCamera::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid,
break; break;
case EScriptObjectMessage::Activate: case EScriptObjectMessage::Activate:
CalculateWaypoints(mgr); CalculateWaypoints(mgr);
if ((x21c_flags & 1) == 0 && x220_24_ && x1b8_.empty()) if ((x21c_flags & 1) == 0 && x220_24_ && x1b8_targets.empty())
break; break;
x1ec_ = 0.f; x1ec_t = 0.f;
Think(0.f, mgr); Think(0.f, mgr);
mgr.GetCameraManager()->AddCinemaCamera(GetUniqueId(), mgr); mgr.GetCameraManager()->AddCinemaCamera(GetUniqueId(), mgr);
x1f4_ = 0; x1f4_passedViewPoint = 0;
if (x1a8_.size() > 0) if (x1a8_viewPointArrivals.size() > 0)
SendArrivedMsg(x1a8_[x1f4_], mgr); SendArrivedMsg(x1a8_viewPointArrivals[x1f4_passedViewPoint], mgr);
x1f8_ = 0; x1f8_passedTarget = 0;
if (x1c8_.size() > 0) if (x1c8_targetArrivals.size() > 0)
SendArrivedMsg(x1c8_[x1f8_], mgr); SendArrivedMsg(x1c8_targetArrivals[x1f8_passedTarget], mgr);
if (x21c_flags & 0x100) if (x21c_flags & 0x100)
mgr.SetCinematicPause(true); mgr.SetCinematicPause(true);
break; 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<CScriptActor> 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<SConnection>& 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<CActor> 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<CActor> 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) 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<CActor> 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<CScriptCameraWaypoint> 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<CActor> 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) void CCinematicCamera::SendArrivedMsg(TUniqueId reciever, CStateManager& mgr)

View File

@ -8,35 +8,48 @@ namespace urde
class CCinematicCamera : public CGameCamera class CCinematicCamera : public CGameCamera
{ {
std::vector<zeus::CVector3f> x188_; std::vector<zeus::CVector3f> x188_viewPoints;
std::vector<zeus::CQuaternion> x198_; std::vector<zeus::CQuaternion> x198_viewOrientations;
std::vector<TUniqueId> x1a8_; std::vector<TUniqueId> x1a8_viewPointArrivals;
std::vector<zeus::CVector3f> x1b8_; std::vector<zeus::CVector3f> x1b8_targets;
std::vector<TUniqueId> x1c8_; std::vector<TUniqueId> x1c8_targetArrivals;
std::vector<float> x1d8_; std::vector<float> x1d8_viewHFovs;
float x1e8_duration; float x1e8_duration;
float x1ec_ = 0.f; float x1ec_t = 0.f;
float x1f0_origFovy; float x1f0_origFovy;
u32 x1f4_ = 0; int x1f4_passedViewPoint = 0;
u32 x1f8_ = 0; int x1f8_passedTarget = 0;
zeus::CQuaternion x1fc_; zeus::CQuaternion x1fc_origOrientation;
TUniqueId x20c_lookAtId = kInvalidUniqueId; TUniqueId x20c_lookAtId = kInvalidUniqueId;
zeus::CVector3f x210_; zeus::CVector3f x210_moveIntoEyePos;
u32 x21c_flags; 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_; bool x220_24_;
zeus::CVector3f GetInterpolatedSplinePoint(const std::vector<zeus::CVector3f>& points, int& idxOut, float t) const;
zeus::CQuaternion GetInterpolatedOrientation(const std::vector<zeus::CQuaternion>& rotations, float t) const;
float GetInterpolatedHFov(const std::vector<float>& 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<SConnection>& conns,
SConnection& randConn, CStateManager& mgr);
void CalculateWaypoints(CStateManager& mgr);
public: public:
CCinematicCamera(TUniqueId uid, std::string_view name, const CEntityInfo& info, CCinematicCamera(TUniqueId uid, std::string_view name, const CEntityInfo& info,
const zeus::CTransform& xf, bool active, float shotDuration, const zeus::CTransform& xf, bool active, float shotDuration,
float fovy, float znear, float zfar, float aspect, u32 flags); float fovy, float znear, float zfar, float aspect, u32 flags);
void Accept(IVisitor& visitor); void Accept(IVisitor& visitor);
void Think(float dt, CStateManager& mgr);
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr); void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr);
void ProcessInput(const CFinalInput&, CStateManager& mgr); void ProcessInput(const CFinalInput&, CStateManager& mgr);
void Reset(const zeus::CTransform&, CStateManager& mgr); void Reset(const zeus::CTransform&, CStateManager& mgr);
u32 GetFlags() const { return x21c_flags; } u32 GetFlags() const { return x21c_flags; }
void WasDeactivated(CStateManager& mgr); void WasDeactivated(CStateManager& mgr);
void CalculateWaypoints(CStateManager& mgr);
void SendArrivedMsg(TUniqueId reciever, CStateManager& mgr); void SendArrivedMsg(TUniqueId reciever, CStateManager& mgr);
float GetDuration() const { return x1e8_duration; }
}; };
} }

View File

@ -24,7 +24,7 @@ CGameCamera::CGameCamera(TUniqueId uid, bool active, std::string_view name, cons
, x184_fov(fovy) , x184_fov(fovy)
{ {
xe7_29_ = false; xe7_29_actorActive = false;
} }
void CGameCamera::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) 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) void CGameCamera::SetActive(bool active)
{ {
CActor::SetActive(active); CActor::SetActive(active);
xe7_29_ = false; xe7_29_actorActive = false;
} }
zeus::CMatrix4f CGameCamera::GetPerspectiveMatrix() const zeus::CMatrix4f CGameCamera::GetPerspectiveMatrix() const
@ -103,9 +103,9 @@ zeus::CTransform CGameCamera::ValidateCameraTransform(const zeus::CTransform& a,
void CGameCamera::UpdatePerspective(float dt) void CGameCamera::UpdatePerspective(float dt)
{ {
if (x174_ > 0.f) if (x174_delayTime > 0.f)
{ {
x174_ -= dt; x174_delayTime -= dt;
return; 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) if (time < 0.f)
{ {
x15c_currentFov = fov; x15c_currentFov = fov;
x170_24_perspDirty = true; x170_24_perspDirty = true;
x184_fov = fov; x184_fov = fov;
x178_ = x174_ = 0.f; x178_ = x174_delayTime = 0.f;
} }
else else
{ {
x174_ = std::max(0.f, f4); x174_delayTime = std::max(0.f, delayTime);
x17c_ = time; x17c_ = time;
x178_ = time; x178_ = time;
x180_ = start; x180_ = start;
@ -154,6 +154,6 @@ void CGameCamera::SkipFovInterpolation()
x170_24_perspDirty = true; x170_24_perspDirty = true;
} }
x178_ = x174_ = 0.f; x178_ = x174_delayTime = 0.f;
} }
} }

View File

@ -24,7 +24,7 @@ protected:
u32 x16c_controllerIdx; u32 x16c_controllerIdx;
bool x170_24_perspDirty : 1; bool x170_24_perspDirty : 1;
bool x170_25_disablesInput : 1; bool x170_25_disablesInput : 1;
float x174_ = 0.f; float x174_delayTime = 0.f;
float x178_ = 0.f; float x178_ = 0.f;
float x17c_ = 0.f; float x17c_ = 0.f;
float x180_; float x180_;
@ -51,7 +51,7 @@ public:
void GetControllerNumber() const; void GetControllerNumber() const;
bool DisablesInput() const; bool DisablesInput() const;
void UpdatePerspective(float); 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(); void SkipFovInterpolation();
}; };
} }

View File

@ -172,6 +172,7 @@ public:
SAdvancementDeltas UpdateAdditiveAnims(float); SAdvancementDeltas UpdateAdditiveAnims(float);
bool IsAdditiveAnimation(u32) const; bool IsAdditiveAnimation(u32) const;
bool IsAdditiveAnimationAdded(u32) const; bool IsAdditiveAnimationAdded(u32) const;
const std::shared_ptr<CAnimTreeNode>& GetRootAnimationTree() const { return x1f8_animRoot; }
const std::shared_ptr<CAnimTreeNode>& GetAdditiveAnimationTree(u32) const; const std::shared_ptr<CAnimTreeNode>& GetAdditiveAnimationTree(u32) const;
bool IsAdditiveAnimationActive(u32) const; bool IsAdditiveAnimationActive(u32) const;
void DelAdditiveAnimation(u32); void DelAdditiveAnimation(u32);

View File

@ -146,7 +146,7 @@ rstl::optional_object<zeus::CAABox> CCollisionActor::GetTouchBounds() const
else if (x258_primitiveType == EPrimitiveType::AABox) else if (x258_primitiveType == EPrimitiveType::AABox)
aabox = {x280_aaboxPrimitive->CalculateAABox(x34_transform)}; aabox = {x280_aaboxPrimitive->CalculateAABox(x34_transform)};
else if (x258_primitiveType == EPrimitiveType::Sphere) 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->max + x304_extendedTouchBounds);
aabox->accumulateBounds(aabox->min - x304_extendedTouchBounds); aabox->accumulateBounds(aabox->min - x304_extendedTouchBounds);

View File

@ -7,7 +7,7 @@ CSimpleShadow::CSimpleShadow(float, float, float, float)
} }
void CSimpleShadow::Render(const CTexture* tex) void CSimpleShadow::Render(const CTexture* tex) const
{ {
} }

View File

@ -10,7 +10,7 @@ class CSimpleShadow
public: public:
CSimpleShadow() = default; CSimpleShadow() = default;
CSimpleShadow(float, float, float, float); CSimpleShadow(float, float, float, float);
void Render(const CTexture* tex); void Render(const CTexture* tex) const;
}; };
} }

View File

@ -150,7 +150,7 @@ void CFluidPlaneShader::PrepareBinding(const boo::ObjToken<boo::IShaderPipeline>
[&](boo::IGraphicsDataFactory::Context& ctx) [&](boo::IGraphicsDataFactory::Context& ctx)
{ {
m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(Vertex), maxVertCount); 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()) switch (ctx.platform())
{ {

View File

@ -460,8 +460,15 @@ static void _BuildShader(std::string& finalVS, std::string& finalFS, int& nextTe
combiner += " colorOut.a = kColor0.a;\n"; combiner += " colorOut.a = kColor0.a;\n";
finalVS = hecl::Format(VS, additionalTCGs.c_str()); char *finalVSs, *finalFSs;
finalFS = hecl::Format(FS, textures.c_str(), combiner.c_str()); 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], 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"; combiner += " colorOut.a = kColor0.a;\n";
finalVS = hecl::Format(VS, additionalTCGs.c_str()); char *finalVSs, *finalFSs;
finalFS = hecl::Format(FSDoor, textures.c_str(), combiner.c_str()); 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<boo::IShaderPipeline> boo::ObjToken<boo::IShaderPipeline>

View File

@ -456,14 +456,20 @@ CFluidPlaneShader::BuildShader(boo::ID3DDataFactory::Context& ctx, const SFluidP
combiner += " colorOut.a = kColor0.a;\n"; combiner += " colorOut.a = kColor0.a;\n";
std::string finalVS = hecl::Format(VS, additionalTCGs.c_str()); char *finalVS, *finalFS;
std::string finalFS = hecl::Format(FS, textures.c_str(), combiner.c_str()); 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, 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::SrcAlpha,
info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::InvSrcAlpha, info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::InvSrcAlpha,
boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false, boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false,
boo::CullMode::None); boo::CullMode::None);
free(finalVS);
free(finalFS);
return ret;
} }
boo::ObjToken<boo::IShaderPipeline> boo::ObjToken<boo::IShaderPipeline>
@ -512,13 +518,19 @@ CFluidPlaneShader::BuildShader(boo::ID3DDataFactory::Context& ctx, const SFluidP
combiner += " colorOut.a = kColor0.a;\n"; combiner += " colorOut.a = kColor0.a;\n";
std::string finalVS = hecl::Format(VS, additionalTCGs.c_str()); char *finalVS, *finalFS;
std::string finalFS = hecl::Format(FSDoor, textures.c_str(), combiner.c_str()); 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, auto ret = ctx.newShaderPipeline(finalVS, finalFS, nullptr, nullptr, nullptr, s_vtxFmt,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false, boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false,
boo::CullMode::None); boo::CullMode::None);
free(finalVS);
free(finalFS);
return ret;
} }
boo::ObjToken<boo::IShaderDataBinding> boo::ObjToken<boo::IShaderDataBinding>

View File

@ -17,7 +17,7 @@ static const char* VS =
" float4 colorIn [[ attribute(4) ]];\n" " float4 colorIn [[ attribute(4) ]];\n"
"};\n" "};\n"
"\n" "\n"
"UBINDING0 uniform FluidPlaneUniform\n" "struct FluidPlaneUniform\n"
"{\n" "{\n"
" float4x4 mv;\n" " float4x4 mv;\n"
" float4x4 mvNorm;\n" " float4x4 mvNorm;\n"
@ -27,13 +27,19 @@ static const char* VS =
"\n" "\n"
"struct VertToFrag\n" "struct VertToFrag\n"
"{\n" "{\n"
" float4 pos : [[ position ]];\n" " float4 pos [[ position ]];\n"
" float4 mvPos;\n" " float4 mvPos;\n"
" float4 mvNorm;\n" " float4 mvNorm;\n"
" float4 mvBinorm;\n" " float4 mvBinorm;\n"
" float4 mvTangent;\n" " float4 mvTangent;\n"
" float4 color;\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"
"\n" "\n"
"vertex VertToFrag vmain(VertData v [[ stage_in ]],\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.mvBinorm = fu.mvNorm * v.binormalIn;\n"
" vtf.mvTangent = fu.mvNorm * v.tangentIn;\n" " vtf.mvTangent = fu.mvNorm * v.tangentIn;\n"
" vtf.color = v.colorIn;\n" " vtf.color = v.colorIn;\n"
" vtf.uvs[0] = (fu.texMtxs[0] * v.posIn).xy;\n" " vtf.uv0 = (fu.texMtxs[0] * v.posIn).xy;\n"
" vtf.uvs[1] = (fu.texMtxs[1] * v.posIn).xy;\n" " vtf.uv1 = (fu.texMtxs[1] * v.posIn).xy;\n"
" vtf.uvs[2] = (fu.texMtxs[2] * v.posIn).xy;\n" " vtf.uv2 = (fu.texMtxs[2] * v.posIn).xy;\n"
"%s" // Additional TCGs here "%s" // Additional TCGs here
" return vtf;\n" " return vtf;\n"
"}\n"; "}\n";
@ -107,13 +113,19 @@ static const char* FS =
"\n" "\n"
"struct VertToFrag\n" "struct VertToFrag\n"
"{\n" "{\n"
" float4 pos : [[ position ]];\n" " float4 pos [[ position ]];\n"
" float4 mvPos;\n" " float4 mvPos;\n"
" float4 mvNorm;\n" " float4 mvNorm;\n"
" float4 mvBinorm;\n" " float4 mvBinorm;\n"
" float4 mvTangent;\n" " float4 mvTangent;\n"
" float4 color;\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"
"\n" "\n"
"fragment float4 fmain(VertToFrag vtf [[ stage_in ]],\n" "fragment float4 fmain(VertToFrag vtf [[ stage_in ]],\n"
@ -130,18 +142,51 @@ static const char* FSDoor =
"using namespace metal;\n" "using namespace metal;\n"
"constexpr sampler samp(address::repeat, filter::linear);\n" "constexpr sampler samp(address::repeat, filter::linear);\n"
"\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" "struct VertToFrag\n"
"{\n" "{\n"
" float4 pos : [[ position ]];\n" " float4 pos [[ position ]];\n"
" float4 mvPos;\n" " float4 mvPos;\n"
" float4 mvNorm;\n" " float4 mvNorm;\n"
" float4 mvBinorm;\n" " float4 mvBinorm;\n"
" float4 mvTangent;\n" " float4 mvTangent;\n"
" float4 color;\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"
"\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" "{\n"
" float4 colorOut;\n" " float4 colorOut;\n"
"%s" // Combiner expression here "%s" // Combiner expression here
@ -190,22 +235,22 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid
if (info.m_hasBumpMap) if (info.m_hasBumpMap)
{ {
bumpMapUv = nextTCG; 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) if (info.m_hasEnvBumpMap)
{ {
envBumpMapUv = nextTCG; 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) if (info.m_hasEnvMap)
{ {
envMapUv = nextTCG; 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) if (info.m_hasLightmap)
{ {
lightmapUv = nextTCG; 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) switch (info.m_type)
@ -215,7 +260,7 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid
case CFluidPlane::EFluidType::Four: case CFluidPlane::EFluidType::Four:
if (info.m_hasLightmap) 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 // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1
// ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS
// Output reg 2 // Output reg 2
@ -253,10 +298,10 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid
if (info.m_hasPatternTex2) if (info.m_hasPatternTex2)
{ {
if (info.m_hasPatternTex1) if (info.m_hasPatternTex1)
combiner += " colorOut = (patternTex1.sample(samp, vtf.uvs[0]) * lu.kColor0 + lighting) *\n" combiner += " colorOut = (patternTex1.sample(samp, vtf.uv0) * lu.kColor0 + lighting) *\n"
" patternTex2.sample(samp, vtf.uvs[1]) + vtf.color;\n"; " patternTex2.sample(samp, vtf.uv1) + vtf.color;\n";
else 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 else
{ {
@ -267,9 +312,9 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid
if (info.m_hasColorTex && !info.m_hasEnvMap && info.m_hasEnvBumpMap) if (info.m_hasColorTex && !info.m_hasEnvMap && info.m_hasEnvBumpMap)
{ {
// Make previous stage indirect, mtx0 // 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); " 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) else if (info.m_hasEnvMap)
{ {
@ -280,15 +325,15 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid
// Make previous stage indirect, mtx0 // Make previous stage indirect, mtx0
if (info.m_hasColorTex) if (info.m_hasColorTex)
combiner += " colorOut += colorTex.sample(samp, vtf.uvs[2]) * lighting;\n"; combiner += " colorOut += colorTex.sample(samp, vtf.uv2) * lighting;\n";
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); " 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); envMapUv);
} }
else if (info.m_hasColorTex) 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; break;
@ -296,7 +341,7 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid
case CFluidPlane::EFluidType::PoisonWater: case CFluidPlane::EFluidType::PoisonWater:
if (info.m_hasLightmap) 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 // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1
// ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS
// Output reg 2 // Output reg 2
@ -334,10 +379,10 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid
if (info.m_hasPatternTex2) if (info.m_hasPatternTex2)
{ {
if (info.m_hasPatternTex1) if (info.m_hasPatternTex1)
combiner += " colorOut = (patternTex1.sample(samp, vtf.uvs[0]) * lu.kColor0 + lighting) *\n" combiner += " colorOut = (patternTex1.sample(samp, vtf.uv0) * lu.kColor0 + lighting) *\n"
" patternTex2.sample(samp, vtf.uvs[1]) + vtf.color;\n"; " patternTex2.sample(samp, vtf.uv1) + vtf.color;\n";
else 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 else
{ {
@ -349,13 +394,13 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid
if (info.m_hasEnvBumpMap) if (info.m_hasEnvBumpMap)
{ {
// Make previous stage indirect, mtx0 // 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); " 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 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_hasPatternTex2)
{ {
if (info.m_hasPatternTex1) if (info.m_hasPatternTex1)
combiner += " colorOut = (patternTex1.sample(samp, vtf.uvs[0]) * lu.kColor0 + vtf.color) *\n" combiner += " colorOut = (patternTex1.sample(samp, vtf.uv0) * lu.kColor0 + vtf.color) *\n"
" patternTex2.sample(samp, vtf.uvs[1]) + vtf.color;\n"; " patternTex2.sample(samp, vtf.uv1) + vtf.color;\n";
else 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 else
{ {
@ -390,7 +435,7 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid
} }
if (info.m_hasColorTex) 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) 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" combiner += " float3 lightVec = lights[3].pos.xyz - vtf.mvPos.xyz;\n"
" float lx = dot(vtf.mvTangent.xyz, lightVec);\n" " float lx = dot(vtf.mvTangent.xyz, lightVec);\n"
" float ly = dot(vtf.mvBinorm.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" combiner += hecl::Format(" float4 emboss1 = bumpMap.sample(samp, vtf.uv%d) + float4(0.5);\n"
" float4 emboss2 = bumpMap.sample(samp, vtf.uvs[%d] + float2(lx, ly));\n", " float4 emboss2 = bumpMap.sample(samp, vtf.uv%d + float2(lx, ly));\n",
bumpMapUv, bumpMapUv); bumpMapUv, bumpMapUv);
// 5: NULL, NULL, NULL // 5: NULL, NULL, NULL
@ -437,10 +482,10 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid
if (info.m_hasPatternTex2) if (info.m_hasPatternTex2)
{ {
if (info.m_hasPatternTex1) if (info.m_hasPatternTex1)
combiner += " colorOut = (patternTex1.sample(samp, vtf.uvs[0]) * lu.kColor0 + vtf.color) *\n" combiner += " colorOut = (patternTex1.sample(samp, vtf.uv0) * lu.kColor0 + vtf.color) *\n"
" patternTex2.sample(samp, vtf.uvs[1]) + vtf.color;\n"; " patternTex2.sample(samp, vtf.uv1) + vtf.color;\n";
else 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 else
{ {
@ -448,31 +493,37 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid
} }
if (info.m_hasColorTex) 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) if (info.m_hasBumpMap)
{ {
// 3: bumpMapTCG, bumpMap, NULL // 3: bumpMapTCG, bumpMap, NULL
// ZERO, TEX, PREV, ZERO // ZERO, TEX, PREV, ZERO
// Output reg prev, scale 2 // 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"; combiner += "colorOut *= emboss1 * float4(2.0);\n";
} }
break; break;
} }
combiner += " colorOut.a = kColor0.a;\n"; combiner += " colorOut.a = lu.kColor0.a;\n";
std::string finalVS = hecl::Format(VS, additionalTCGs.c_str()); char *finalVS, *finalFS;
std::string finalFS = hecl::Format(FS, textures.c_str(), combiner.c_str()); 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, auto ret = ctx.newShaderPipeline(finalVS, finalFS, nullptr, nullptr,
s_vtxFmt, CGraphics::g_ViewportSamples, s_vtxFmt, CGraphics::g_ViewportSamples,
info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::SrcAlpha, info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::SrcAlpha,
info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::InvSrcAlpha, info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::InvSrcAlpha,
boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false, boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false,
boo::CullMode::None); boo::CullMode::None);
free(finalVS);
free(finalFS);
return ret;
} }
boo::ObjToken<boo::IShaderPipeline> boo::ObjToken<boo::IShaderPipeline>
@ -506,8 +557,8 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid
// Tex0 * kColor0 * Tex1 + Tex2 // Tex0 * kColor0 * Tex1 + Tex2
if (info.m_hasPatternTex1 && info.m_hasPatternTex2) if (info.m_hasPatternTex1 && info.m_hasPatternTex2)
{ {
combiner += " colorOut = patternTex1.sample(samp, vtf.uvs[0]) * lu.kColor0 *\n" combiner += " colorOut = patternTex1.sample(samp, vtf.uv0) * lu.kColor0 *\n"
" patternTex2.sample(samp, vtf.uvs[1]);\n"; " patternTex2.sample(samp, vtf.uv1);\n";
} }
else else
{ {
@ -516,19 +567,25 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid
if (info.m_hasColorTex) 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()); char *finalVS, *finalFS;
std::string finalFS = hecl::Format(FSDoor, textures.c_str(), combiner.c_str()); 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, auto ret = ctx.newShaderPipeline(finalVS, finalFS, nullptr, nullptr,
s_vtxFmt, CGraphics::g_ViewportSamples, s_vtxFmt, CGraphics::g_ViewportSamples,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false, boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false,
boo::CullMode::None); boo::CullMode::None);
free(finalVS);
free(finalFS);
return ret;
} }
boo::ObjToken<boo::IShaderDataBinding> CFluidPlaneShader::BuildBinding(boo::MetalDataFactory::Context& ctx, boo::ObjToken<boo::IShaderDataBinding> CFluidPlaneShader::BuildBinding(boo::MetalDataFactory::Context& ctx,

View File

@ -10,6 +10,8 @@
#include "IOStreams.hpp" #include "IOStreams.hpp"
#include "hecl/hecl.hpp" #include "hecl/hecl.hpp"
using namespace std::literals;
namespace urde namespace urde
{ {

View File

@ -27,11 +27,12 @@ public:
ArmCannon = (1 << 11), ArmCannon = (1 << 11),
BigStrike = (1 << 12), BigStrike = (1 << 12),
StaticInterference = (1 << 14), StaticInterference = (1 << 14),
KeepInCinematic = (1 << 17),
}; };
private: private:
EProjectileAttrib xe8_projectileAttribs; EProjectileAttrib xe8_projectileAttribs;
TUniqueId xec_uid; TUniqueId xec_ownerId;
EWeaponType xf0_weaponType; EWeaponType xf0_weaponType;
u32 xf4_; u32 xf4_;
CMaterialFilter xf8_; CMaterialFilter xf8_;
@ -52,8 +53,8 @@ public:
EProjectileAttrib GetAttribField() const { return xe8_projectileAttribs; } EProjectileAttrib GetAttribField() const { return xe8_projectileAttribs; }
const CMaterialFilter& GetFilter() const; const CMaterialFilter& GetFilter() const;
void SetFilter(const CMaterialFilter&); void SetFilter(const CMaterialFilter&);
TUniqueId GetOwnerId() const; TUniqueId GetOwnerId() const { return xec_ownerId; }
void SetOwnerId(TUniqueId); void SetOwnerId(TUniqueId oid) { xec_ownerId = oid; }
EWeaponType GetType() const; EWeaponType GetType() const;
const CDamageInfo& GetDamageInfo() const; const CDamageInfo& GetDamageInfo() const;
CDamageInfo& DamageInfo(); CDamageInfo& DamageInfo();

View File

@ -7,6 +7,8 @@
#include "Character/IAnimReader.hpp" #include "Character/IAnimReader.hpp"
#include "Character/CActorLights.hpp" #include "Character/CActorLights.hpp"
#include "Camera/CGameCamera.hpp" #include "Camera/CGameCamera.hpp"
#include "GameGlobalObjects.hpp"
#include "CSimplePool.hpp"
namespace urde 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})) , x70_materialFilter(CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {0ull}))
, xc6_nextDrawNode(otherUid) , xc6_nextDrawNode(otherUid)
{ {
x90_actorLights = mData.IsNull() ? std::unique_ptr<CActorLights>() : params.x0_lightParms.MakeActorLights();
if (mData.x10_animData || mData.x1c_normalModel) if (mData.x10_animData || mData.x1c_normalModel)
x64_modelData = std::make_unique<CModelData>(std::move(mData)); x64_modelData = std::make_unique<CModelData>(std::move(mData));
xd0_ = params.x64_;
xd8_nonLoopingSfxHandles.resize(2); 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) void CActor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr)
@ -499,14 +530,9 @@ bool CActor::CanDrawStatic() const
const CScannableObjectInfo* CActor::GetScannableObjectInfo() const const CScannableObjectInfo* CActor::GetScannableObjectInfo() const
{ {
if (!x98_scanObjectInfo) if (!x98_scanObjectInfo || !x98_scanObjectInfo.IsLoaded())
return nullptr; return nullptr;
return x98_scanObjectInfo.GetObj();
TToken<CScannableObjectInfo>& info = *x98_scanObjectInfo;
if (!info || !info.IsLoaded())
return nullptr;
return info.GetObj();
} }
void CActor::SetCalculateLighting(bool c) void CActor::SetCalculateLighting(bool c)

View File

@ -36,15 +36,15 @@ protected:
CSfxHandle x8c_loopingSfxHandle; CSfxHandle x8c_loopingSfxHandle;
std::unique_ptr<CActorLights> x90_actorLights; std::unique_ptr<CActorLights> x90_actorLights;
std::unique_ptr<CSimpleShadow> x94_simpleShadow; std::unique_ptr<CSimpleShadow> x94_simpleShadow;
std::unique_ptr<TToken<CScannableObjectInfo>> x98_scanObjectInfo; TLockedToken<CScannableObjectInfo> x98_scanObjectInfo;
zeus::CAABox x9c_renderBounds; zeus::CAABox x9c_renderBounds;
CModelFlags xb4_drawFlags; CModelFlags xb4_drawFlags;
float xbc_time = 0.f; float xbc_time = 0.f;
float xc0_pitchBend = 0.f; float xc0_pitchBend = 0.f;
TUniqueId xc4_fluidId = kInvalidUniqueId; TUniqueId xc4_fluidId = kInvalidUniqueId;
TUniqueId xc6_nextDrawNode = kInvalidUniqueId; TUniqueId xc6_nextDrawNode;
u32 xc8_drawnToken = -1; int xc8_drawnToken = -1;
u32 xcc_addedToken = -1; int xcc_addedToken = -1;
float xd0_; float xd0_;
float xd4_maxVol = 1.f; float xd4_maxVol = 1.f;
rstl::reserved_vector<CSfxHandle, 2> xd8_nonLoopingSfxHandles; rstl::reserved_vector<CSfxHandle, 2> xd8_nonLoopingSfxHandles;
@ -63,14 +63,17 @@ protected:
bool xe5_26_muted : 1; bool xe5_26_muted : 1;
bool xe5_27_useInSortedLists : 1; bool xe5_27_useInSortedLists : 1;
bool xe5_28_callTouch : 1; bool xe5_28_callTouch : 1;
bool xe5_29_ : 1;
bool xe5_30_ : 1;
bool xe5_31_ : 1; bool xe5_31_ : 1;
u8 xe6_24_fluidCounter : 3; 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; bool xe6_30_enablePitchBend : 1;
u8 xe6_31_targetableVisorFlags : 4; u8 xe6_31_targetableVisorFlags : 4;
bool xe7_27_ : 1; bool xe7_27_ : 1;
bool xe7_28_worldLightingDirty : 1; bool xe7_28_worldLightingDirty : 1;
bool xe7_29_ : 1; bool xe7_29_actorActive : 1;
bool xe7_30_doTargetDistanceTest : 1; bool xe7_30_doTargetDistanceTest : 1;
bool xe7_31_targetable : 1; bool xe7_31_targetable : 1;
}; };
@ -94,8 +97,8 @@ public:
Done, Done,
}; };
CActor(TUniqueId, bool, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, CActor(TUniqueId uid, bool active, std::string_view name, const CEntityInfo& info, const zeus::CTransform&,
const CMaterialList&, const CActorParameters&, TUniqueId); CModelData&& mData, const CMaterialList& list, const CActorParameters& params, TUniqueId otherUid);
virtual void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); virtual void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&);
virtual void SetActive(bool active) virtual void SetActive(bool active)
@ -103,7 +106,7 @@ public:
xe4_27_ = true; xe4_27_ = true;
xe4_28_ = true; xe4_28_ = true;
xe4_29_actorLightsDirty = true; xe4_29_actorLightsDirty = true;
xe7_29_ = true; xe7_29_actorActive = active;
CEntity::SetActive(active); CEntity::SetActive(active);
} }
virtual void PreRender(CStateManager&, const zeus::CFrustum&) {} virtual void PreRender(CStateManager&, const zeus::CFrustum&) {}
@ -177,7 +180,7 @@ public:
const CActorLights* GetActorLights() const { return x90_actorLights.get(); } const CActorLights* GetActorLights() const { return x90_actorLights.get(); }
CActorLights* ActorLights() { return x90_actorLights.get(); } CActorLights* ActorLights() { return x90_actorLights.get(); }
bool CanDrawStatic() const; 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; } void SetWorldLightingDirty(bool b) { xe7_28_worldLightingDirty = b; }
const CScannableObjectInfo* GetScannableObjectInfo() const; const CScannableObjectInfo* GetScannableObjectInfo() const;
const CHealthInfo* GetHealthInfo(const CStateManager& mgr) const const CHealthInfo* GetHealthInfo(const CStateManager& mgr) const

View File

@ -11,6 +11,7 @@ namespace urde
class CActorParameters class CActorParameters
{ {
friend class ScriptLoader; friend class ScriptLoader;
friend class CActor;
CLightParameters x0_lightParms; CLightParameters x0_lightParms;
CScannableParameters x40_scanParms; CScannableParameters x40_scanParms;
std::pair<CAssetId, CAssetId> x44_xrayAssets = {}; std::pair<CAssetId, CAssetId> x44_xrayAssets = {};
@ -23,7 +24,7 @@ class CActorParameters
bool x58_24_ : 1; bool x58_24_ : 1;
bool x58_25_thermalHeat : 1; bool x58_25_thermalHeat : 1;
bool x58_26_ : 1; bool x58_26_ : 1;
bool x58_27_ : 1; bool x58_27_noSortThermal : 1;
}; };
u32 _dummy = 0; u32 _dummy = 0;
}; };
@ -32,7 +33,7 @@ class CActorParameters
float x64_ = 0.f; float x64_ = 0.f;
public: 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, CActorParameters(const CLightParameters& lightParms, const CScannableParameters& scanParms,
const std::pair<CAssetId, CAssetId>& xrayAssets, const std::pair<CAssetId, CAssetId>& thermalAssets, const std::pair<CAssetId, CAssetId>& xrayAssets, const std::pair<CAssetId, CAssetId>& thermalAssets,
const CVisorParameters& visorParms, bool b1, bool thermalHeat, bool c, bool d) const CVisorParameters& visorParms, bool b1, bool thermalHeat, bool c, bool d)
@ -44,7 +45,7 @@ public:
, x58_24_(b1) , x58_24_(b1)
, x58_25_thermalHeat(thermalHeat) , x58_25_thermalHeat(thermalHeat)
, x58_26_(c) , x58_26_(c)
, x58_27_(d) , x58_27_noSortThermal(d)
{ {
} }
CActorParameters Scannable(const CScannableParameters& sParms) const CActorParameters Scannable(const CScannableParameters& sParms) const

View File

@ -10,6 +10,7 @@ namespace urde
class CLightParameters class CLightParameters
{ {
friend class CActor;
public: public:
enum class EShadowTesselation enum class EShadowTesselation
{ {

View File

@ -13,6 +13,7 @@ class CScannableParameters
public: public:
CScannableParameters() = default; CScannableParameters() = default;
CScannableParameters(CAssetId id) : x0_scanId(id) {} CScannableParameters(CAssetId id) : x0_scanId(id) {}
CAssetId GetScanId() const { return x0_scanId; }
}; };
} }

View File

@ -30,7 +30,7 @@ CScriptActor::CScriptActor(TUniqueId uid, std::string_view name, const CEntityIn
, x2e2_29_((x2e2_24_ && x2e2_25_dead && x2d8_ != 0)) , x2e2_29_((x2e2_24_ && x2e2_25_dead && x2d8_ != 0))
, x2e2_30_transposeRotate(b4) , x2e2_30_transposeRotate(b4)
, x2e2_31_(b5) , x2e2_31_(b5)
, x2e3_24_(false) , x2e3_24_cameraMoveIntoAlpha(false)
{ {
if (x64_modelData && (x64_modelData->HasAnimData() || x64_modelData->HasNormalModel()) && castsShadow) if (x64_modelData && (x64_modelData->HasAnimData() || x64_modelData->HasNormalModel()) && castsShadow)
CreateShadow(true); CreateShadow(true);

View File

@ -27,7 +27,7 @@ protected:
bool x2e2_29_ : 1; bool x2e2_29_ : 1;
bool x2e2_30_transposeRotate : 1; bool x2e2_30_transposeRotate : 1;
bool x2e2_31_ : 1; bool x2e2_31_ : 1;
bool x2e3_24_ : 1; bool x2e3_24_cameraMoveIntoAlpha : 1;
public: public:
CScriptActor(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, CScriptActor(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&,
@ -44,7 +44,7 @@ public:
void Touch(CActor&, CStateManager&); void Touch(CActor&, CStateManager&);
const CDamageVulnerability* GetDamageVulnerability() const { return &x268_damageVulnerability; } const CDamageVulnerability* GetDamageVulnerability() const { return &x268_damageVulnerability; }
CHealthInfo* HealthInfo(CStateManager&) { return &x260_currentHealth; } CHealthInfo* HealthInfo(CStateManager&) { return &x260_currentHealth; }
bool GetX2E3_24() const { return x2e3_24_; } bool IsCameraMoveIntoAlpha() const { return x2e3_24_cameraMoveIntoAlpha; }
}; };
}; };

View File

@ -45,9 +45,7 @@ void CScriptAiJumpPoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId oth
if (wpnt) if (wpnt)
{ {
x10c_currentWaypoint = wpnt->GetUniqueId(); x10c_currentWaypoint = wpnt->GetUniqueId();
const CScriptWaypoint* nextWpnt = wpnt->NextWaypoint(mgr); x10e_nextWaypoint = wpnt->NextWaypoint(mgr);
if (nextWpnt)
x10e_nextWaypoint = nextWpnt->GetUniqueId();
} }
} }
} }

View File

@ -7,10 +7,10 @@ namespace urde
{ {
CScriptCameraWaypoint::CScriptCameraWaypoint(TUniqueId uid, std::string_view name, const CEntityInfo& info, 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), : CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::Unknown),
CActorParameters::None(), kInvalidUniqueId) CActorParameters::None(), kInvalidUniqueId)
, xe8_(f1) , xe8_hfov(hfov)
, xec_(w1) , xec_(w1)
{ {

View File

@ -8,17 +8,18 @@ namespace urde
class CScriptCameraWaypoint : public CActor class CScriptCameraWaypoint : public CActor
{ {
float xe8_; float xe8_hfov;
u32 xec_; u32 xec_;
public: public:
CScriptCameraWaypoint(TUniqueId uid, std::string_view name, const CEntityInfo& info, 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 Accept(IVisitor& visitor);
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&);
void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const {} void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const {}
void Render(const CStateManager&) const {} void Render(const CStateManager&) const {}
TUniqueId GetRandomNextWaypointId(CStateManager& mgr) const; TUniqueId GetRandomNextWaypointId(CStateManager& mgr) const;
float GetHFov() const { return xe8_hfov; }
}; };
} }

View File

@ -38,7 +38,7 @@ void CScriptPlayerActor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid
void CScriptPlayerActor::SetActive(bool active) void CScriptPlayerActor::SetActive(bool active)
{ {
CActor::SetActive(active); CActor::SetActive(active);
xe7_29_ = true; xe7_29_actorActive = true;
} }
void CScriptPlayerActor::PreRender(CStateManager&, const zeus::CFrustum&) void CScriptPlayerActor::PreRender(CStateManager&, const zeus::CFrustum&)

View File

@ -23,6 +23,7 @@ CScriptTrigger::CScriptTrigger(TUniqueId uid, std::string_view name, const CEnti
{ {
x148_26_deactivateOnEntered = deactivateOnEntered; x148_26_deactivateOnEntered = deactivateOnEntered;
x148_27_deactivateOnExited = deactivateOnExited; x148_27_deactivateOnExited = deactivateOnExited;
SetCallTouch(false);
} }
void CScriptTrigger::Accept(IVisitor& visitor) { visitor.Visit(this); } void CScriptTrigger::Accept(IVisitor& visitor) { visitor.Visit(this); }

View File

@ -1,18 +1,20 @@
#include "CScriptWaypoint.hpp" #include "CScriptWaypoint.hpp"
#include "Character/CModelData.hpp"
#include "Collision/CMaterialList.hpp"
#include "CActorParameters.hpp" #include "CActorParameters.hpp"
#include "TCastTo.hpp" #include "TCastTo.hpp"
#include "CStateManager.hpp"
namespace urde namespace urde
{ {
CScriptWaypoint::CScriptWaypoint(TUniqueId uid, std::string_view name, const CEntityInfo& info, CScriptWaypoint::CScriptWaypoint(TUniqueId uid, std::string_view name, const CEntityInfo& info,
const zeus::CTransform& xf, bool active, float, float, const zeus::CTransform& xf, bool active, float f1, float f2,
u32, u32, u32, u32, u32, u32, u32) u32 w1, u32 w2, u32 w3, u32 w4, u32 w5, u32 w6, u32 w7)
: CActor(uid, active, name, info, xf, CModelData(), CMaterialList(), : 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) void CScriptWaypoint::Accept(IVisitor& visitor)
@ -20,4 +22,46 @@ void CScriptWaypoint::Accept(IVisitor& visitor)
visitor.Visit(this); 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<TUniqueId, 10> 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<CScriptWaypoint> 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)];
}
} }

View File

@ -8,6 +8,14 @@ namespace urde
class CScriptWaypoint : public CActor class CScriptWaypoint : public CActor
{ {
float xe8_;
u32 xec_;
float xf0_;
bool xf4_;
bool xf5_;
bool xf6_;
bool xf7_;
bool xf8_;
u16 xfa_jumpFlags; u16 xfa_jumpFlags;
public: public:
CScriptWaypoint(TUniqueId, std::string_view, const CEntityInfo&, CScriptWaypoint(TUniqueId, std::string_view, const CEntityInfo&,
@ -15,8 +23,10 @@ public:
u32, u32, u32, u32, u32, u32, u32); u32, u32, u32, u32, u32, u32, u32);
void Accept(IVisitor& visitor); void Accept(IVisitor& visitor);
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr);
const CScriptWaypoint* NextWaypoint(CStateManager&) const { return nullptr; } void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const;
TUniqueId FollowWaypoint(CStateManager& mgr) const;
TUniqueId NextWaypoint(CStateManager& mgr) const;
}; };
} }

View File

@ -9,15 +9,16 @@ namespace urde
class CVisorParameters class CVisorParameters
{ {
public: public:
u32 x0_mask : 4; u8 x0_mask : 4;
bool x0_4_b1 : 1; bool x0_4_b1 : 1;
bool x0_5_b2 : 1; bool x0_5_b2 : 1;
bool x0_28_b3 : 1; bool x0_28_b3 : 1;
bool x0_29_b4 : 1; bool x0_29_b4 : 1;
CVisorParameters() CVisorParameters()
: x0_mask(0xf), x0_4_b1(false), x0_5_b2(false) {} : 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) {} : x0_mask(mask), x0_4_b1(b1), x0_5_b2(b2) {}
u8 GetMask() const { return x0_mask; }
}; };
} }

2
hecl

@ -1 +1 @@
Subproject commit 2bfe803bf63aa17af34adac7c7b317dc8c646467 Subproject commit 2064c5ed258337bf71a2c855ab17592abf86e0d1

@ -1 +1 @@
Subproject commit 155d4553794a7428090c453c30dd15e17d0961f0 Subproject commit 726c42873311435b263e6bc41444b393f13abee2