Various CScriptSpecialFunction implementation, more debugOverlay CVars

This commit is contained in:
Phillip Stephens 2018-06-08 14:00:18 -07:00
parent 8f9d7da3ee
commit c0b8b89a9b
19 changed files with 490 additions and 37 deletions

View File

@ -26,6 +26,107 @@ static logvisor::Module Log("urde::SpecMP2");
extern hecl::Database::DataSpecEntry SpecEntMP2;
extern hecl::Database::DataSpecEntry SpecEntMP2ORIG;
static const std::unordered_set<uint32_t> IndividualOrigIDs =
{
0xB7BBD0B4,
0x1F9DA858,
0x2A13C23E,
0xF13452F8,
0xA91A7703,
0xC042EC91,
0x12A12131,
0x5F556002,
0xA9798329,
0xB306E26F,
0xCD7B1ACA,
0x8ADA8184,
0x1A29C0E6,
0x5D9F9796,
0x951546A8,
0x7946C4C5,
0x409AA72E,
};
struct OriginalIDs
{
static void Generate(PAKRouter<DNAMP2::PAKBridge>& pakRouter, hecl::Database::Project& project)
{
std::unordered_set<UniqueID32> addedIDs;
std::vector<UniqueID32> originalIDs;
pakRouter.enumerateResources([&](const DNAMP1::PAK::Entry* ent) {
if (ent->type == FOURCC('MLVL') ||
ent->type == FOURCC('SCAN') ||
ent->type == FOURCC('MREA') ||
IndividualOrigIDs.find(ent->id.toUint32()) != IndividualOrigIDs.end())
{
if (addedIDs.find(ent->id) == addedIDs.cend())
{
addedIDs.insert(ent->id);
originalIDs.push_back(ent->id);
}
}
return true;
});
std::sort(originalIDs.begin(), originalIDs.end());
athena::io::YAMLDocWriter yamlW("MP2OriginalIDs");
for (const UniqueID32& id : originalIDs)
{
hecl::ProjectPath path = pakRouter.getWorking(id);
yamlW.writeString(id.toString().c_str(), path.getRelativePathUTF8());
}
hecl::ProjectPath path(project.getProjectWorkingPath(), "MP2/!original_ids.yaml");
path.makeDirChain(false);
athena::io::FileWriter fileW(path.getAbsolutePath());
yamlW.finish(&fileW);
}
static void Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath)
{
hecl::Database::Project& project = inPath.getProject();
athena::io::YAMLDocReader r;
athena::io::FileReader fr(inPath.getAbsolutePath());
if (!fr.isOpen() || !r.parse(&fr))
return;
std::vector<std::pair<UniqueID32, UniqueID32>> originalIDs;
originalIDs.reserve(r.getRootNode()->m_mapChildren.size());
for (const auto& node : r.getRootNode()->m_mapChildren)
{
char* end = const_cast<char*>(node.first.c_str());
u32 id = strtoul(end, &end, 16);
if (end != node.first.c_str() + 8)
continue;
hecl::ProjectPath path(project.getProjectWorkingPath(), node.second->m_scalarString.c_str());
originalIDs.push_back(std::make_pair(id, path.hash().val32()));
}
std::sort(originalIDs.begin(), originalIDs.end(),
[](const std::pair<UniqueID32, UniqueID32>& a, const std::pair<UniqueID32, UniqueID32>& b) {
return a.first < b.first;
});
athena::io::FileWriter w(outPath.getAbsolutePath());
w.writeUint32Big(originalIDs.size());
for (const auto& idPair : originalIDs)
{
idPair.first.write(w);
idPair.second.write(w);
}
std::sort(originalIDs.begin(), originalIDs.end(),
[](const std::pair<UniqueID32, UniqueID32>& a, const std::pair<UniqueID32, UniqueID32>& b) {
return a.second < b.second;
});
for (const auto& idPair : originalIDs)
{
idPair.second.write(w);
idPair.first.write(w);
}
}
};
struct SpecMP2 : SpecBase
{
bool checkStandaloneID(const char* id) const
@ -42,12 +143,21 @@ struct SpecMP2 : SpecBase
hecl::ProjectPath m_workPath;
hecl::ProjectPath m_cookPath;
PAKRouter<DNAMP2::PAKBridge> m_pakRouter;
IDRestorer<UniqueID32> m_idRestorer;
void setThreadProject()
{
SpecBase::setThreadProject();
UniqueIDBridge::SetIDRestorer(&m_idRestorer);
}
SpecMP2(const hecl::Database::DataSpecEntry* specEntry, hecl::Database::Project& project, bool pc)
: SpecBase(specEntry, project, pc),
m_workPath(project.getProjectWorkingPath(), _S("MP2")),
m_cookPath(project.getProjectCookedPath(SpecEntMP2), _S("MP2")),
m_pakRouter(*this, m_workPath, m_cookPath) {}
m_pakRouter(*this, m_workPath, m_cookPath),
m_idRestorer({project.getProjectWorkingPath(), "MP2/!original_ids.yaml"}, project)
{}
void buildPaks(nod::Node& root,
const std::vector<hecl::SystemString>& args,
@ -281,6 +391,9 @@ struct SpecMP2 : SpecBase
process.waitUntilComplete();
/* Generate original ID mapping for MLVL and SCAN entries - marks complete project */
OriginalIDs::Generate(m_pakRouter, m_project);
return true;
}
@ -413,6 +526,20 @@ struct SpecMP2 : SpecBase
DNAMAPU::MAPU::Cook(mapu, out);
progress(_S("Done"));
}
UniqueID32 newToOriginal(urde::CAssetId id) const
{
if (UniqueID32 origId = m_idRestorer.newToOriginal({uint32_t(id.Value()), true}))
return {origId.toUint32(), true};
return {uint32_t(id.Value()), true};
}
urde::CAssetId originalToNew(UniqueID32 id) const
{
if (UniqueID32 newId = m_idRestorer.originalToNew(id))
return newId.toUint32();
return id.toUint32();
}
};
hecl::Database::DataSpecEntry SpecEntMP2

