Implement WorldTeleporter and SpiderBallWaypoint

This commit is contained in:
Phillip Stephens 2017-08-08 15:12:14 -07:00
parent 69187353b9
commit ecff2b7f8d
16 changed files with 402 additions and 35 deletions

View File

@ -32,7 +32,7 @@ struct Application : boo::IApplicationCallback
m_fileMgr(_S("urde")),
m_cvarManager(m_fileMgr)
{
m_viewManager.reset(new ViewManager(m_fileMgr, m_cvarManager));
m_viewManager = std::make_unique<ViewManager>(m_fileMgr, m_cvarManager);
}
virtual ~Application() = default;
@ -74,7 +74,7 @@ struct Application : boo::IApplicationCallback
zeus::detectCPU();
for (const boo::SystemString& arg : app->getArgs())
{
if (arg.find(_S("--verbosity=")) == 0)
if (arg.find(_S("--verbosity=")) == 0 || arg.find(_S("-v=")) == 0)
{
hecl::SystemUTF8View utf8Arg(arg.substr(arg.find_last_of('=') + 1));
hecl::VerbosityLevel = atoi(utf8Arg.c_str());

View File

@ -49,6 +49,20 @@ public:
iterator begin() { return iterator(*this, x2008_firstId); }
iterator end() { return iterator(*this, kInvalidUniqueId); }
class const_iterator
{
friend class CObjectList;
const CObjectList& m_list;
TUniqueId m_id;
const_iterator(const CObjectList& list, TUniqueId id) : m_list(list), m_id(id) {}
public:
const_iterator& operator++() { m_id = m_list.GetNextObjectIndex(m_id); return *this; }
bool operator!=(const iterator& other) const { return m_id != other.m_id; }
const CEntity* operator*() const { return m_list.GetObjectById(m_id); }
};
const_iterator cbegin() const { return const_iterator(*this, x2008_firstId); }
const_iterator cend() const { return const_iterator(*this, kInvalidUniqueId); }
CObjectList(EGameObjectList listEnum);
void AddObject(CEntity& entity);

View File

@ -33,7 +33,7 @@ public:
inline float Float()
{
return Next() * 0.000015259022;
return Next() * 0.000015259022f;
}
inline float Range(float min, float max)
@ -43,9 +43,7 @@ public:
inline s32 Range(s32 min, s32 max)
{
s32 rnd = Next();
s32 diff = (max - min) + 1;
return min + (rnd - ((rnd / diff) * diff));
return min + (Next() % ((max - min) + 1));
}
static CRandom16* GetRandomNumber() {return g_randomNumber;}

View File

@ -405,6 +405,7 @@ public:
ResId GetPauseHUDMessage() const { return xf08_pauseHudMessage; }
void IncrementHUDMessageFrameCounter() { ++xf80_hudMessageFrameCount; }
bool ShouldQuitGame() const { return xf94_25_quitGame; }
void SetShouldQuitGame(bool should) { xf94_25_quitGame = should; }
void SetInSaveUI(bool b) { xf94_28_inSaveUI = b; }
void SetInMapScreen(bool b) { xf94_27_inMapScreen = b; }
bool GetInMapScreen() const { return xf94_27_inMapScreen; }
@ -427,6 +428,7 @@ public:
CActorModelParticles* GetActorModelParticles() const { return x884_actorModelParticles; }
const std::shared_ptr<CMapWorldInfo>& MapWorldInfo() const { return x8c0_mapWorldInfo; }
const std::shared_ptr<CWorldTransManager>& WorldTransManager() const { return x8c4_worldTransManager; }
const std::shared_ptr<CWorldLayerState>& LayerState() const { return x8c8_worldLayerState; }
CPlayer& GetPlayer() const { return *x84c_player; }

View File

@ -1,4 +1,5 @@
#include "CConsoleOutputWindow.hpp"
#include "Graphics/CGraphics.hpp"
namespace urde
{

View File

@ -41,6 +41,7 @@ public:
virtual bool Proc()=0;
virtual void Shutdown()=0;
virtual boo::IWindow* GetMainWindow() const=0;
virtual void SetFlowState(EFlowState) = 0;
};
}

View File

@ -20,7 +20,7 @@ public:
x4_charIdx(in.readUint32Big()),
x8_defaultAnim(in.readUint32Big()) {}
u32 GetACSFile() const { return x0_ancs; }
ResId GetACSFile() const { return x0_ancs; }
u32 GetCharacter() const { return x4_charIdx; }
u32 GetInitialAnimation() const { return x8_defaultAnim; }
void SetCharacter(u32 charIdx) { x4_charIdx = charIdx; }

View File

@ -53,6 +53,7 @@ set(WORLD_SOURCES
CScriptWorldTeleporter.hpp CScriptWorldTeleporter.cpp
CScriptCameraWaypoint.hpp CScriptCameraWaypoint.cpp
CScriptCoverPoint.hpp CScriptCoverPoint.cpp
CScriptSpiderBallWaypoint.hpp CScriptSpiderBallWaypoint.cpp
CScriptSpawnPoint.hpp CScriptSpawnPoint.cpp
CScriptCameraHint.hpp CScriptCameraHint.cpp
CScriptPickup.hpp CScriptPickup.cpp

View File

@ -0,0 +1,94 @@
#include "CScriptSpiderBallWaypoint.hpp"
#include "CActorParameters.hpp"
#include "CStateManager.hpp"
#include "TCastTo.hpp"
namespace urde
{
CScriptSpiderBallWaypoint::CScriptSpiderBallWaypoint(TUniqueId uid, const std::string& name, const CEntityInfo& info,
const zeus::CTransform& xf, bool active, u32 w1)
: CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::Unknown),
CActorParameters::None(), kInvalidUniqueId)
, xe8_(w1)
{
}
void CScriptSpiderBallWaypoint::Accept(IVisitor& visitor)
{
visitor.Visit(this);
}
void CScriptSpiderBallWaypoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr)
{
CActor::AcceptScriptMsg(msg, uid, mgr);
if (msg == EScriptObjectMessage::InitializedInArea)
BuildWaypointListAndBounds(mgr);
else if (msg == EScriptObjectMessage::UNKM2)
SendScriptMsgs(EScriptObjectState::Arrived, mgr, EScriptObjectMessage::None);
}
void CScriptSpiderBallWaypoint::AccumulateBounds(const zeus::CVector3f& v)
{
if (!xfc_aabox)
xfc_aabox.emplace(v, v);
xfc_aabox->accumulateBounds(v);
}
void CScriptSpiderBallWaypoint::BuildWaypointListAndBounds(CStateManager& mgr)
{
u32 validConnections = 0;
for (const SConnection& conn : x20_conns)
{
if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Next)
{
TUniqueId uid = mgr.GetIdForScript(conn.x8_objId);
if (uid != kInvalidUniqueId)
{
static_cast<CScriptSpiderBallWaypoint*>(mgr.ObjectById(uid))->AddPreviousWaypoint(GetUniqueId());
++validConnections;
}
}
}
if (validConnections == 0)
AccumulateBounds(x34_transform.origin);
else
{
CScriptSpiderBallWaypoint* curWaypoint = this;
TUniqueId uid = curWaypoint->NextWaypoint(mgr, ECheckActiveWaypoint::Yes);
while (uid != kInvalidUniqueId)
{
curWaypoint = static_cast<CScriptSpiderBallWaypoint*>(mgr.ObjectById(uid));
uid = curWaypoint->NextWaypoint(mgr, ECheckActiveWaypoint::Yes);
}
curWaypoint->AccumulateBounds(x34_transform.origin);
}
}
void CScriptSpiderBallWaypoint::AddPreviousWaypoint(TUniqueId uid)
{
xec_waypoints.push_back(uid);
}
TUniqueId CScriptSpiderBallWaypoint::NextWaypoint(const CStateManager& mgr, ECheckActiveWaypoint checkActive)
{
for (const SConnection& conn : x20_conns)
{
if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Next)
{
TUniqueId uid = mgr.GetIdForScript(conn.x8_objId);
if (uid != kInvalidUniqueId)
{
const CEntity* ent = mgr.GetObjectById(uid);
if (ent && checkActive == ECheckActiveWaypoint::Yes && ent->GetActive())
return ent->GetUniqueId();
}
}
}
return kInvalidUniqueId;
}
}

