diff --git a/Runtime/Character/CAnimData.hpp b/Runtime/Character/CAnimData.hpp index 99ae9290d..e6ccf1590 100644 --- a/Runtime/Character/CAnimData.hpp +++ b/Runtime/Character/CAnimData.hpp @@ -252,6 +252,7 @@ public: u32 GetPassedSoundPOICount() const { return x218_passedSoundCount; } s32 GetCharacterIndex() const { return x204_charIdx; } + u16 GetDefaultAnimation() const { return x208_defaultAnim; } }; } diff --git a/Runtime/MP1/CFrontEndUI.cpp b/Runtime/MP1/CFrontEndUI.cpp index d68e0e8a0..533fa6405 100644 --- a/Runtime/MP1/CFrontEndUI.cpp +++ b/Runtime/MP1/CFrontEndUI.cpp @@ -2006,7 +2006,7 @@ CFrontEndUI::CFrontEndUI() m->ResetGameState(); g_GameState->SetCurrentWorldId(g_ResFactory->TranslateOriginalToNew(g_DefaultWorldTag.id)); - g_GameState->CurrentWorldState().SetAreaId(0); + g_GameState->CurrentWorldState().SetAreaId(7); g_GameState->GameOptions().ResetToDefaults(); g_GameState->WriteBackupBuf(); diff --git a/Runtime/Particle/CElementGen.cpp b/Runtime/Particle/CElementGen.cpp index b0e828a42..b91f4b81e 100644 --- a/Runtime/Particle/CElementGen.cpp +++ b/Runtime/Particle/CElementGen.cpp @@ -7,6 +7,7 @@ #include "CParticleElectric.hpp" #include "Graphics/CModel.hpp" #include "Graphics/Shaders/CElementGenShaders.hpp" +#include "Character/CActorLights.hpp" #include "CWarp.hpp" #define MAX_GLOBAL_PARTICLES 2560 @@ -885,7 +886,7 @@ u32 CElementGen::GetSystemCount() return (ret + (x25c_activeParticleCount != 0)); } -void CElementGen::Render() +void CElementGen::Render(const CActorLights* actorLights) { CGenDescription* desc = x1c_genDesc.GetObj(); @@ -903,7 +904,7 @@ void CElementGen::Render() { SParticleModel& pmdl = desc->x5c_x48_PMDL; if (pmdl.m_found || desc->x45_24_x31_26_PMUS) - RenderModels(); + RenderModels(actorLights); if (x26c_31_LINE) RenderLines(); @@ -914,7 +915,7 @@ void CElementGen::Render() CParticleGlobals::g_currentParticleSystem = prevSystem; } -void CElementGen::RenderModels() +void CElementGen::RenderModels(const CActorLights* actorLights) { CGenDescription* desc = x1c_genDesc.GetObj(); @@ -1134,6 +1135,8 @@ void CElementGen::RenderModels() else { CModel* model = desc->x5c_x48_PMDL.m_token.GetObj(); + if (actorLights) + actorLights->ActivateLights(model->GetInstance()); if (g_subtractBlend) { model->Draw({5, 0, 1, zeus::CColor(1.f, 0.5f)}); diff --git a/Runtime/Particle/CElementGen.hpp b/Runtime/Particle/CElementGen.hpp index 28ca71bf1..a23291ba4 100644 --- a/Runtime/Particle/CElementGen.hpp +++ b/Runtime/Particle/CElementGen.hpp @@ -23,6 +23,7 @@ class IGenDescription; class CGenDescription; class CParticleSwoosh; class CParticleElectric; +class CActorLights; class CElementGen : public CParticleGen { @@ -203,13 +204,13 @@ public: void SetCEXTValue(int i, float v) { x9c_cextValues[i] = v; } bool InternalUpdate(double); - void RenderModels(); + void RenderModels(const CActorLights* actLights); void RenderLines(); void RenderParticles(); void RenderParticlesIndirectTexture(); bool Update(double); - void Render(); + void Render(const CActorLights* = nullptr); void SetOrientation(const zeus::CTransform&); void SetTranslation(const zeus::CVector3f&); void SetGlobalOrientation(const zeus::CTransform&); diff --git a/Runtime/Particle/CParticleElectric.cpp b/Runtime/Particle/CParticleElectric.cpp index d7a792d86..cceda30a1 100644 --- a/Runtime/Particle/CParticleElectric.cpp +++ b/Runtime/Particle/CParticleElectric.cpp @@ -625,7 +625,7 @@ bool CParticleElectric::Update(double dt) return ret; } -void CParticleElectric::Render() +void CParticleElectric::Render(const CActorLights*) { if (x3e8_electricManagers.size()) { diff --git a/Runtime/Particle/CParticleElectric.hpp b/Runtime/Particle/CParticleElectric.hpp index 13cf4d618..41307dfa3 100644 --- a/Runtime/Particle/CParticleElectric.hpp +++ b/Runtime/Particle/CParticleElectric.hpp @@ -107,7 +107,7 @@ public: CParticleElectric(const TToken& desc); bool Update(double); - void Render(); + void Render(const CActorLights* = nullptr); void SetOrientation(const zeus::CTransform&); void SetTranslation(const zeus::CVector3f&); void SetGlobalOrientation(const zeus::CTransform&); diff --git a/Runtime/Particle/CParticleGen.hpp b/Runtime/Particle/CParticleGen.hpp index 7b2f095c4..8cf270129 100644 --- a/Runtime/Particle/CParticleGen.hpp +++ b/Runtime/Particle/CParticleGen.hpp @@ -12,6 +12,7 @@ namespace urde { class CWarp; +class CActorLights; struct CParticle { @@ -33,7 +34,7 @@ public: virtual ~CParticleGen() = default; virtual bool Update(double)=0; - virtual void Render()=0; + virtual void Render(const CActorLights* = nullptr)=0; virtual void SetOrientation(const zeus::CTransform&)=0; virtual void SetTranslation(const zeus::CVector3f&)=0; virtual void SetGlobalOrientation(const zeus::CTransform&)=0; diff --git a/Runtime/Particle/CParticleSwoosh.cpp b/Runtime/Particle/CParticleSwoosh.cpp index 915d455ab..b1cb7dca5 100644 --- a/Runtime/Particle/CParticleSwoosh.cpp +++ b/Runtime/Particle/CParticleSwoosh.cpp @@ -978,7 +978,7 @@ void CParticleSwoosh::Render2SidedNoSplineNoGaps() CGraphics::DrawArray(drawStart, m_cachedVerts.size() - drawStart); } -void CParticleSwoosh::Render() +void CParticleSwoosh::Render(const CActorLights*) { if (x1b4_LENG < 2 || x1ac_particleCount <= 1) return; diff --git a/Runtime/Particle/CParticleSwoosh.hpp b/Runtime/Particle/CParticleSwoosh.hpp index 789abebc0..f727e8d00 100644 --- a/Runtime/Particle/CParticleSwoosh.hpp +++ b/Runtime/Particle/CParticleSwoosh.hpp @@ -134,7 +134,7 @@ public: CSwooshDescription* GetDesc() { return x1c_desc.GetObj(); } bool Update(double); - void Render(); + void Render(const CActorLights* = nullptr); void SetOrientation(const zeus::CTransform&); void SetTranslation(const zeus::CVector3f&); void SetGlobalOrientation(const zeus::CTransform&); diff --git a/Runtime/World/CScriptActorKeyframe.cpp b/Runtime/World/CScriptActorKeyframe.cpp index caf9c9d54..8eb593cbf 100644 --- a/Runtime/World/CScriptActorKeyframe.cpp +++ b/Runtime/World/CScriptActorKeyframe.cpp @@ -1,19 +1,26 @@ #include "CScriptActorKeyframe.hpp" +#include "CStateManager.hpp" +#include "World/CScriptActor.hpp" +#include "World/CScriptPlatform.hpp" +#include "World/CAi.hpp" #include "TCastTo.hpp" namespace urde { CScriptActorKeyframe::CScriptActorKeyframe(TUniqueId uid, std::string_view name, const CEntityInfo& info, s32 animId, - bool b1, float f1, bool b2, u32 w2, bool active, float totalPlayback) + bool looping, float lifetime, bool b2, u32 w2, bool active, float totalPlayback) : CEntity(uid, info, active, name) , x34_animationId(animId) -, x38_(f1) -, x3c_(totalPlayback) -, x40_(f1) +, x38_initialLifetime(lifetime) +, x3c_playbackRate(totalPlayback) +, x40_lifetime(lifetime) { - x44_24_ = b1; - x44_25_ = b2; + x44_24_looping = looping; + x44_25_disableUpdate = b2; x44_26_ = w2; + x44_27_ = w2; + x44_28_ = false; + x44_29_ = false; } void CScriptActorKeyframe::Accept(IVisitor& visitor) @@ -21,14 +28,113 @@ void CScriptActorKeyframe::Accept(IVisitor& visitor) visitor.Visit(this); } -void CScriptActorKeyframe::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) {} +void CScriptActorKeyframe::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) +{ + + if (msg == EScriptObjectMessage::Action) + { + if (GetActive()) + { + if (!x44_25_disableUpdate) + { + for (const SConnection& conn : x20_conns) + { + if (conn.x0_state != EScriptObjectState::Play || conn.x4_msg != EScriptObjectMessage::Play) + continue; + + auto search = mgr.GetIdListForScript(conn.x8_objId); + for (auto it = search.first; it != search.second; ++it) + UpdateEntity(it->second, mgr); + } + } + + x44_28_ = true; + SendScriptMsgs(EScriptObjectState::Play, mgr, EScriptObjectMessage::None); + } + } + else if (msg == EScriptObjectMessage::InitializedInArea) + { + if (x34_animationId == -1) + x34_animationId = 0; + } + + CEntity::AcceptScriptMsg(msg, uid, mgr); +} void CScriptActorKeyframe::Think(float dt, CStateManager& mgr) { - if (x44_25_) + if (!x44_25_disableUpdate || !x44_24_looping || !x44_27_ || !x44_28_ || x40_lifetime <= 0.f) { + CEntity::Think(dt, mgr); + return; } + + x40_lifetime -= dt; + if (x40_lifetime <= 0.f) + { + CEntity::Think(dt, mgr); + return; + } + + x44_28_ = false; + for (const SConnection& conn : x20_conns) + { + if (conn.x0_state != EScriptObjectState::Play || conn.x4_msg!= EScriptObjectMessage::Play) + continue; + CEntity* ent = mgr.ObjectById(mgr.GetIdForScript(conn.x8_objId)); + if (TCastToPtr act = ent) + { + if (act->HasModelData() && act->GetModelData()->HasAnimData()) + { + CAnimData* animData = act->ModelData()->AnimationData(); + if (animData->IsAdditiveAnimation(x34_animationId)) + animData->DelAdditiveAnimation(x34_animationId); + + if (animData->GetDefaultAnimation() == x34_animationId) + animData->EnableLooping(false); + } + } + else if (TCastToPtr ai = ent) + { + CAnimData* animData = act->ModelData()->AnimationData(); + if (animData->IsAdditiveAnimation(x34_animationId)) + animData->DelAdditiveAnimation(x34_animationId); + /* TODO: Finish */ + } + } + + CEntity::Think(dt, mgr); } -void CScriptActorKeyframe::UpdateEntity(TUniqueId, CStateManager&) {} +void CScriptActorKeyframe::UpdateEntity(TUniqueId uid, CStateManager& mgr) +{ + CEntity* ent = mgr.ObjectById(uid); + CActor* act = nullptr; + if (TCastToPtr tmp = ent) + act = tmp; + else if (TCastToPtr tmp = ent) + act = tmp; + + if (act) + { + if (!act->GetActive()) + mgr.SendScriptMsg(act, GetUniqueId(), EScriptObjectMessage::Activate); + act->SetDrawFlags({0, 0, 3, zeus::CColor::skWhite}); + if (act->HasModelData() && act->GetModelData()->HasAnimData()) + { + CAnimData* animData = act->ModelData()->AnimationData(); + if (animData->IsAdditiveAnimation(x34_animationId)) + { + animData->AddAdditiveAnimation(x34_animationId, 1.f, x44_24_looping, x44_26_); + } + else + { + animData->SetAnimation(CAnimPlaybackParms(x34_animationId, -1, 1.f, true), false); + act->ModelData()->EnableLooping(x44_24_looping); + animData->MultiplyPlaybackRate(x3c_playbackRate); + } + } + } + /* TODO: Finish */ +} } diff --git a/Runtime/World/CScriptActorKeyframe.hpp b/Runtime/World/CScriptActorKeyframe.hpp index b5c2992ee..a2742da5d 100644 --- a/Runtime/World/CScriptActorKeyframe.hpp +++ b/Runtime/World/CScriptActorKeyframe.hpp @@ -9,14 +9,14 @@ class CScriptActorKeyframe : public CEntity { private: s32 x34_animationId; - float x38_; - float x3c_; - float x40_; + float x38_initialLifetime; + float x3c_playbackRate; + float x40_lifetime; union { struct { - bool x44_24_ : 1; - bool x44_25_ : 1; + bool x44_24_looping : 1; + bool x44_25_disableUpdate : 1; bool x44_26_ : 1; bool x44_27_ : 1; bool x44_28_ : 1; diff --git a/Runtime/World/CScriptEffect.cpp b/Runtime/World/CScriptEffect.cpp index 4b338b797..66587ac30 100644 --- a/Runtime/World/CScriptEffect.cpp +++ b/Runtime/World/CScriptEffect.cpp @@ -275,12 +275,14 @@ void CScriptEffect::AddToRenderer(const zeus::CFrustum& frustum, const CStateMan void CScriptEffect::Render(const CStateManager& mgr) const { -// if (x138_actorLights) -// x138_actorLights->ActivateLights(); + /* The following code is kept for reference, this is now performed in CElementGen + if (x138_actorLights) + x138_actorLights->ActivateLights(); + */ if (x104_particleSystem && x104_particleSystem->GetParticleCountAll() > 0) { g_NumParticlesRendered += x104_particleSystem->GetParticleCountAll(); - x104_particleSystem->Render(); + x104_particleSystem->Render(GetActorLights()); } if (xf4_electric && xf4_electric->GetParticleCount() > 0) diff --git a/Runtime/World/ScriptLoader.cpp b/Runtime/World/ScriptLoader.cpp index 28b182cd8..b8e371cde 100644 --- a/Runtime/World/ScriptLoader.cpp +++ b/Runtime/World/ScriptLoader.cpp @@ -1181,17 +1181,17 @@ CEntity* ScriptLoader::LoadActorKeyframe(CStateManager& mgr, CInputStream& in, i return nullptr; std::string name = mgr.HashInstanceName(in); - s32 w1 = in.readInt32Big(); - bool b1 = in.readBool(); - float f1 = in.readFloatBig(); + s32 animId = in.readInt32Big(); + bool looping = in.readBool(); + float lifetime = in.readFloatBig(); bool active = in.readBool(); u32 w2 = in.readUint32Big(); - float f2 = in.readFloatBig(); + float totalPlayback = in.readFloatBig(); - if (w1 == -1) + if (animId == -1) return nullptr; - return new CScriptActorKeyframe(mgr.AllocateUniqueId(), name, info, w1, b1, f1, false, w2, active, f2); + return new CScriptActorKeyframe(mgr.AllocateUniqueId(), name, info, animId, looping, lifetime, false, w2, active, totalPlayback); } CEntity* ScriptLoader::LoadWater(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)