View File

@ -160,7 +160,7 @@ CGameState::CGameState(CBitStreamReader& stream, u32 saveIdx)
for (u32 i = 0; i < 128; i++)
x0_[i] = stream.ReadEncoded(8);
//u32 tsSeconds = stream.ReadEncoded(32);
stream.ReadEncoded(32);
x228_24_hardMode = stream.ReadEncoded(1);
x228_25_initPowerupsAtFirstSpawn = stream.ReadEncoded(1);
@ -173,7 +173,6 @@ CGameState::CGameState(CBitStreamReader& stream, u32 saveIdx)
xa0_playTime = conv.doub;
x98_playerState = std::make_shared<CPlayerState>(stream);
//float currentHealth = x98_playerState->GetHealthInfo().GetHP();
x17c_gameOptions = CGameOptions(stream);
x1f8_hintOptions = CHintOptions(stream);

View File

@ -180,6 +180,11 @@ bool CMemoryCardSys::InitializePump()
return false;
}
std::pair<TAreaId, s32> CMemoryCardSys::GetAreaAndWorldIdForSaveId(s32 saveId) const
{
return {kInvalidAreaId, -1};
}
void CMemoryCardSys::CCardFileInfo::LockBannerToken(CAssetId bannerTxtr, CSimplePool& sp)
{
x3c_bannerTex = bannerTxtr;

View File

@ -164,6 +164,7 @@ public:
}
};
std::pair<TAreaId, s32> GetAreaAndWorldIdForSaveId(s32 saveId) const;
static kabufuda::ProbeResults CardProbe(kabufuda::ECardSlot port);
static ECardResult MountCard(kabufuda::ECardSlot port);
static ECardResult UnmountCard(kabufuda::ECardSlot port);

View File