View File

@ -0,0 +1,32 @@
#ifndef __URDE_CSCRIPTSPIDERBALLWAYPOINT_HPP__
#define __URDE_CSCRIPTSPIDERBALLWAYPOINT_HPP__
#include "CActor.hpp"
namespace urde
{
class CScriptSpiderBallWaypoint : public CActor
{
enum class ECheckActiveWaypoint
{
No,
Yes
};
u32 xe8_;
std::vector<TUniqueId> xec_waypoints;
std::experimental::optional<zeus::CAABox> xfc_aabox;
public:
CScriptSpiderBallWaypoint(TUniqueId, const std::string&, const CEntityInfo&, const zeus::CTransform&, bool, u32);
void Accept(IVisitor&);
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&);
void Render(const CStateManager& mgr) const { CActor::Render(mgr); }
void AddToRenderer(const zeus::CFrustum&, const CStateManager&) {}
std::experimental::optional<zeus::CAABox> GetTouchBounds() const { return xfc_aabox; }
void AccumulateBounds(const zeus::CVector3f&);
void BuildWaypointListAndBounds(CStateManager&);
void AddPreviousWaypoint(TUniqueId);
TUniqueId NextWaypoint(const CStateManager&, ECheckActiveWaypoint);
};
}
#endif // __URDE_CSCRIPTSPIDERBALLWAYPOINT_HPP__

