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
{
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()
{
Reset();
@ -20,17 +27,17 @@ void CSortedListManager::AddToLinkedList(s16 nodeId, s16& headId, s16& tailId) c
{
if (headId == -1)
{
const_cast<SNode&>(x0_nodes[nodeId]).x28_next = headId;
const_cast<SNode&>(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<SNode&>(x0_nodes[nodeId]).x28_next = headId;
const_cast<SNode&>(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<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)
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)
{
for (int i=0 ; i<a ; ++i)
{
s16 id = xb000_sortedLists[int(la)].x0_ids[i];
if (x0_nodes[id].x1c_selfIdxs[lb] > 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<xb000_sortedLists[int(lb)].x800_size ; ++i)
{
s16 id = xb000_sortedLists[int(lb)].x0_ids[i];
if (x0_nodes[id].x1c_selfIdxs[la] < aabb[int(la)])
s16 id = AccessElement(xb000_sortedLists[int(lb)].x0_ids, i);
if (AccessElement(x0_nodes, id).x1c_selfIdxs[la] < aabb[int(la)])
AddToLinkedList(id, headId, tailId);
}
}
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)] ||
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<TUniqueId, 1024>& o
s16 id = const_cast<CSortedListManager&>(*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<TUniqueId, 1024>& o
s16 id = const_cast<CSortedListManager&>(*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<TUniqueId, 1024>& 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;
}

View File

@ -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<TUniqueId, 1024>&, const zeus::CVector3f&, const zeus::CVector3f&,

View File

@ -271,25 +271,25 @@ void CStateManager::UpdateThermalVisor()
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)
{
case 0:
{
CActor& actor = reinterpret_cast<CActor&>(drawable);
const CActor& actor = *reinterpret_cast<const CActor*>(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<CActor&>(actor).xc8_drawnToken = mgr.x8dc_objectDrawToken;
break;
}
case 1:
reinterpret_cast<CSimpleShadow&>(drawable).Render(mgr.x8f0_shadowTex.GetObj());
reinterpret_cast<const CSimpleShadow*>(drawable)->Render(mgr.x8f0_shadowTex.GetObj());
break;
case 2:
reinterpret_cast<CDecal&>(drawable).Render();
reinterpret_cast<const CDecal*>(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<const CActor*>(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<CActor> 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<const CActor*>(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<const CActor*>(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<const CActor*>(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<CActor> 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<zeus::CAABox> touchAABB2 = ent2->GetTouchBounds();
if (!ent2->GetActive() || touchAABB2)
if (!ent2->GetActive() || !touchAABB2)
continue;
if (visits[ent2->GetUniqueId().Value()])

View File

@ -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<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)
{

View File

@ -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);

View File

@ -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<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)
@ -58,7 +243,7 @@ void CCinematicCamera::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid,
TUniqueId id = mgr.GetIdForScript(conn.x8_objId);
if (TCastToPtr<CScriptActor> 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<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)
{
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)

View File

@ -8,35 +8,48 @@ namespace urde
class CCinematicCamera : public CGameCamera
{
std::vector<zeus::CVector3f> x188_;
std::vector<zeus::CQuaternion> x198_;
std::vector<TUniqueId> x1a8_;
std::vector<zeus::CVector3f> x1b8_;
std::vector<TUniqueId> x1c8_;
std::vector<float> x1d8_;
std::vector<zeus::CVector3f> x188_viewPoints;
std::vector<zeus::CQuaternion> x198_viewOrientations;
std::vector<TUniqueId> x1a8_viewPointArrivals;
std::vector<zeus::CVector3f> x1b8_targets;
std::vector<TUniqueId> x1c8_targetArrivals;
std::vector<float> 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<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:
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; }
};
}

View File

@ -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;
}
}

View File

@ -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();
};
}

View File

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

View File

@ -146,7 +146,7 @@ rstl::optional_object<zeus::CAABox> 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);

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:
CSimpleShadow() = default;
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)
{
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())
{

View File

@ -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<boo::IShaderPipeline>

View File

@ -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<boo::IShaderPipeline>
@ -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<boo::IShaderDataBinding>

View File

@ -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<boo::IShaderPipeline>
@ -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<boo::IShaderDataBinding> CFluidPlaneShader::BuildBinding(boo::MetalDataFactory::Context& ctx,

View File

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

View File

@ -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();

View File

@ -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<CActorLights>() : params.x0_lightParms.MakeActorLights();
if (mData.x10_animData || mData.x1c_normalModel)
x64_modelData = std::make_unique<CModelData>(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<CScannableObjectInfo>& info = *x98_scanObjectInfo;
if (!info || !info.IsLoaded())
return nullptr;
return info.GetObj();
return x98_scanObjectInfo.GetObj();
}
void CActor::SetCalculateLighting(bool c)

View File

@ -36,15 +36,15 @@ protected:
CSfxHandle x8c_loopingSfxHandle;
std::unique_ptr<CActorLights> x90_actorLights;
std::unique_ptr<CSimpleShadow> x94_simpleShadow;
std::unique_ptr<TToken<CScannableObjectInfo>> x98_scanObjectInfo;
TLockedToken<CScannableObjectInfo> 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<CSfxHandle, 2> 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

View File

@ -11,6 +11,7 @@ namespace urde
class CActorParameters
{
friend class ScriptLoader;
friend class CActor;
CLightParameters x0_lightParms;
CScannableParameters x40_scanParms;
std::pair<CAssetId, CAssetId> 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<CAssetId, CAssetId>& xrayAssets, const std::pair<CAssetId, CAssetId>& 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

View File

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

View File

@ -13,6 +13,7 @@ class CScannableParameters
public:
CScannableParameters() = default;
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_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);

View File

@ -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; }
};
};

View File

@ -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);
}
}
}

View File

@ -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)
{

View File

@ -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; }
};
}

View File

@ -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&)

View File

@ -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); }

View File

@ -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<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
{
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;
};
}

View File

@ -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; }
};
}

2
hecl

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

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