@ -69,13 +69,14 @@ CPlayerState::CPlayerState()
CPlayerState::CPlayerState(CBitStreamReader& stream)
: x188_staticIntf(5)
{
x4_enabledItems = u32(stream.ReadEncoded(0x20u));
x0_24_alive = true;
x4_enabledItems = u32(stream.ReadEncoded(32));
union
{
float fHP;
u32 iHP;
} hp;
hp.iHP = u32(stream.ReadEncoded(0x20u));
hp.iHP = u32(stream.ReadEncoded(32));
xc_health.SetHP(hp.fHP);
x8_currentBeam = EBeamId(stream.ReadEncoded(CBitStreamReader::GetBitCount(5)));
x20_currentSuit = EPlayerSuit(stream.ReadEncoded(CBitStreamReader::GetBitCount(4)));

View File

@ -469,7 +469,7 @@ public:
}
TUniqueId GetPlayerActorHead() const { return xf6c_playerActorHead; }
void SetPlayerActorHead(TUniqueId id) { xf6c_playerActorHead = id; }
std::shared_ptr<CWorldLayerState>& WorldLayerStateNC() { return x8c8_worldLayerState; }
static float g_EscapeShakeCountdown;
static bool g_EscapeShakeCountdownInit;
};

View File

@ -7,6 +7,8 @@ namespace urde
{
enum class ERumbleFxId
{
Zero = 0,
One = 1,
CameraShake = 6,
EscapeSequenceShake = 7,
PlayerBump = 11,
@ -14,7 +16,11 @@ enum class ERumbleFxId
PlayerMissileFire = 13,
PlayerGrappleFire = 14,
PlayerLand = 15,
PlayerGrappleSwoosh = 17
PlayerGrappleSwoosh = 17,
Twenty = 20,
TwentyOne = 21,
TwentyTwo = 22,
TwentyThree = 23
};
enum class ERumblePriority
{

View File

@ -1,5 +1,6 @@
#include "CEnvFxManager.hpp"
#include "Graphics/CTexture.hpp"
#include "CActor.hpp"
namespace urde
{
@ -43,4 +44,8 @@ void CEnvFxManager::Cleanup()
xb70_ = 0;
}
void CEnvFxManager::sub801e4f10(CActor*, float, const CStateManager& , u32, u32)
{
}
}

View File

@ -10,6 +10,7 @@ namespace urde
{
class CStateManager;
class CTexture;
class CActor;
enum class EEnvFxType
{
@ -85,6 +86,7 @@ public:
bool GetX24() const { return x24_; }
float GetRainMagnitude() const { return x30_rainMagnitude; }
void Cleanup();
void sub801e4f10(CActor*, float, const CStateManager&, u32, u32);
};
}

View File

@ -428,7 +428,7 @@ CGameArea::CGameArea(CInputStream& in, int idx, int mlvlVersion)
x84_mrea = in.readUint32Big();
if (mlvlVersion > 15)
x88_areaId = in.readUint32Big();
x88_areaId = in.readInt32Big();
else
x88_areaId = -1;

View File

@ -100,13 +100,13 @@ class CGameArea final : public IGameArea
friend class CWorld;
friend class CStateManager;
int x4_selfIdx;
TAreaId x4_selfIdx;
CAssetId x8_nameSTRG;
zeus::CTransform xc_transform;
zeus::CTransform x3c_invTransform;
zeus::CAABox x6c_aabb;
CAssetId x84_mrea;
u32 x88_areaId;
s32 x88_areaId;
std::vector<u16> x8c_attachedAreaIndices;
std::vector<SObjectTag> x9c_deps1;
std::vector<SObjectTag> xac_deps2;
@ -372,6 +372,8 @@ public:
CGameArea* GetNext() const { return x130_next; }
static void WarmupShaders(const SObjectTag& mreaTag);
s32 GetAreaSaveId() const { return x88_areaId; }
};
}

View File