View File

@ -1,10 +1,151 @@
#include "CScriptWorldTeleporter.hpp"
#include "CStateManager.hpp"
#include "CWorldTransManager.hpp"
#include "CWorld.hpp"
#include "CGameState.hpp"
#include "IMain.hpp"
#include "TCastTo.hpp"
namespace urde
{
CScriptWorldTeleporter::CScriptWorldTeleporter(TUniqueId uid, const std::string& name, const CEntityInfo& info,
bool active, u32, u32)
bool active, ResId worldId, ResId areaId)
: CEntity(uid, info, active, name)
, x34_worldId(worldId)
, x38_areaId(areaId)
, x3c_type(ETeleporterType::NoTransition)
, x40_24_upElevator(false)
, x40_25_inTransition(false)
, x40_27_fadeWhite(false)
{
}
CScriptWorldTeleporter::CScriptWorldTeleporter(TUniqueId uid, const std::string& name, const CEntityInfo& info,
bool active, ResId worldId, ResId areaId,
ResId playerAncs, u32 charIdx, u32 defaultAnim,
const zeus::CVector3f& playerScale, ResId platformModel,
const zeus::CVector3f& platformScale, ResId backgroundModel,
const zeus::CVector3f& backgroundScale, bool upElevator, u16 soundId,
u8 volume, u8 panning)
: CEntity(uid, info, active, name)
, x34_worldId(worldId)
, x38_areaId(areaId)
, x3c_type(ETeleporterType::Elevator)
, x40_24_upElevator(upElevator)
, x40_25_inTransition(false)
, x40_27_fadeWhite(false)
, x50_playerAnim(playerAncs, charIdx, defaultAnim)
, x5c_playerScale(playerScale)
, x68_platformModel(platformModel)
, x6c_platformScale(platformScale)
, x78_backgroundModel(backgroundModel)
, x7c_backgroundScale(backgroundScale)
, x88_soundId(CSfxManager::TranslateSFXID(soundId))
, x8a_volume(volume)
, x8b_panning(panning)
{
}
CScriptWorldTeleporter::CScriptWorldTeleporter(TUniqueId uid, const std::string& name, const CEntityInfo& info,
bool active, ResId worldId, ResId areaId, u16 soundId, u8 volume,
u8 panning, ResId fontId, ResId stringId, bool fadeWhite,
float charFadeIn, float charsPerSecond, float showDelay)
: CEntity(uid, info, active, name)
, x34_worldId(worldId)
, x38_areaId(areaId)
, x3c_type(ETeleporterType::Text)
, x40_24_upElevator(false)
, x40_25_inTransition(false)
, x40_27_fadeWhite(fadeWhite)
, x44_charFadeIn(charFadeIn)
, x48_charsPerSecond(charsPerSecond)
, x4c_showDelay(showDelay)
, x88_soundId(CSfxManager::TranslateSFXID(soundId))
, x8a_volume(volume)
, x8b_panning(panning)
, x8c_fontId(fontId)
, x90_stringId(stringId)
{
}
void CScriptWorldTeleporter::Accept(IVisitor& visitor)
{
visitor.Visit(this);
}
void CScriptWorldTeleporter::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr)
{
if (GetActive())
{
const std::shared_ptr<CWorldTransManager>& transMgr = mgr.WorldTransManager();
switch(msg)
{
case EScriptObjectMessage::Stop:
x40_25_inTransition = false;
transMgr->DisableTransition();
transMgr->SfxStop();
break;
case EScriptObjectMessage::Play:
StartTransition(mgr);
transMgr->SetSfx(x88_soundId, x8a_volume, x8b_panning);
transMgr->SfxStart();
break;
case EScriptObjectMessage::SetToZero:
{
const auto& world = mgr.WorldNC();
world->SetPauseState(true);
ResId currentWorld = g_GameState->CurrentWorldAssetId();
if (g_ResFactory->GetResourceTypeById(currentWorld) == SBIG('MLVL'))
{
StartTransition(mgr);
g_GameState->SetCurrentWorldId(x34_worldId);
g_GameState->CurrentWorldState().SetDesiredAreaAssetId(x38_areaId);
g_Main->SetFlowState(EFlowState::None);
mgr.SetShouldQuitGame(true);
}
else
{
x40_25_inTransition = false;
transMgr->DisableTransition();
g_GameState->SetCurrentWorldId(currentWorld);
}
break;
}
default:
break;
}
}
CEntity::AcceptScriptMsg(msg, uid, mgr);
}
void CScriptWorldTeleporter::StartTransition(CStateManager& mgr)
{
if (!x40_25_inTransition)
{
const auto& transMgr = mgr.WorldTransManager();
switch(x3c_type)
{
case ETeleporterType::NoTransition:
transMgr->DisableTransition();
break;
case ETeleporterType::Elevator:
if (x50_playerAnim.GetACSFile() != kInvalidResId && x50_playerAnim.GetCharacter() != -1)
{
transMgr->EnableTransition(CAnimRes(x50_playerAnim.GetACSFile(), x50_playerAnim.GetCharacter(),
x5c_playerScale, x50_playerAnim.GetInitialAnimation(),true),
x68_platformModel, x6c_platformScale, x78_backgroundModel,
x7c_backgroundScale, x40_24_upElevator);
x40_25_inTransition = true;
}
break;
case ETeleporterType::Text:
transMgr->EnableTransition(x8c_fontId, x90_stringId, 0, x40_27_fadeWhite, x44_charFadeIn, x48_charsPerSecond,
x4c_showDelay);
x40_25_inTransition = true;
break;
}
}
}
}

