Various bug fixes

This commit is contained in:
Jack Andersen 2019-03-08 22:58:27 -10:00
parent f40bf707f6
commit 2f963b9ce3
28 changed files with 283 additions and 120 deletions

View File

@ -5,6 +5,7 @@
namespace urde {
hecl::ProjectPath CDvdFile::m_DvdRoot;
std::unordered_map<std::string, std::string> CDvdFile::m_caseInsensitiveMap;
class CFileDvdRequest : public IDvdRequest {
std::shared_ptr<athena::io::FileReader> m_reader;
@ -90,8 +91,34 @@ std::shared_ptr<IDvdRequest> CDvdFile::AsyncSeekRead(void* buf, u32 len, ESeekOr
return ret;
}
hecl::ProjectPath CDvdFile::ResolvePath(std::string_view path) {
auto start = path.begin();
while (*start == '/') ++start;
std::string lowerChStr(start, path.end());
std::transform(lowerChStr.begin(), lowerChStr.end(), lowerChStr.begin(), ::tolower);
auto search = m_caseInsensitiveMap.find(lowerChStr);
if (search == m_caseInsensitiveMap.end())
return {};
return hecl::ProjectPath(m_DvdRoot, search->second);
}
void CDvdFile::RecursiveBuildCaseInsensitiveMap(const hecl::ProjectPath& path, std::string::size_type prefixLen) {
for (const auto& p : path.enumerateDir()) {
if (p.m_isDir) {
RecursiveBuildCaseInsensitiveMap(hecl::ProjectPath(path, p.m_name), prefixLen);
} else {
hecl::ProjectPath ch(path, p.m_name);
std::string chStr(ch.getAbsolutePathUTF8().begin() + prefixLen, ch.getAbsolutePathUTF8().end());
std::string lowerChStr(chStr);
std::transform(lowerChStr.begin(), lowerChStr.end(), lowerChStr.begin(), ::tolower);
m_caseInsensitiveMap[lowerChStr] = chStr;
}
}
}
void CDvdFile::Initialize(const hecl::ProjectPath& path) {
m_DvdRoot = path;
RecursiveBuildCaseInsensitiveMap(path, path.getAbsolutePathUTF8().length() + 1);
if (m_WorkerRun.load())
return;
m_WorkerRun.store(true);

View File

@ -18,6 +18,7 @@ class CDvdFile {
friend class CResLoader;
friend class CFileDvdRequest;
static hecl::ProjectPath m_DvdRoot;
static std::unordered_map<std::string, std::string> m_caseInsensitiveMap;
static std::thread m_WorkerThread;
static std::mutex m_WorkerMutex;
static std::condition_variable m_WorkerCV;
@ -29,16 +30,19 @@ class CDvdFile {
std::string x18_path;
std::shared_ptr<athena::io::FileReader> m_reader;
static hecl::ProjectPath ResolvePath(std::string_view path);
static void RecursiveBuildCaseInsensitiveMap(const hecl::ProjectPath& path, std::string::size_type prefixLen);
public:
static void Initialize(const hecl::ProjectPath& path);
static void Shutdown();
CDvdFile(std::string_view path)
: x18_path(path)
, m_reader(std::make_shared<athena::io::FileReader>(hecl::ProjectPath(m_DvdRoot, path).getAbsolutePath())) {}
, m_reader(std::make_shared<athena::io::FileReader>(ResolvePath(path).getAbsolutePath())) {}
operator bool() const { return m_reader->isOpen(); }
void UpdateFilePos(int pos) { m_reader->seek(pos, athena::SeekOrigin::Begin); }
static bool FileExists(std::string_view path) { return hecl::ProjectPath(m_DvdRoot, path).isFile(); }
static bool FileExists(std::string_view path) { return ResolvePath(path).isFile(); }
void CloseFile() { m_reader->close(); }
std::shared_ptr<IDvdRequest> AsyncSeekRead(void* buf, u32 len, ESeekOrigin whence, int off,
std::function<void(u32)>&& cb = {});

View File

@ -97,6 +97,19 @@ void CResFactory::CancelBuild(const SObjectTag& tag) {
}
}
void CResFactory::LoadPersistentResources(CSimplePool& sp) {
const auto& paks = x4_loader.GetPaks();
for (auto it = paks.begin(); it != paks.end(); ++it) {
if (!(*it)->IsWorldPak()) {
for (const CAssetId& id : (*it)->GetDepList()) {
SObjectTag tag(GetResourceTypeById(id), id);
m_nonWorldTokens.push_back(sp.GetObj(tag));
m_nonWorldTokens.back().Lock();
}
}
}
}
void CResFactory::LoadOriginalIDs(CSimplePool& sp) {
#if RUNTIME_ORIGINAL_IDS
m_origIds = sp.GetObj("MP1OriginalIDs");

View File

@ -38,6 +38,7 @@ public:
private:
std::list<SLoadingData> m_loadList;
std::unordered_map<SObjectTag, std::list<SLoadingData>::iterator> m_loadMap;
std::vector<CToken> m_nonWorldTokens; /* URDE: always keep non-world resources resident */
void AddToLoadList(SLoadingData&& data);
CFactoryFnReturn BuildSync(const SObjectTag&, const CVParamTransfer&, CObjectReference* selfRef);
bool PumpResource(SLoadingData& data);
@ -87,6 +88,9 @@ public:
return x4_loader.EnumerateNamedResources(lambda);
}
void LoadPersistentResources(CSimplePool& sp);
void UnloadPersistentResources() { m_nonWorldTokens.clear(); }
void LoadOriginalIDs(CSimplePool& sp);
CAssetId TranslateOriginalToNew(CAssetId id) const;
CAssetId TranslateNewToOriginal(CAssetId id) const;

View File

@ -1,5 +1,6 @@
#include "CMetaAnimBlend.hpp"
#include "CMetaAnimFactory.hpp"
#include "CAnimTreeBlend.hpp"
namespace urde {
@ -17,8 +18,14 @@ void CMetaAnimBlend::GetUniquePrimitives(std::set<CPrimitive>& primsOut) const {
std::shared_ptr<CAnimTreeNode> CMetaAnimBlend::VGetAnimationTree(const CAnimSysContext& animSys,
const CMetaAnimTreeBuildOrders& orders) const {
// CMetaAnimTreeBuildOrders buildOrders = CMetaAnimTreeBuildOrders::NoSpecialOrders();
return {};
CMetaAnimTreeBuildOrders oa = CMetaAnimTreeBuildOrders::NoSpecialOrders();
CMetaAnimTreeBuildOrders ob = orders.x0_recursiveAdvance ?
CMetaAnimTreeBuildOrders::PreAdvanceForAll(*orders.x0_recursiveAdvance) :
CMetaAnimTreeBuildOrders::NoSpecialOrders();
auto a = x4_animA->GetAnimationTree(animSys, oa);
auto b = x8_animB->GetAnimationTree(animSys, ob);
return std::make_shared<CAnimTreeBlend>(x10_, a, b, xc_blend,
CAnimTreeBlend::CreatePrimitiveName(a, b, xc_blend));
}
} // namespace urde

View File

@ -1,5 +1,7 @@
#include "CMetaAnimPhaseBlend.hpp"
#include "CMetaAnimFactory.hpp"
#include "CAnimTreeTimeScale.hpp"
#include "CAnimTreeBlend.hpp"
namespace urde {
@ -17,7 +19,24 @@ void CMetaAnimPhaseBlend::GetUniquePrimitives(std::set<CPrimitive>& primsOut) co
std::shared_ptr<CAnimTreeNode> CMetaAnimPhaseBlend::VGetAnimationTree(const CAnimSysContext& animSys,
const CMetaAnimTreeBuildOrders& orders) const {
return {};
if (orders.x0_recursiveAdvance)
return GetAnimationTree(animSys, CMetaAnimTreeBuildOrders::PreAdvanceForAll(*orders.x0_recursiveAdvance));
auto a = x4_animA->GetAnimationTree(animSys, CMetaAnimTreeBuildOrders::NoSpecialOrders());
auto b = x8_animB->GetAnimationTree(animSys, CMetaAnimTreeBuildOrders::NoSpecialOrders());
auto da = a->GetContributionOfHighestInfluence().GetSteadyStateAnimInfo().GetDuration();
auto db = b->GetContributionOfHighestInfluence().GetSteadyStateAnimInfo().GetDuration();
auto dblend = da + (db - da) * xc_blend;
float fa = da / dblend;
float fb = db / dblend;
auto tsa = std::make_shared<CAnimTreeTimeScale>(a, fa,
CAnimTreeTimeScale::CreatePrimitiveName(a, fa, CCharAnimTime::Infinity(), -1.f));
auto tsb = std::make_shared<CAnimTreeTimeScale>(b, fb,
CAnimTreeTimeScale::CreatePrimitiveName(b, fb, CCharAnimTime::Infinity(), -1.f));
return std::make_shared<CAnimTreeBlend>(x10_, tsa, tsb, xc_blend,
CAnimTreeBlend::CreatePrimitiveName(tsa, tsb, xc_blend));
}
} // namespace urde

View File

@ -12,17 +12,13 @@ void CMetaAnimPlay::GetUniquePrimitives(std::set<CPrimitive>& primsOut) const {
std::shared_ptr<CAnimTreeNode> CMetaAnimPlay::VGetAnimationTree(const CAnimSysContext& animSys,
const CMetaAnimTreeBuildOrders& orders) const {
if (orders.x0_recursiveAdvance) {
CMetaAnimTreeBuildOrders modOrders;
modOrders.PreAdvanceForAll(*orders.x0_recursiveAdvance);
return GetAnimationTree(animSys, modOrders);
}
if (orders.x0_recursiveAdvance)
return GetAnimationTree(animSys, CMetaAnimTreeBuildOrders::PreAdvanceForAll(*orders.x0_recursiveAdvance));
TLockedToken<CAllFormatsAnimSource> prim =
animSys.xc_store.GetObj(SObjectTag{FOURCC('ANIM'), x4_primitive.GetAnimResId()});
std::shared_ptr<CAnimTreeNode> ret = std::make_shared<CAnimTreeAnimReaderContainer>(
return std::make_shared<CAnimTreeAnimReaderContainer>(
x4_primitive.GetName(), CAllFormatsAnimSource::GetNewReader(prim, x1c_startTime), x4_primitive.GetAnimDbIdx());
return ret;
}
} // namespace urde

View File

@ -24,25 +24,20 @@ void CMetaAnimSequence::GetUniquePrimitives(std::set<CPrimitive>& primsOut) cons
std::shared_ptr<CAnimTreeNode> CMetaAnimSequence::VGetAnimationTree(const CAnimSysContext& animSys,
const CMetaAnimTreeBuildOrders& orders) const {
if (orders.x0_recursiveAdvance) {
CMetaAnimTreeBuildOrders modOrders;
modOrders.PreAdvanceForAll(*orders.x0_recursiveAdvance);
return GetAnimationTree(animSys, modOrders);
}
if (orders.x0_recursiveAdvance)
return GetAnimationTree(animSys, CMetaAnimTreeBuildOrders::PreAdvanceForAll(*orders.x0_recursiveAdvance));
#if 0
std::vector<std::string> anims;
anims.reserve(anims.size());
for (const std::shared_ptr<IMetaAnim>& anim : x4_sequence)
{
std::shared_ptr<CAnimTreeNode> chNode = anim->GetAnimationTree(animSys, orders);
anims.emplace_back(chNode->GetName());
}
/* Originally used to generate name string */
std::vector<std::string> anims;
anims.reserve(anims.size());
for (const std::shared_ptr<IMetaAnim>& anim : x4_sequence) {
std::shared_ptr<CAnimTreeNode> chNode = anim->GetAnimationTree(animSys, orders);
anims.emplace_back(chNode->GetName());
}
#endif
std::shared_ptr<CAnimTreeNode> ret = std::make_shared<CAnimTreeSequence>(x4_sequence, animSys, "");
return ret;
return std::make_shared<CAnimTreeSequence>(x4_sequence, animSys, "");
}
} // namespace urde

View File

@ -11,10 +11,14 @@ CTransitionDatabaseGame::CTransitionDatabaseGame(const std::vector<CTransition>&
x14_transitions.reserve(transitions.size());
for (const CTransition& trans : transitions)
x14_transitions.emplace_back(trans.GetAnimPair(), trans.GetMetaTrans());
std::sort(x14_transitions.begin(), x14_transitions.end(),
[](const auto& a, const auto& b) { return a.first < b.first; });
x24_halfTransitions.reserve(halfTransitions.size());
for (const CHalfTransition& trans : halfTransitions)
x24_halfTransitions.emplace_back(trans.GetId(), trans.GetMetaTrans());
std::sort(x24_halfTransitions.begin(), x24_halfTransitions.end(),
[](const auto& a, const auto& b) { return a.first < b.first; });
}
const std::shared_ptr<IMetaTrans>& CTransitionDatabaseGame::GetMetaTrans(u32 a, u32 b) const {

View File

@ -46,7 +46,6 @@ struct CMetaAnimTreeBuildOrders {
static CMetaAnimTreeBuildOrders NoSpecialOrders() { return {}; }
static CMetaAnimTreeBuildOrders PreAdvanceForAll(const CPreAdvanceIndicator& ind) {
CMetaAnimTreeBuildOrders ret;
ret.x0_recursiveAdvance.emplace(ind);
ret.x44_singleAdvance.emplace(ind);
return ret;
}

View File

@ -117,7 +117,7 @@ zeus::CVector3f CCollisionActor::GetScanObjectIndicatorPosition(const CStateMana
}
scanScale *= 3.0f;
zeus::CVector3f orbitPos = GetOrbitPosition(mgr);
return (scanScale * (orbitPos - gameCamera->GetTransform().origin).normalized()) - orbitPos;
return orbitPos - scanScale * (orbitPos - gameCamera->GetTranslation()).normalized();
}
const CCollisionPrimitive* CCollisionActor::GetCollisionPrimitive() const {

View File

@ -18,11 +18,10 @@ CGuiModel::CGuiModel(const CGuiWidgetParms& parms, CSimplePool* sp, CAssetId mod
bool CGuiModel::GetIsFinishedLoadingWidgetSpecific() const {
if (!xb8_model)
return true;
const CModel* model = xb8_model.GetObj();
if (!model)
if (!xb8_model.IsLoaded())
return false;
model->GetInstance().Touch(0);
return model->IsLoaded(0);
xb8_model->GetInstance().Touch(0);
return xb8_model->IsLoaded(0);
}
void CGuiModel::Touch() const {

View File

@ -358,7 +358,8 @@ void CSamusHud::UpdateEnergy(float dt, const CStateManager& mgr, bool init) {
float curLastTankEnergy = x2d0_playerHealth;
while (curLastTankEnergy > CPlayerState::GetBaseHealthCapacity())
curLastTankEnergy -= CPlayerState::GetEnergyTankCapacity();
x28c_energyIntf->SetCurrEnergy(lastTankEnergy, curLastTankEnergy < lastTankEnergy);
x28c_energyIntf->SetCurrEnergy(lastTankEnergy,
curLastTankEnergy > lastTankEnergy != x2d0_playerHealth > energy);
}
x2d0_playerHealth = energy;
if (x28c_energyIntf) {

View File

@ -759,6 +759,10 @@ bool CMain::Proc() {
// Warmup cycle overrides update
if (m_warmupTags.size())
return false;
if (!m_loadedPersistentResources) {
x128_globalObjects.m_gameResFactory->LoadPersistentResources(*g_SimplePool);
m_loadedPersistentResources = true;
}
m_console->proc();
if (!m_console->isOpen()) {
@ -832,6 +836,7 @@ void CMain::ShutdownSubsystems() {
void CMain::Shutdown() {
m_console->unregisterCommand("Give");
x128_globalObjects.m_gameResFactory->UnloadPersistentResources();
x164_archSupport.reset();
ShutdownSubsystems();
CParticleSwooshShaders::Shutdown();

View File

@ -242,6 +242,7 @@ private:
std::vector<SObjectTag> m_warmupTags;
std::vector<SObjectTag>::iterator m_warmupIt;
bool m_needsWarmupClear = false;
bool m_loadedPersistentResources = false;
bool m_doQuit = false;
void InitializeSubsystems();

View File

@ -25,7 +25,7 @@ CAtomicAlpha::CAtomicAlpha(TUniqueId uid, std::string_view name, const CEntityIn
, x580_pathFind(nullptr, 3, pInfo.GetPathfindingIndex(), 1.f, 1.f)
, x668_bombProjectile(bombWeapon, bombDamage)
, x690_bombModel(CStaticRes(cmdl, GetModelData()->GetScale())) {
const_cast<TToken<CWeaponDescription>*>(&x668_bombProjectile.Token())->Lock();
x668_bombProjectile.Token().Lock();
for (u32 i = 0; i < skBombCount; ++i) {
x6dc_bombLocators.push_back(
SBomb(skBombLocators[i], pas::ELocomotionType(u32(pas::ELocomotionType::Internal10) + i)));

View File

@ -76,7 +76,7 @@ CBabygoth::CBabygoth(TUniqueId uid, std::string_view name, const CEntityInfo& in
if (x570_babyData.x148_.IsValid())
xa38_ = g_SimplePool->GetObj({SBIG('PART'), babyData.x148_});
xa48_31_ = true;
const_cast<TToken<CWeaponDescription>*>(&x958_.Token())->Lock();
x958_.Token().Lock();
UpdateTouchBounds();
x460_knockBackController.SetEnableFreeze(false);
x460_knockBackController.SetAutoResetImpulse(true);

View File

@ -25,8 +25,9 @@ CNewIntroBoss::CNewIntroBoss(TUniqueId uid, std::string_view name, const CEntity
, x5f0_beamContactFxId(beamContactFxId)
, x5f4_beamPulseFxId(beamPulseFxId)
, x5f8_beamTextureId(beamTextureId)
, x5fc_beamGlowTextureId(beamGlowTextureId) {
const_cast<TToken<CWeaponDescription>*>(&x5ac_projectileInfo.Token())->Lock();
, x5fc_beamGlowTextureId(beamGlowTextureId)
, x644_initialXf(xf) {
x5ac_projectileInfo.Token().Lock();
x574_boneTracking.SetActive(true);
}
@ -257,7 +258,7 @@ void CNewIntroBoss::Think(float dt, CStateManager& mgr) {
curProjectile->ResetBeam(mgr, true);
x450_bodyController->SetPlaybackRate(1.f);
SetTransform(x644_);
SetTransform(x644_initialXf);
StopRumble(mgr);
Death(mgr, GetTransform().frontVector(), EScriptObjectState::DeathRattle);
}

View File

@ -34,7 +34,7 @@ class CNewIntroBoss : public CPatterned {
float x638_ = 0.2f;
float x63c_attackTime = 8.f;
float x640_initialHp = 0.f;
zeus::CTransform x644_;
zeus::CTransform x644_initialXf;
s16 x674_rumbleVoice = -1;
TUniqueId x676_curProjectile = kInvalidUniqueId;
bool x678_ = false;

View File

@ -38,7 +38,7 @@ CPuddleSpore::CPuddleSpore(TUniqueId uid, std::string_view name, EFlavorType fla
x5dc_elemGens.reserve(kEyeCount);
for (u32 i = 0; i < kEyeCount; ++i)
x5dc_elemGens.emplace_back(new CElementGen(x5d0_));
const_cast<TToken<CWeaponDescription>*>(&x5ec_projectileInfo.Token())->Lock();
x5ec_projectileInfo.Token().Lock();
x460_knockBackController.SetAutoResetImpulse(false);
}

View File

@ -22,7 +22,7 @@ CSeedling::CSeedling(TUniqueId uid, std::string_view name, const CEntityInfo& in
, x6e8_deathDamage(dInfo2)
, x722_24_renderOnlyClusterA(true)
, x722_25_curNeedleCluster(false) {
const_cast<TToken<CWeaponDescription>*>(&x6c0_projectileInfo.Token())->Lock();
x6c0_projectileInfo.Token().Lock();
CreateShadow(false);
MakeThermalColdAndHot();
}

View File

@ -237,7 +237,7 @@ bool CElementGen::Update(double t) {
if (pswtElem && !x26d_25_warmedUp) {
int pswt = 0;
pswtElem->GetValue(x74_curFrame, pswt);
Log.report(logvisor::Info, "Running warmup on particle system 0x%08x for %d ticks.", desc, pswt);
//Log.report(logvisor::Info, "Running warmup on particle system 0x%08x for %d ticks.", desc, pswt);
InternalUpdate((1.f / 60.f) * pswt);
x26d_25_warmedUp = true;
}

View File

@ -27,16 +27,16 @@ CScriptSpecialFunction::CScriptSpecialFunction(TUniqueId uid, std::string_view n
kInvalidUniqueId)
, xe8_function(func)
, xec_locatorName(lcName)
, xfc_(f1)
, x100_(f2)
, x104_(f3)
, x108_(f4)
, x10c_(vec)
, x118_(col)
, xfc_float1(f1)
, x100_float2(f2)
, x104_float3(f3)
, x108_float4(f4)
, x10c_vector3f(vec)
, x118_color(col)
, x11c_damageInfo(dInfo)
, x170_(CSfxManager::TranslateSFXID(sId1))
, x172_(CSfxManager::TranslateSFXID(sId2))
, x174_(CSfxManager::TranslateSFXID(sId3))
, x170_sfx1(CSfxManager::TranslateSFXID(sId1))
, x172_sfx2(CSfxManager::TranslateSFXID(sId2))
, x174_sfx3(CSfxManager::TranslateSFXID(sId3))
, x1bc_areaSaveId(aId1)
, x1c0_layerIdx(aId2)
, x1c4_item(itemType) {
@ -126,12 +126,12 @@ void CScriptSpecialFunction::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId
switch (xe8_function) {
case ESpecialFunction::HUDFadeIn: {
if (msg == EScriptObjectMessage::Action)
mgr.Player()->SetHudDisable(xfc_, 0.f, 0.5f);
mgr.Player()->SetHudDisable(xfc_float1, 0.f, 0.5f);
break;
}
case ESpecialFunction::EscapeSequence: {
if (msg == EScriptObjectMessage::Action && xfc_ >= 0.f)
mgr.ResetEscapeSequenceTimer(xfc_);
if (msg == EScriptObjectMessage::Action && xfc_float1 >= 0.f)
mgr.ResetEscapeSequenceTimer(xfc_float1);
break;
}
case ESpecialFunction::SpinnerController: {
@ -165,7 +165,7 @@ void CScriptSpecialFunction::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId
break;
}
case EScriptObjectMessage::SetToZero: {
x16c_ = -0.5f * x104_;
x16c_ = -0.5f * x104_float3;
break;
}
default:
@ -210,10 +210,10 @@ void CScriptSpecialFunction::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId
break;
}
case ESpecialFunction::IntroBossRingController: {
if (x1a8_ != 3) {
if (x1a8_ringState != ERingState::Breakup) {
switch (msg) {
case EScriptObjectMessage::Play: {
if (x1a8_ != 0)
if (x1a8_ringState != ERingState::Scramble)
RingScramble(mgr);
for (SRingController& cont : x198_ringControllers) {
@ -223,14 +223,14 @@ void CScriptSpecialFunction::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId
cont.xc_ = zeus::skForward;
}
x1a8_ = 3;
x1a8_ringState = ERingState::Breakup;
break;
}
case EScriptObjectMessage::SetToZero: {
x1a8_ = 1;
x1ac_ = GetTranslation() - mgr.GetPlayer().GetTranslation();
x1ac_.z() = 0.f;
x1ac_.normalize();
x1a8_ringState = ERingState::Rotate;
x1ac_ringRotateTarget = GetTranslation() - mgr.GetPlayer().GetTranslation();
x1ac_ringRotateTarget.z() = 0.f;
x1ac_ringRotateTarget.normalize();
break;
}
case EScriptObjectMessage::Action: {
@ -250,8 +250,20 @@ void CScriptSpecialFunction::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId
act->RemoveMaterial(EMaterialTypes::Occluder, mgr);
}
}
}
// std::sort(x198_ringControllers.begin(), x198_ringControllers.end());
std::sort(x198_ringControllers.begin(), x198_ringControllers.end(),
[&mgr](const SRingController& a, const SRingController& b) {
TCastToConstPtr<CActor> actA(mgr.GetObjectById(a.x0_id));
TCastToConstPtr<CActor> actB(mgr.GetObjectById(b.x0_id));
if (actA && actB)
return actA->GetTranslation().z() < actB->GetTranslation().z();
return false;
});
for (auto& rc : x198_ringControllers) {
rc.x4_rotateSpeed = (x1b8_ringReverse ? 1.f : -1.f) * xfc_float1;
rc.x8_reachedTarget = false;
}
break;
}
@ -264,7 +276,7 @@ void CScriptSpecialFunction::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId
case ESpecialFunction::RadialDamage: {
if (msg == EScriptObjectMessage::Action) {
CDamageInfo dInfo = x11c_damageInfo;
dInfo.SetRadius(xfc_);
dInfo.SetRadius(xfc_float1);
mgr.ApplyDamageToWorld(GetUniqueId(), *this, GetTranslation(), dInfo,
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {0ull}));
}
@ -272,7 +284,7 @@ void CScriptSpecialFunction::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId
}
case ESpecialFunction::BossEnergyBar: {
if (msg == EScriptObjectMessage::Increment)
mgr.SetBossParams(uid, xfc_, u32(x100_) + 86);
mgr.SetBossParams(uid, xfc_float1, u32(x100_float2) + 86);
else if (msg == EScriptObjectMessage::Decrement)
mgr.SetBossParams(kInvalidUniqueId, 0.f, 0);
break;
@ -332,12 +344,12 @@ void CScriptSpecialFunction::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId
*/
case ESpecialFunction::EnvFxDensityController: {
if (msg == EScriptObjectMessage::Action)
mgr.GetEnvFxManager()->SetFxDensity(s32(x100_), xfc_);
mgr.GetEnvFxManager()->SetFxDensity(s32(x100_float2), xfc_float1);
break;
}
case ESpecialFunction::RumbleEffect:
if (msg == EScriptObjectMessage::Action) {
s32 rumbFx = s32(x100_);
s32 rumbFx = s32(x100_float2);
/* Retro originally did not check the upper bounds, this could potentially cause a crash
* with some runtimes, so let's make sure we're not out of bounds in either direction
*/
@ -367,7 +379,7 @@ void CScriptSpecialFunction::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId
}
case ESpecialFunction::DropBomb: {
if (msg == EScriptObjectMessage::Action) {
if (xfc_ >= 1.f)
if (xfc_float1 >= 1.f)
mgr.GetPlayer().GetPlayerGun()->DropBomb(CPlayerGun::EBWeapon::PowerBomb, mgr);
else
mgr.GetPlayer().GetPlayerGun()->DropBomb(CPlayerGun::EBWeapon::Bomb, mgr);
@ -389,13 +401,13 @@ void CScriptSpecialFunction::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId
const SObjectTag* objectTag = g_ResFactory->GetResourceIdByName(xec_locatorName);
CAssetId assetId = objectTag ? objectTag->id : CAssetId();
mgr.SetPendingOnScreenTex(assetId, {int(x104_), int(x108_)}, {int(xfc_), int(x100_)});
mgr.SetPendingOnScreenTex(assetId, {int(x104_float3), int(x108_float4)}, {int(xfc_float1), int(x100_float2)});
if (objectTag) {
x1e8_ = g_SimplePool->GetObj(*objectTag);
x1e5_26_displayBillboard = true;
}
} else if (msg == EScriptObjectMessage::Decrement) {
mgr.SetPendingOnScreenTex({}, {int(x104_), int(x108_)}, {int(xfc_), int(x100_)});
mgr.SetPendingOnScreenTex({}, {int(x104_float3), int(x108_float4)}, {int(xfc_float1), int(x100_float2)});
if (x1e8_)
x1e8_ = TLockedToken<CTexture>();
x1e5_26_displayBillboard = false;
@ -418,9 +430,9 @@ void CScriptSpecialFunction::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId
}
case ESpecialFunction::FogFader: {
if (msg == EScriptObjectMessage::Increment)
mgr.GetCameraManager()->SetFogDensity(x100_, xfc_);
mgr.GetCameraManager()->SetFogDensity(x100_float2, xfc_float1);
else if (msg == EScriptObjectMessage::Decrement)
mgr.GetCameraManager()->SetFogDensity(x100_, 1.f);
mgr.GetCameraManager()->SetFogDensity(x100_float2, 1.f);
break;
}
case ESpecialFunction::EnterLogbook: {
@ -429,7 +441,7 @@ void CScriptSpecialFunction::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId
break;
}
case ESpecialFunction::Ending: {
if (msg == EScriptObjectMessage::Action && GetSpecialEnding(mgr) == u32(xfc_))
if (msg == EScriptObjectMessage::Action && GetSpecialEnding(mgr) == u32(xfc_float1))
SendScriptMsgs(EScriptObjectState::Zero, mgr, EScriptObjectMessage::None);
break;
}
@ -450,15 +462,83 @@ void CScriptSpecialFunction::SkipCinematic(CStateManager& stateMgr) {
stateMgr.SetSkipCinematicSpecialFunction(kInvalidUniqueId);
}
void CScriptSpecialFunction::RingMoveCloser(CStateManager&, float) {}
void CScriptSpecialFunction::RingScramble(CStateManager& mgr) {
SendScriptMsgs(EScriptObjectState::Zero, mgr, EScriptObjectMessage::None);
x1a8_ringState = ERingState::Scramble;
x1b8_ringReverse = !x1b8_ringReverse;
float dir = (x1b8_ringReverse ? 1.f : -1.f);
for (auto& rc : x198_ringControllers) {
rc.x4_rotateSpeed = dir * mgr.GetActiveRandom()->Range(x100_float2, x104_float3);
dir = -dir;
rc.x8_reachedTarget = false;
}
}
void CScriptSpecialFunction::RingMoveAway(CStateManager&, float) {}
void CScriptSpecialFunction::ThinkRingPuller(float, CStateManager&) {}
void CScriptSpecialFunction::RingScramble(CStateManager&) {}
void CScriptSpecialFunction::ThinkIntroBossRingController(float, CStateManager&) {}
void CScriptSpecialFunction::ThinkIntroBossRingController(float dt, CStateManager& mgr) {
if (x1a8_ringState != ERingState::Breakup) {
for (const auto& rc : x198_ringControllers) {
if (TCastToPtr<CActor> act = mgr.ObjectById(rc.x0_id)) {
zeus::CTransform newXf = act->GetTransform();
newXf.rotateLocalZ(zeus::degToRad(rc.x4_rotateSpeed * dt));
act->SetTransform(newXf);
}
}
}
switch (x1a8_ringState) {
case ERingState::Breakup: {
float minMag = 0.f;
for (const auto& rc : x198_ringControllers) {
if (TCastToPtr<CActor> act = mgr.ObjectById(rc.x0_id)) {
act->SetTranslation(act->GetTransform().basis[1] * 50.f * dt + act->GetTranslation());
minMag = std::min(act->GetTranslation().magnitude(), minMag);
}
}
CalculateRenderBounds();
if (minMag != 0.f) {
/* Never actually happens */
for (const auto& rc : x198_ringControllers) {
if (CEntity* ent = mgr.ObjectById(rc.x0_id))
ent->SetActive(false);
}
SetActive(false);
}
break;
}
case ERingState::Rotate: {
x1ac_ringRotateTarget =
zeus::CQuaternion::fromAxisAngle(zeus::skUp,
zeus::degToRad(xfc_float1 * (x1b8_ringReverse ? 1.f : -1.f) * dt)).transform(x1ac_ringRotateTarget);
bool allReachedTarget = true;
for (auto& rc : x198_ringControllers) {
if (TCastToPtr<CActor> act = mgr.ObjectById(rc.x0_id)) {
zeus::CVector3f lookDirFlat = act->GetTransform().basis[1];
lookDirFlat.z() = 0.f;
lookDirFlat.normalize();
if (std::acos(zeus::clamp(-1.f, lookDirFlat.dot(x1ac_ringRotateTarget), 1.f)) <=
zeus::degToRad((xfc_float1 + std::fabs(rc.x4_rotateSpeed)) / 30.f)) {
zeus::CTransform newXf = zeus::lookAt(zeus::skZero3f, x1ac_ringRotateTarget);
newXf.origin = act->GetTranslation();
act->SetTransform(newXf);
rc.x4_rotateSpeed = (x1b8_ringReverse ? 1.f : -1.f) * xfc_float1;
rc.x8_reachedTarget = true;
} else {
allReachedTarget = false;
break;
}
}
}
if (allReachedTarget) {
SendScriptMsgs(EScriptObjectState::MaxReached, mgr, EScriptObjectMessage::None);
x1a8_ringState = ERingState::Stopped;
for (auto& rc : x198_ringControllers)
rc.x8_reachedTarget = false;
}
break;
}
default:
break;
}
}
void CScriptSpecialFunction::ThinkPlayerFollowLocator(float, CStateManager&) {}
@ -498,7 +578,7 @@ void CScriptSpecialFunction::ThinkObjectFollowObject(float, CStateManager&) {}
void CScriptSpecialFunction::ThinkChaffTarget(float, CStateManager&) {}
void CScriptSpecialFunction::ThinkActorScale(float dt, CStateManager& mgr) {
float deltaScale = dt * xfc_;
float deltaScale = dt * xfc_float1;
for (const SConnection& conn : x20_conns) {
if (conn.x0_state != EScriptObjectState::Play || conn.x4_msg != EScriptObjectMessage::Activate)
@ -509,9 +589,9 @@ void CScriptSpecialFunction::ThinkActorScale(float dt, CStateManager& mgr) {
zeus::CVector3f scale = mData->GetScale();
if (deltaScale > 0.f)
scale = zeus::min(zeus::CVector3f(deltaScale) + scale, zeus::CVector3f(x100_));
scale = zeus::min(zeus::CVector3f(deltaScale) + scale, zeus::CVector3f(x100_float2));
else
scale = zeus::max(zeus::CVector3f(deltaScale) + scale, zeus::CVector3f(x100_));
scale = zeus::max(zeus::CVector3f(deltaScale) + scale, zeus::CVector3f(x100_float2));
mData->SetScale(scale);
}
@ -575,6 +655,6 @@ u32 CScriptSpecialFunction::GetSpecialEnding(const CStateManager& mgr) const {
return 2;
}
CScriptSpecialFunction::SRingController::SRingController(TUniqueId uid, float f, bool b) : x0_id(uid), x4_(f), x8_(b) {}
CScriptSpecialFunction::SRingController::SRingController(TUniqueId uid, float f, bool b) : x0_id(uid), x4_rotateSpeed(f), x8_reachedTarget(b) {}
} // namespace urde

View File

@ -53,10 +53,17 @@ public:
One,
};
enum class ERingState {
Scramble,
Rotate,
Stopped,
Breakup
};
struct SRingController {
TUniqueId x0_id;
float x4_;
bool x8_;
float x4_rotateSpeed;
bool x8_reachedTarget;
zeus::CVector3f xc_;
SRingController(TUniqueId uid, float f, bool b);
};
@ -64,28 +71,28 @@ public:
private:
ESpecialFunction xe8_function;
std::string xec_locatorName;
float xfc_;
float x100_;
float x104_;
float x108_;
zeus::CVector3f x10c_;
zeus::CColor x118_;
float xfc_float1;
float x100_float2;
float x104_float3;
float x108_float4;
zeus::CVector3f x10c_vector3f;
zeus::CColor x118_color;
CDamageInfo x11c_damageInfo;
float x138_ = 0.f;
zeus::CTransform x13c_ = zeus::CTransform();
float x16c_ = 0.f;
s16 x170_;
s16 x172_;
s16 x174_;
s16 x170_sfx1;
s16 x172_sfx2;
s16 x174_sfx3;
CSfxHandle x178_sfxHandle;
u32 x17c_;
float x180_ = 0.f;
std::vector<float> x184_;
float x194_ = 0.f;
std::vector<SRingController> x198_ringControllers;
u32 x1a8_ = 2;
zeus::CVector3f x1ac_ = zeus::skZero3f;
bool x1b8_ = true;
ERingState x1a8_ringState = ERingState::Stopped;
zeus::CVector3f x1ac_ringRotateTarget = zeus::skZero3f;
bool x1b8_ringReverse = true;
s32 x1bc_areaSaveId;
s32 x1c0_layerIdx;
CPlayerState::EItemType x1c4_item;
@ -120,9 +127,6 @@ public:
void Render(const CStateManager&) const;
void SkipCinematic(CStateManager&);
void RingMoveCloser(CStateManager&, float);
void RingMoveAway(CStateManager&, float);
void ThinkRingPuller(float, CStateManager&);
void RingScramble(CStateManager&);
void ThinkIntroBossRingController(float, CStateManager&);
void ThinkPlayerFollowLocator(float, CStateManager&);

View File

@ -47,11 +47,7 @@ CScriptStreamedMusic::CScriptStreamedMusic(TUniqueId id, const CEntityInfo& info
, x47_music(music)
, x48_fadeIn(fadeIn)
, x4c_fadeOut(fadeOut)
, x50_volume(volume) {
size_t pos;
while ((pos = x34_fileName.find("audio/")) != std::string::npos)
x34_fileName.replace(pos, 6, "Audio/");
}
, x50_volume(volume) {}
void CScriptStreamedMusic::Stop(CStateManager& mgr) {
if (x45_fileIsDsp)

View File

@ -18,7 +18,8 @@ CWorld::CSoundGroupData::CSoundGroupData(int grpId, CAssetId agsc) : x0_groupId(
CDummyWorld::CDummyWorld(CAssetId mlvlId, bool loadMap) : x4_loadMap(loadMap), xc_mlvlId(mlvlId) {
SObjectTag tag{FOURCC('MLVL'), mlvlId};
x34_loadBuf.reset(new u8[g_ResFactory->ResourceSize(tag)]);
x38_bufSz = g_ResFactory->ResourceSize(tag);
x34_loadBuf.reset(new u8[x38_bufSz]);
x30_loadToken = g_ResFactory->LoadResourceAsync(tag, x34_loadBuf.get());
}
@ -99,10 +100,9 @@ void CWorldLayers::ReadWorldLayers(athena::io::MemoryReader& r, int version, CAs
bool CDummyWorld::ICheckWorldComplete() {
switch (x8_phase) {
case Phase::Loading: {
if (x30_loadToken && !x30_loadToken->IsComplete())
if (!x30_loadToken->IsComplete())
return false;
x30_loadToken.reset();
athena::io::MemoryReader r(x34_loadBuf.get(), UINT32_MAX, false);
athena::io::MemoryReader r(x34_loadBuf.get(), x38_bufSz);
r.readUint32Big();
int version = r.readUint32Big();
x10_strgId = r.readUint32Big();
@ -141,6 +141,10 @@ bool CDummyWorld::ICheckWorldComplete() {
CWorldLayers::ReadWorldLayers(r, version, xc_mlvlId);
x30_loadToken.reset();
x34_loadBuf.reset();
x38_bufSz = 0;
if (x4_loadMap)
x8_phase = Phase::LoadingMap;
else {
@ -179,8 +183,9 @@ CWorld::CWorld(IObjectStore& objStore, IFactory& resFactory, CAssetId mlvlId)
: x8_mlvlId(mlvlId), x60_objectStore(objStore), x64_resFactory(resFactory) {
x70_24_currentAreaNeedsAllocation = true;
SObjectTag tag{FOURCC('MLVL'), mlvlId};
x40_loadBuf.reset(new u8[resFactory.ResourceSize(tag)]);
resFactory.LoadResourceAsync(tag, x40_loadBuf.get());
x44_bufSz = resFactory.ResourceSize(tag);
x40_loadBuf.reset(new u8[x44_bufSz]);
x3c_loadToken = resFactory.LoadResourceAsync(tag, x40_loadBuf.get());
}
CWorld::~CWorld() {
@ -277,9 +282,9 @@ bool CWorld::CheckWorldComplete(CStateManager* mgr, TAreaId id, CAssetId mreaId)
switch (x4_phase) {
case Phase::Loading: {
if (!x40_loadBuf)
if (!x3c_loadToken->IsComplete())
return false;
athena::io::MemoryReader r(x40_loadBuf.get(), UINT32_MAX);
athena::io::MemoryReader r(x40_loadBuf.get(), x44_bufSz);
r.readUint32Big();
int version = r.readUint32Big();
xc_strgId = r.readUint32Big();
@ -338,6 +343,9 @@ bool CWorld::CheckWorldComplete(CStateManager* mgr, TAreaId id, CAssetId mreaId)
CWorldLayers::ReadWorldLayers(r, version, x8_mlvlId);
x3c_loadToken.reset();
x40_loadBuf.reset();
x44_bufSz = 0;
x4_phase = Phase::LoadingMap;
[[fallthrough]];
}

View File

@ -47,7 +47,7 @@ class CDummyWorld : public IWorld {
TLockedToken<CMapWorld> x2c_mapWorld;
std::shared_ptr<IDvdRequest> x30_loadToken;
std::unique_ptr<uint8_t[]> x34_loadBuf;
// u32 x38_bufSz;
u32 x38_bufSz;
TAreaId x3c_curAreaId = kInvalidAreaId;
public:
@ -116,9 +116,9 @@ private:
CAssetId x24_mapwId;
TLockedToken<CMapWorld> x28_mapWorld;
std::vector<CRelay> x2c_relays;
// AsyncTask x3c_loadToken;
std::shared_ptr<IDvdRequest> x3c_loadToken;
std::unique_ptr<uint8_t[]> x40_loadBuf;
// u32 x44_bufSz;
u32 x44_bufSz;
u32 x48_chainCount = 0;
CGameArea* x4c_chainHeads[5] = {};

2
amuse

@ -1 +1 @@
Subproject commit a4b8946ee2a395477683e40088aaa5d1d2245194
Subproject commit aa5abd5ff5561f3b105a20046588fa1d8bd7785c