@ -1,8 +1,11 @@
#include "CScriptPlatform.hpp"
#include "Collision/CMaterialList.hpp"
#include "Collision/CCollidableOBBTreeGroup.hpp"
#include "World/CScriptWaypoint.hpp"
#include "World/CScriptColorModulate.hpp"
#include "World/CWorld.hpp"
#include "CStateManager.hpp"
#include "TCastTo.hpp"
namespace urde
{
@ -18,26 +21,173 @@ static CMaterialList MakePlatformMaterialList()
CScriptPlatform::CScriptPlatform(TUniqueId uid, std::string_view name, const CEntityInfo& info,
const zeus::CTransform& xf, CModelData&& mData, const CActorParameters& actParms,
const zeus::CAABox& aabb, float f1, bool, float f2, bool active,
const zeus::CAABox& aabb, float f1, bool b1, float f2, bool active,
const CHealthInfo& hInfo, const CDamageVulnerability& dVuln,
const std::experimental::optional<TLockedToken<CCollidableOBBTreeGroupContainer>>& dcln,
bool, u32, u32)
bool b2, u32 w1, u32 w2)
: CPhysicsActor(uid, active, name, info, xf, std::move(mData), MakePlatformMaterialList(), aabb, SMoverData(15000.f),
actParms, 0.3f, 0.1f)
, x28c_(hInfo)
, x294_(hInfo)
, x29c_(dVuln)
, x25c_currentMass(f1)
, x28c_initialHealth(hInfo)
, x294_health(hInfo)
, x29c_damageVuln(dVuln)
, x304_treeGroupContainer(dcln)
{
x348_ = f2;
x34c_ = w1;
x350_ = w2;
x356_24_dead = false;;
x356_25_ = false;
x356_26_ = b1;
x356_27_ = false;
x356_28_ = b2;
x356_29_ = false;
x356_30_ = false;
x356_31_ = true;
CActor::SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(
CMaterialList(EMaterialTypes::Solid),
CMaterialList(EMaterialTypes::NoStaticCollision, EMaterialTypes::NoPlatformCollision, EMaterialTypes::Platform)));
if (x304_treeGroupContainer)
x314_treeGroup = std::make_unique<CCollidableOBBTreeGroup>(x304_treeGroupContainer->GetObj(), x68_material);
}
void CScriptPlatform::Accept(IVisitor& visitor) { visitor.Visit(this); }
void CScriptPlatform::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr)
{
switch(msg)
{
case EScriptObjectMessage::InitializedInArea:
BuildSlaveList(mgr);
break;
case EScriptObjectMessage::AddPlatformRider:
AddRider(x318_riders, uid, this, mgr);
break;
case EScriptObjectMessage::Stop:
{
x25c_currentMass = 0.f;
Stop();
break;
}
case EScriptObjectMessage::Next:
{
x25a_targetWaypoint = GetNext(x258_currentWaypoint, mgr);
if (x25a_targetWaypoint == kInvalidUniqueId)
mgr.SendScriptMsg(this, GetUniqueId(), EScriptObjectMessage::Stop);
else if (TCastToPtr<CScriptWaypoint> wp = mgr.ObjectById(x25a_targetWaypoint))
{
x25c_currentMass = 0.f;
Stop();
x270_ = wp->GetTranslation() - GetTranslation();
SetTranslation(wp->GetTranslation());
x258_currentWaypoint = x25a_targetWaypoint;
x25a_targetWaypoint = GetNext(x258_currentWaypoint, mgr);
mgr.SendScriptMsg(wp, GetUniqueId(), EScriptObjectMessage::Arrived);
#if 0
if (!x328_slaves1.empty() || !x338_slaves2.empty())
DragSlaves(bitVector, x270_);
/* TODO: Implement bitvector */
#endif
x270_ = zeus::CVector3f::skZero;
}
break;
}
case EScriptObjectMessage::Start:
{
x25a_targetWaypoint = GetNext(x258_currentWaypoint, mgr);
if (x25a_targetWaypoint == kInvalidUniqueId)
mgr.SendScriptMsg(this, GetUniqueId(), EScriptObjectMessage::Stop);
else
x25c_currentMass = 0.f;
break;
}
case EScriptObjectMessage::Reset:
{
x356_24_dead = false;
x294_health = x28c_initialHealth;
break;
}
case EScriptObjectMessage::Increment:
{
if (GetActive())
CScriptColorModulate::FadeInHelper(mgr, GetUniqueId(), x268_fadeInTime);
else
mgr.SendScriptMsg(this, GetUniqueId(), EScriptObjectMessage::Activate);
break;
}
case EScriptObjectMessage::Decrement:
CScriptColorModulate::FadeOutHelper(mgr, GetUniqueId(), x26c_fadeOutTime);
break;
case EScriptObjectMessage::Deleted:
DecayRiders(x318_riders, 0.f, mgr);
break;
default:
break;
}
CPhysicsActor::AcceptScriptMsg(msg, uid, mgr);
}
void CScriptPlatform::PreThink(float dt, CStateManager& mgr)
{
DecayRiders(x318_riders, dt, mgr);
x264_ -= dt;
x260_ -= dt;
if (x260_ <= 0.f)
{
x270_ = zeus::CVector3f::skZero;
zeus::CTransform xf = x34_transform;
CMotionState mState = GetMotionState();
if (GetActive())
{
for (SRiders& rider : x318_riders)
{
if (TCastToPtr<CPhysicsActor> act = mgr.ObjectById(rider.x0_uid))
rider.x8_transform.origin = x34_transform.transposeRotate(act->GetTranslation() - GetTranslation());
}
}
}
x27c_ = Move(dt, mgr);
}
void CScriptPlatform::Think(float dt, CStateManager& mgr)
{
if (!GetActive())
return;
if (HasModelData() && GetModelData()->HasAnimData())
{
if (!x356_25_)
UpdateAnimation(dt, mgr, true);
if (x356_28_ && mgr.GetWorld()->GetNeededEnvFx() == EEnvFxType::Rain)
{
if (HasModelData() && (GetModelData()->HasAnimData() || GetModelData()->HasNormalModel())
&& mgr.GetEnvFxManager()->GetRainMagnitude() != 0.f)
mgr.GetEnvFxManager()->sub801e4f10(this, 0.f, mgr, x34c_, x350_);
}
}
#if 0
if (!x328_slaves1.empty() || !x338_slaves2.empty())
DragSlaves(bitVector, x270_);
/* TODO: Implement bitvector */
#endif
if (x356_24_dead)
return;
if (HealthInfo(mgr)->GetHP() <= 0.f)
{
x356_24_dead = true;
SendScriptMsgs(EScriptObjectState::Dead, mgr, EScriptObjectMessage::None);
}
}
std::experimental::optional<zeus::CAABox> CScriptPlatform::GetTouchBounds() const
{
if (x314_treeGroup)
@ -64,4 +214,68 @@ bool CScriptPlatform::IsSlave(TUniqueId id) const
[id](const SRiders& rider){ return rider.x0_uid == id; });
return search != x338_slaves2.end();
}
void CScriptPlatform::BuildSlaveList(CStateManager& mgr)
{
}
void CScriptPlatform::AddRider(std::vector<SRiders>&, TUniqueId, const CPhysicsActor*, CStateManager& )
{
}
TUniqueId CScriptPlatform::GetNext(TUniqueId uid, CStateManager& mgr)
{
TCastToConstPtr<CScriptWaypoint> nextWp = mgr.GetObjectById(uid);
if (!nextWp)
return GetWaypoint(mgr);
TUniqueId next = nextWp->NextWaypoint(mgr);
if (TCastToConstPtr<CScriptWaypoint>(mgr.GetObjectById(next)))
x25c_currentMass = xe8_mass;
return next;
}
TUniqueId CScriptPlatform::GetWaypoint(CStateManager& mgr)
{
for (const SConnection& conn : x20_conns)
{
if (conn.x4_msg == EScriptObjectMessage::Follow)
return mgr.GetIdForScript(conn.x8_objId);
}
return kInvalidUniqueId;
}
void CScriptPlatform::SplashThink(const zeus::CAABox &, const CFluidPlane &, float, CStateManager &) const
{
}
zeus::CQuaternion CScriptPlatform::Move(float, CStateManager& mgr)
{
TUniqueId nextWaypoint = x25a_targetWaypoint;
if (x25a_targetWaypoint == kInvalidUniqueId)
nextWaypoint = GetNext(x258_currentWaypoint, mgr);
TCastToPtr<CScriptWaypoint> wp = mgr.ObjectById(nextWaypoint);
if (x258_currentWaypoint != kInvalidUniqueId)
{
if (wp && !wp->GetActive())
nextWaypoint = GetNext(x258_currentWaypoint, mgr);
if (nextWaypoint == kInvalidUniqueId)
{
if (TCastToPtr<CScriptWaypoint> wp = mgr.ObjectById(x258_currentWaypoint))
if (wp->GetActive())
nextWaypoint = wp->GetUniqueId();
}
}
if (nextWaypoint == kInvalidUniqueId)
return zeus::CQuaternion::skNoRotation;
/* TODO: Finish */
return {};
}
}