View File

@ -2,6 +2,7 @@
#define __CSCRIPTWORLDTELEPORTER_HPP__
#include "CEntity.hpp"
#include "CAnimationParameters.hpp"
#include "zeus/CVector3f.hpp"
namespace urde
@ -9,36 +10,52 @@ namespace urde
class CScriptWorldTeleporter : public CEntity
{
u32 x34_;
u32 x38_;
u32 x3c_ = 0;
enum class ETeleporterType
{
NoTransition,
Elevator,
Text
};
ResId x34_worldId;
ResId x38_areaId;
ETeleporterType x3c_type = ETeleporterType::NoTransition;
union
{
struct
{
bool x40_24_ : 1;
bool x40_25_ : 1;
bool x40_26_ : 1;
bool x40_27_ : 1;
bool x40_24_upElevator : 1;
bool x40_25_inTransition : 1;
bool x40_27_fadeWhite : 1;
};
u8 _dummy = 0;
};
float x44_ = 0.1f;
float x48_ = 8.0f;
float x4c_ = 0.0f;
u32 x50_ = -1;
u32 x54_ = -1;
u32 x58_ = 0;
zeus::CVector3f x5c_;
u32 x68_ = -1;
zeus::CVector3f x6c_;
u32 x78_ = -1;
zeus::CVector3f x7c_;
u32 x88_ = -1;
float x44_charFadeIn = 0.1f;
float x48_charsPerSecond = 8.0f;
float x4c_showDelay = 0.0f;
CAnimationParameters x50_playerAnim;
zeus::CVector3f x5c_playerScale;
ResId x68_platformModel = kInvalidResId;
zeus::CVector3f x6c_platformScale;
ResId x78_backgroundModel = kInvalidResId;
zeus::CVector3f x7c_backgroundScale;
u16 x88_soundId = -1;
u8 x8a_volume = 0;
u8 x8b_panning = 0;
ResId x8c_fontId;
ResId x90_stringId;
public:
CScriptWorldTeleporter(TUniqueId, const std::string&, const CEntityInfo&, bool, u32, u32);
CScriptWorldTeleporter(TUniqueId, const std::string&, const CEntityInfo&, bool, ResId, ResId);
CScriptWorldTeleporter(TUniqueId, const std::string&, const CEntityInfo&, bool, ResId, ResId, u16, u8, u8, ResId,
ResId, bool, float, float, float);
CScriptWorldTeleporter(TUniqueId, const std::string&, const CEntityInfo&, bool, ResId, ResId, ResId, u32, u32,
const zeus::CVector3f&, ResId, const zeus::CVector3f&, ResId, const zeus::CVector3f&, bool,
u16, u8, u8);
void Accept(IVisitor&);
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr);
void StartTransition(CStateManager&);
};
}

View File

@ -487,4 +487,19 @@ bool CWorldTransManager::WaitForModelsAndTextures()
return true;
}
void CWorldTransManager::SfxStop()
{
if (x28_sfxHandle)
{
CSfxManager::SfxStop(x28_sfxHandle);
x28_sfxHandle.reset();
}
}
void CWorldTransManager::SfxStart()
{
if (!x28_sfxHandle && x24_sfx != 0xFFFF)
x28_sfxHandle = CSfxManager::SfxStart(x24_sfx, x2c_volume, x2d_panning, false, 127, true, -1);
}
}

View File

@ -9,6 +9,7 @@
#include "Graphics/Shaders/CColoredQuadFilter.hpp"
#include "Graphics/Shaders/CTexturedQuadFilter.hpp"
#include "Graphics/Shaders/CCameraBlurFilter.hpp"
#include "Audio/CSfxManager.hpp"
namespace urde
{
@ -60,10 +61,10 @@ private:
float x18_bgOffset;
float x1c_bgHeight;
CRandom16 x20_random = CRandom16(99);
u16 x24_ = 1189;
u32 x28_ = 0;
u8 x2c_ = 127;
u8 x2d_ = 64;
u16 x24_sfx = 1189;
CSfxHandle x28_sfxHandle;
u8 x2c_volume = 127;
u8 x2d_panning = 64;
ETransType x30_type = ETransType::Disabled;
float x34_stopTime;
float x38_textStartTime = 0.f;
@ -121,6 +122,14 @@ public:
void DisableTransition();
void TouchModels();
ETransType GetTransType() { return x30_type; }
void SetSfx(u16 sfx, u8 volume, u8 panning)
{
x24_sfx = sfx;
x2c_volume = volume;
x2d_panning = panning;
}
void SfxStart();
void SfxStop();
static bool WaitForModelsAndTextures();
};

View File

@ -59,6 +59,7 @@
#include "CScriptCameraPitchVolume.hpp"
#include "CScriptCameraHintTrigger.hpp"
#include "CScriptVisorFlare.hpp"
#include "CScriptWorldTeleporter.hpp"
#include "CScriptBeam.hpp"
#include "CScriptMazeNode.hpp"
#include "Camera/CCinematicCamera.hpp"
@ -1847,9 +1848,50 @@ CEntity* ScriptLoader::LoadVisorFlare(CStateManager& mgr, CInputStream& in, int
CEntity* ScriptLoader::LoadWorldTeleporter(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)
{
if (propCount < 4 || propCount > 21)
{
Log.report(logvisor::Warning, "Incorrect number of props for WorldTeleporter");
return nullptr;
}
std::string name = mgr.HashInstanceName(in);
bool active = in.readBool();
ResId worldId = in.readUint32Big();
ResId areaId = in.readUint32Big();
if (propCount == 4)
return new CScriptWorldTeleporter(mgr.AllocateUniqueId(), name, info, active, worldId, areaId);
CAnimationParameters animParms = LoadAnimationParameters(in);
zeus::CVector3f playerScale = zeus::CVector3f::ReadBig(in);
ResId platformModel = in.readUint32Big();
zeus::CVector3f platformScale = zeus::CVector3f::ReadBig(in);
ResId backgroundModel = in.readUint32Big();
zeus::CVector3f backgroundScale = zeus::CVector3f::ReadBig(in);
bool upElevator = in.readBool();
s16 elevatorSound = (propCount < 12 ? s16(-1) : s16(in.readUint32Big()));
u8 volume = (propCount < 13 ? u8(127) : u8(in.readUint32Big()));
u8 panning = (propCount < 14 ? u8(64) : u8(in.readUint32Big()));
bool showText = (propCount < 15 ? false : in.readBool());
ResId fontId = (propCount < 16 ? kInvalidResId : in.readUint32Big());
ResId stringId = (propCount < 17 ? kInvalidResId : in.readUint32Big());
bool fadeWhite = (propCount < 18 ? false : in.readBool());
float charFadeInTime = (propCount < 19 ? 0.1f : in.readFloatBig());
float charsPerSecond = (propCount < 20 ? 16.f : in.readFloatBig());
float showDelay = (propCount < 21 ? 0.f : in.readFloatBig());
if (showText)
return new CScriptWorldTeleporter(mgr.AllocateUniqueId(), name, info, active, worldId, areaId, elevatorSound,
volume, panning, fontId, stringId, fadeWhite, charFadeInTime, charsPerSecond,
showDelay);
return new CScriptWorldTeleporter(mgr.AllocateUniqueId(), name, info, active, worldId, areaId,
animParms.GetACSFile(), animParms.GetCharacter(),
animParms.GetInitialAnimation(), playerScale, platformModel, platformScale,
backgroundModel, backgroundScale, upElevator, elevatorSound, volume, panning);
}
CEntity* ScriptLoader::LoadVisorGoo(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)
{
return nullptr;