View File

@ -11,6 +11,7 @@ namespace urde
{
class CCollidableOBBTreeGroup;
class CCollidableOBBTreeGroupContainer;
class CFluidPlane;
struct SRiders
{
@ -22,18 +23,18 @@ struct SRiders
class CScriptPlatform : public CPhysicsActor
{
u32 x254_;
TUniqueId x258_ = kInvalidUniqueId;
TUniqueId x25a_ = kInvalidUniqueId;
float x25c_;
float x260_;
float x264_;
float x268_;
float x26c_;
TUniqueId x258_currentWaypoint = kInvalidUniqueId;
TUniqueId x25a_targetWaypoint = kInvalidUniqueId;
float x25c_currentMass;
float x260_ = 0.f;
float x264_ = 0.f;
float x268_fadeInTime = 0.f;
float x26c_fadeOutTime = 0.f;
zeus::CVector3f x270_;
zeus::CQuaternion x27c_;
CHealthInfo x28c_;
CHealthInfo x294_;
CDamageVulnerability x29c_;
CHealthInfo x28c_initialHealth;
CHealthInfo x294_health;
CDamageVulnerability x29c_damageVuln;
std::experimental::optional<TLockedToken<CCollidableOBBTreeGroupContainer>> x304_treeGroupContainer;
std::unique_ptr<CCollidableOBBTreeGroup> x314_treeGroup;
std::vector<SRiders> x318_riders;
@ -42,12 +43,12 @@ class CScriptPlatform : public CPhysicsActor
float x348_;
u32 x34c_;
u32 x350_;
TUniqueId x354_;
TUniqueId x354_ = kInvalidUniqueId;
union
{
struct
{
bool x356_24_ : 1;
bool x356_24_dead : 1;
bool x356_25_ : 1;
bool x356_26_ : 1;
bool x356_27_ : 1;
@ -66,6 +67,9 @@ public:
const std::experimental::optional<TLockedToken<CCollidableOBBTreeGroupContainer>>& dcln, bool, u32, u32);
void Accept(IVisitor& visitor);
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&);
void PreThink(float, CStateManager&);
void Think(float, CStateManager&);
std::experimental::optional<zeus::CAABox> GetTouchBounds() const;
bool IsRider(TUniqueId id) const;
bool IsSlave(TUniqueId id) const;
@ -75,6 +79,17 @@ public:
const std::vector<SRiders>& GetX338() const { return x338_slaves2; }
void AddSlave(TUniqueId, CStateManager&) {}
bool HasComplexCollision() const { return x314_treeGroup.operator bool(); }
void BuildSlaveList(CStateManager&);
void AddRider(std::vector<SRiders>&, TUniqueId, const CPhysicsActor*, CStateManager&);
TUniqueId GetNext(TUniqueId, CStateManager&);
TUniqueId GetWaypoint(CStateManager&);
const CDamageVulnerability* GetDamageVulnerability() const { return &x29c_damageVuln; }
CHealthInfo* HealthInfo(CStateManager&) { return &x294_health; }
void DecayRiders(std::vector<SRiders>&, float, CStateManager&) {}
virtual void SplashThink(const zeus::CAABox&, const CFluidPlane&, float, CStateManager&) const;
virtual zeus::CQuaternion Move(float, CStateManager&);
};
}

View File

@ -4,6 +4,7 @@
#include "Audio/CSfxManager.hpp"
#include "TCastTo.hpp"
#include "GameGlobalObjects.hpp"
#include "CMemoryCardSys.hpp"
#include "CGameState.hpp"
#include "CStateManager.hpp"
#include "IMain.hpp"
@ -17,7 +18,7 @@ CScriptSpecialFunction::CScriptSpecialFunction(TUniqueId uid, std::string_view n
const zeus::CTransform& xf, ESpecialFunction func,
std::string_view lcName, float f1, float f2, float f3, float f4,
const zeus::CVector3f& vec, const zeus::CColor& col, bool active,
const CDamageInfo& dInfo, CAssetId aId1, CAssetId aId2, CAssetId aId3,
const CDamageInfo& dInfo, s32 aId1, s32 aId2, CAssetId aId3,
s16 sId1, s16 sId2, s16 sId3)
: CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(), CActorParameters::None(),
kInvalidUniqueId)
@ -33,8 +34,8 @@ CScriptSpecialFunction::CScriptSpecialFunction(TUniqueId uid, std::string_view n
, x170_(CSfxManager::TranslateSFXID(sId1))
, x172_(CSfxManager::TranslateSFXID(sId2))
, x174_(CSfxManager::TranslateSFXID(sId3))
, x1bc_(aId1)
, x1c0_(aId2)
, x1bc_areaSaveId(aId1)
, x1c0_layerIdx(aId2)
, x1c4_(aId3)
{
x1e4_26_ = true;
@ -88,6 +89,15 @@ void CScriptSpecialFunction::Think(float dt, CStateManager& mgr)
default: break;
}
}
static const ERumbleFxId fxTranslation[6] =
{
ERumbleFxId::Twenty,
ERumbleFxId::One,
ERumbleFxId::TwentyOne,
ERumbleFxId::TwentyTwo,
ERumbleFxId::TwentyThree,
ERumbleFxId::Zero
};
void CScriptSpecialFunction::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr)
{
@ -332,8 +342,54 @@ void CScriptSpecialFunction::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId
}
case ESpecialFunction::ScriptLayerController:
{
if (msg == EScriptObjectMessage::Decrement || msg == EScriptObjectMessage::Increment)
{
if (x1bc_areaSaveId != -1 && x1c0_layerIdx != -1)
{
TAreaId aId = mgr.GetWorld()->GetAreaIdForSaveId(x1bc_areaSaveId);
std::shared_ptr<CWorldLayerState> worldLayerState;
if (aId != kInvalidAreaId)
worldLayerState = mgr.WorldLayerStateNC();
else
{
std::pair<CAssetId, TAreaId> worldAreaPair = g_MemoryCardSys->GetAreaAndWorldIdForSaveId(x1bc_areaSaveId);
if (worldAreaPair.first.IsValid())
{
worldLayerState = g_GameState->StateForWorld(worldAreaPair.first).GetLayerState();
aId = worldAreaPair.second;
}
}
if (aId != kInvalidAreaId)
worldLayerState->SetLayerActive(aId, x1c0_layerIdx, msg == EScriptObjectMessage::Increment);
}
}
break;
}
/*
For some bizarre reason ScriptLayerController drops into EnvFxDensityController
[[fallthrough]];
We won't do that though
*/
case ESpecialFunction::EnvFxDensityController:
{
if (msg == EScriptObjectMessage::Action)
mgr.GetEnvFxManager()->SetFxDensity(s32(x100_), xfc_);
break;
}
case ESpecialFunction::RumbleEffect:
if (msg == EScriptObjectMessage::Action)
{
s32 rumbFx = s32(x100_);
/* 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
*/
if (rumbFx < 0 || rumbFx >= 6)
break;
mgr.GetRumbleManager().Rumble(mgr, fxTranslation[rumbFx], 1.f, ERumblePriority::One);
}
break;
default:
break;
}

View File

@ -92,8 +92,8 @@ private:
u32 x1a8_ = 2;
zeus::CVector3f x1ac_ = zeus::CVector3f::skZero;
bool x1b8_ = true;
CAssetId x1bc_;
CAssetId x1c0_;
s32 x1bc_areaSaveId;
s32 x1c0_layerIdx;
CAssetId x1c4_;
std::experimental::optional<zeus::CAABox> x1c8_;
union
@ -118,7 +118,7 @@ private:
public:
CScriptSpecialFunction(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, ESpecialFunction,
std::string_view, float, float, float, float, const zeus::CVector3f&, const zeus::CColor&,
bool, const CDamageInfo&, CAssetId, CAssetId, CAssetId, s16, s16, s16);
bool, const CDamageInfo&, s32, s32, CAssetId, s16, s16, s16);
void Accept(IVisitor& visitor);
void Think(float, CStateManager &);

View File

@ -775,4 +775,23 @@ bool CWorld::AreSkyNeedsMet() const
return true;
return false;
}
TAreaId CWorld::GetAreaIdForSaveId(s32 saveId) const
{
if (saveId == -1)
return kInvalidAreaId;
if (x18_areas.size() <= 0)
return kInvalidAreaId;
TAreaId cur = 0;
for (const auto& area : x18_areas)
{
if (area->x88_areaId == saveId)
return cur;
++cur;
}
return kInvalidAreaId;
}
}

View File

@ -211,6 +211,7 @@ public:
EEnvFxType GetNeededEnvFx() const { return xc4_neededFx; }
CAssetId GetWorldAssetId() const { return x8_mlvlId; }
bool AreSkyNeedsMet() const;
TAreaId GetAreaIdForSaveId(s32 saveId) const;
};
struct CWorldLayers

View File

@ -2387,7 +2387,7 @@ CEntity* ScriptLoader::LoadFogVolume(CStateManager& mgr, CInputStream& in, int p
return new CScriptSpecialFunction(mgr.AllocateUniqueId(), name, info, ConvertEditorEulerToTransform4f(center, {}),
CScriptSpecialFunction::ESpecialFunction::FogVolume, "", flickerSpeed, f2, 0.f,
0.f, volume, fogColor, active, CDamageInfo(), CAssetId(), CAssetId(), CAssetId(),
0.f, volume, fogColor, active, CDamageInfo(), -1, -1, CAssetId(),
-1, -1, -1);
}
@ -2448,7 +2448,7 @@ CEntity* ScriptLoader::LoadEnvFxDensityController(CStateManager& mgr, CInputStre
return new CScriptSpecialFunction(mgr.AllocateUniqueId(), name, info, zeus::CTransform::Identity(),
CScriptSpecialFunction::ESpecialFunction::EnvFxDensityController, "", density, w1,
0.f, 0.f, zeus::CVector3f::skZero, zeus::CColor::skBlack, active, CDamageInfo(),
CAssetId(), CAssetId(), CAssetId(), -1, -1, -1);
-1, -1, CAssetId(), -1, -1, -1);
}
CEntity* ScriptLoader::LoadMagdolite(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)

@ -1 +1 @@
Subproject commit 53a4334b239e7653536e8663880a79660c93ebb6
Subproject commit 690a69707dea51eead11d4c0e7246603c6e8e52c