From 77af3f0ebd7ff1c928cc80dc6dcbd156c72c77e0 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Thu, 20 Jun 2019 20:02:56 -1000 Subject: [PATCH] CPuddleToadGamma and animation system fixes --- DataSpec/DNACommon/ANIM.cpp | 19 ++- DataSpec/DNACommon/ANIM.hpp | 9 +- DataSpec/DNAMP1/ANIM.cpp | 3 +- .../DNAMP1/ScriptObjects/PuddleToadGamma.hpp | 18 +- README.md | 6 +- Runtime/CStateManager.cpp | 2 +- Runtime/Graphics/CBooRenderer.cpp | 34 +++- Runtime/Graphics/CBooRenderer.hpp | 15 +- Runtime/Graphics/CModel.hpp | 1 + Runtime/Graphics/CModelBoo.cpp | 23 ++- .../Graphics/Shaders/CFluidPlaneShader.cpp | 18 +- .../Graphics/Shaders/CFluidPlaneShader.hpp | 7 +- Runtime/MP1/CMFGame.cpp | 3 + Runtime/MP1/World/CPuddleToadGamma.cpp | 158 ++++++++++-------- Runtime/MP1/World/CPuddleToadGamma.hpp | 36 ++-- Runtime/Weapon/CBomb.cpp | 8 +- Runtime/Weapon/CBomb.hpp | 6 +- Runtime/World/CActor.cpp | 3 - Runtime/World/CFluidPlaneCPU.cpp | 3 + Runtime/World/CFluidPlaneDoor.cpp | 4 + Runtime/World/CGameArea.cpp | 6 +- Runtime/World/CMorphBallShadow.cpp | 1 + Runtime/World/CPatterned.hpp | 2 +- Runtime/World/CPhysicsActor.cpp | 8 +- Runtime/World/CPlayer.cpp | 2 +- Runtime/World/CPlayer.hpp | 4 +- Runtime/World/CScriptDoor.cpp | 51 +++--- Runtime/World/CScriptDoor.hpp | 8 +- Runtime/World/CWorldShadow.cpp | 2 +- Runtime/World/ScriptLoader.cpp | 21 +-- Shaders/CModelShaders.frag.glsl | 2 +- Shaders/CModelShaders.frag.hlsl | 4 +- Shaders/CModelShaders.frag.metal | 18 +- hecl | 2 +- lldb-extras/.lldbinit | 5 + 35 files changed, 309 insertions(+), 203 deletions(-) diff --git a/DataSpec/DNACommon/ANIM.cpp b/DataSpec/DNACommon/ANIM.cpp index 4b6dc3139..3b99b7824 100644 --- a/DataSpec/DNACommon/ANIM.cpp +++ b/DataSpec/DNACommon/ANIM.cpp @@ -35,21 +35,21 @@ size_t ComputeBitstreamSize(size_t keyFrameCount, const std::vector& ch } static inline QuantizedRot QuantizeRotation(const Value& quat, atUint32 div) { - float q = M_PIF / 2.0f / float(div); + float q = float(div) / (M_PIF / 2.0f); zeus::simd_floats f(quat.simd); assert(std::abs(f[1]) <= 1.f && "Out of range quat X component"); assert(std::abs(f[2]) <= 1.f && "Out of range quat Y component"); assert(std::abs(f[3]) <= 1.f && "Out of range quat Z component"); return {{ - atInt32(std::asin(f[1]) / q), - atInt32(std::asin(f[2]) / q), - atInt32(std::asin(f[3]) / q), + atInt32(std::asin(f[1]) * q), + atInt32(std::asin(f[2]) * q), + atInt32(std::asin(f[3]) * q), }, (f[0] < 0.f)}; } static inline Value DequantizeRotation(const QuantizedRot& v, atUint32 div) { - float q = M_PIF / 2.0f / float(div); + float q = (M_PIF / 2.0f) / float(div); athena::simd_floats f = { 0.0f, std::sin(v.v[0] * q), @@ -259,6 +259,7 @@ void BitstreamWriter::quantize(atUint8* data, atUint8 q, atInt32 val) { atUint32 bitRem = m_bitCur % 32; atUint32 masked = val & ((1 << q) - 1); + assert(((((val >> 31) & 0x1) == 0x1) || (((masked >> (q - 1)) & 0x1) == 0)) && "Twos compliment fail"); /* Fill 32 bit buffer with region containing bits */ /* Make them least significant */ @@ -317,8 +318,8 @@ std::unique_ptr BitstreamWriter::write(const std::vector initVals; @@ -404,11 +405,11 @@ std::unique_ptr BitstreamWriter::write(const std::vector 0 && (delta >> (ret - 1))) + ++ret; assert(ret <= 24 && "Bad q value"); return ret; } diff --git a/DataSpec/DNAMP1/ANIM.cpp b/DataSpec/DNAMP1/ANIM.cpp index 95e9e7091..a67497cc5 100644 --- a/DataSpec/DNAMP1/ANIM.cpp +++ b/DataSpec/DNAMP1/ANIM.cpp @@ -618,7 +618,8 @@ ANIM::ANIM(const BlenderAction& act, const std::unordered_map name; - Value unknown1; + Value flavor; Value location; Value orientation; Value scale; PatternedInfo patternedInfo; ActorParameters actorParameters; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - DamageInfo damageInfo1; + Value suckForceMultiplier; + Value suckAngle; + Value playerSuckRange; + Value localShootDir; + Value playerShootSpeed; + Value shouldAttackWaitTime; + Value spotPlayerWaitTime; + DamageInfo playerShootDamage; DamageInfo damageInfo2; UniqueID32 dcln; diff --git a/README.md b/README.md index 0cf97eda6..ce5a35c43 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Everything else is much too experimental to make portable/stable release builds ### Platform Support * Windows 7+ (64-bit support only) -* macOS 10.9+ +* macOS 10.11+ * Linux * Arch is known to function with [`glx` vendor setup instructions](https://wiki.archlinux.org/index.php/Category:Graphics) *(main development/testing OS)* * **[WIP]** Vulkan loader detection is also integrated into the cmake for Linux @@ -16,12 +16,12 @@ Everything else is much too experimental to make portable/stable release builds * Much multimedia functionality is in place, but not fully tested ### Build Prerequisites: -* [CMake 3.10+](https://cmake.org) +* [CMake 3.13+](https://cmake.org) * [Python 3+](https://python.org) * LLVM development package *(headers and libs)* * [Specialized Windows Package](https://axiodl.com/LLVM-9.0.0svn-win64.exe) * [macOS Package](http://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz) -* **[Windows]** [Visual Studio 2017 and Windows SDK](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx) +* **[Windows]** [Visual Studio 2017/2019 and Windows SDK](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx) * **[macOS]** [Xcode Tools](https://developer.apple.com/xcode/download/) * **[Linux]** recent development packages of `udev`, `x11`, `xcb`, `xinput`, `glx`, `asound` diff --git a/Runtime/CStateManager.cpp b/Runtime/CStateManager.cpp index d4ee6751d..0cd3cc334 100644 --- a/Runtime/CStateManager.cpp +++ b/Runtime/CStateManager.cpp @@ -924,7 +924,7 @@ void CStateManager::DrawActorCubeFaces(CActor& actor, int& cubeInst) const { SetupFogForArea(area); g_Renderer->EnablePVS(pvsArr[i], area.x4_selfIdx); g_Renderer->SetWorldLightFadeLevel(area.GetPostConstructed()->x1128_worldLightingLevel); - g_Renderer->UpdateAreaUniforms(area.x4_selfIdx, false, true, cubeInst * 6 + f); + g_Renderer->UpdateAreaUniforms(area.x4_selfIdx, EWorldShadowMode::None, true, cubeInst * 6 + f); g_Renderer->DrawUnsortedGeometry(area.x4_selfIdx, 0x2, 0x0); } diff --git a/Runtime/Graphics/CBooRenderer.cpp b/Runtime/Graphics/CBooRenderer.cpp index b5d4a6c16..9af5319fe 100644 --- a/Runtime/Graphics/CBooRenderer.cpp +++ b/Runtime/Graphics/CBooRenderer.cpp @@ -555,7 +555,8 @@ void CBooRenderer::GenerateSphereRampTex(boo::IGraphicsDataFactory::Context& ctx } } x220_sphereRamp = ctx.newStaticTexture(SPHERE_RAMP_RES, SPHERE_RAMP_RES, 1, boo::TextureFormat::I8, - boo::TextureClampMode::Repeat, data[0], SPHERE_RAMP_RES * SPHERE_RAMP_RES); + boo::TextureClampMode::ClampToEdge, data[0], + SPHERE_RAMP_RES * SPHERE_RAMP_RES); } void CBooRenderer::GenerateScanLinesVBO(boo::IGraphicsDataFactory::Context& ctx) { @@ -617,8 +618,10 @@ void CBooRenderer::LoadThermoPalette() { void CBooRenderer::LoadBallFade() { m_ballFadeTex = xc_store.GetObj("TXTR_BallFade"); CTexture* ballFadeTexObj = m_ballFadeTex.GetObj(); - if (ballFadeTexObj) + if (ballFadeTexObj) { m_ballFade = ballFadeTexObj->GetBooTexture(); + m_ballFade->setClampMode(boo::TextureClampMode::ClampToEdge); + } } CBooRenderer::CBooRenderer(IObjectStore& store, IFactory& resFac) @@ -703,18 +706,25 @@ void CBooRenderer::EnablePVS(const CPVSVisSet& set, u32 areaIdx) { void CBooRenderer::DisablePVS() { xc8_pvs = std::nullopt; } -void CBooRenderer::UpdateAreaUniforms(int areaIdx, bool shadowRender, bool activateLights, int cubeFace) { +void CBooRenderer::UpdateAreaUniforms(int areaIdx, EWorldShadowMode shadowMode, bool activateLights, int cubeFace, + const CModelFlags* ballShadowFlags) { SetupRendererStates(); CModelFlags flags; int bufIdx; - if (shadowRender) { + if (shadowMode == EWorldShadowMode::WorldOnActorShadow) { flags.m_extendedShader = EExtendedShader::SolidColor; flags.x4_color = zeus::skBlack; bufIdx = 1; + } else if (shadowMode == EWorldShadowMode::BallOnWorldShadow) { + flags = *ballShadowFlags; + bufIdx = 2; + } else if (shadowMode == EWorldShadowMode::BallOnWorldIds) { + flags.m_extendedShader = EExtendedShader::SolidColor; + bufIdx = 3; } else { flags.m_extendedShader = EExtendedShader::Lighting; - bufIdx = cubeFace == -1 ? 0 : 2 + cubeFace; + bufIdx = cubeFace == -1 ? 0 : 4 + cubeFace; } for (CAreaListItem& item : x1c_areaListItems) { @@ -724,6 +734,9 @@ void CBooRenderer::UpdateAreaUniforms(int areaIdx, bool shadowRender, bool activ item.m_shaderSet->m_geomLayout->Update(flags, nullptr, nullptr, &item.m_shaderSet->m_matSet, item.m_shaderSet->m_geomLayout->GetSharedBuffer(bufIdx), nullptr); + if (shadowMode == EWorldShadowMode::BallOnWorldShadow || shadowMode == EWorldShadowMode::BallOnWorldIds) + continue; + for (auto it = item.x10_models.begin(); it != item.x10_models.end(); ++it) { CBooModel* model = *it; if (model->TryLockTextures()) { @@ -1239,9 +1252,9 @@ void CBooRenderer::FindOverlappingWorldModels(std::vector& modelBits, const } int CBooRenderer::DrawOverlappingWorldModelIDs(int alphaVal, const std::vector& modelBits, - const zeus::CAABox& aabb) const { + const zeus::CAABox& aabb) { SetupRendererStates(); - const_cast(*this).UpdateAreaUniforms(-1, false, false); + UpdateAreaUniforms(-1, EWorldShadowMode::BallOnWorldIds, false); CModelFlags flags; flags.m_extendedShader = EExtendedShader::SolidColor; // Do solid color draw @@ -1263,6 +1276,7 @@ int CBooRenderer::DrawOverlappingWorldModelIDs(int alphaVal, const std::vector(model).UpdateUniformData(flags, nullptr, nullptr, 3); const_cast(model).VerifyCurrentShader(0); for (const CBooSurface* surf = model.x38_firstUnsortedSurface; surf; surf = surf->m_next) if (surf->GetBounds().intersects(aabb)) @@ -1279,10 +1293,13 @@ int CBooRenderer::DrawOverlappingWorldModelIDs(int alphaVal, const std::vector& modelBits, - const zeus::CAABox& aabb, float alpha) const { + const zeus::CAABox& aabb, float alpha) { CModelFlags flags; flags.x4_color.a() = alpha; flags.m_extendedShader = EExtendedShader::MorphBallShadow; // Do shadow draw + flags.mbShadowBox = aabb; + + UpdateAreaUniforms(-1, EWorldShadowMode::BallOnWorldShadow, false, -1, &flags); u32 curWord = 0; for (const CAreaListItem& item : x1c_areaListItems) { @@ -1301,6 +1318,7 @@ void CBooRenderer::DrawOverlappingWorldModelShadows(int alphaVal, const std::vec flags.x4_color.r() = alphaVal / 255.f; const CBooModel& model = *item.x10_models[wordModel + j]; + const_cast(model).UpdateUniformData(flags, nullptr, nullptr, 2); const_cast(model).VerifyCurrentShader(0); for (const CBooSurface* surf = model.x38_firstUnsortedSurface; surf; surf = surf->m_next) if (surf->GetBounds().intersects(aabb)) diff --git a/Runtime/Graphics/CBooRenderer.hpp b/Runtime/Graphics/CBooRenderer.hpp index dd51d2bb3..cc6a37ba3 100644 --- a/Runtime/Graphics/CBooRenderer.hpp +++ b/Runtime/Graphics/CBooRenderer.hpp @@ -47,6 +47,14 @@ public: static void Init(); }; +enum class EWorldShadowMode { + None, + WorldOnActorShadow, + BallOnWorldShadow, + BallOnWorldIds, + MAX +}; + class CBooRenderer final : public IRenderer { friend class CBooModel; friend class CModel; @@ -201,7 +209,8 @@ public: const SShader* shaderSet); void EnablePVS(const CPVSVisSet&, u32); void DisablePVS(); - void UpdateAreaUniforms(int areaIdx, bool shadowRender = false, bool activateLights = true, int cubeFace = -1); + void UpdateAreaUniforms(int areaIdx, EWorldShadowMode shadowMode = EWorldShadowMode::None, + bool activateLights = true, int cubeFace = -1, const CModelFlags* ballShadowFlags = nullptr); void RemoveStaticGeometry(const std::vector*); void DrawAreaGeometry(int areaIdx, int mask, int targetMask); void DrawUnsortedGeometry(int areaIdx, int mask, int targetMask, bool shadowRender = false); @@ -293,9 +302,9 @@ public: } void FindOverlappingWorldModels(std::vector& modelBits, const zeus::CAABox& aabb) const; - int DrawOverlappingWorldModelIDs(int alphaVal, const std::vector& modelBits, const zeus::CAABox& aabb) const; + int DrawOverlappingWorldModelIDs(int alphaVal, const std::vector& modelBits, const zeus::CAABox& aabb); void DrawOverlappingWorldModelShadows(int alphaVal, const std::vector& modelBits, const zeus::CAABox& aabb, - float alpha) const; + float alpha); bool IsThermalVisorActive() const { return x318_29_thermalVisor; } bool IsThermalVisorHotPass() const { return m_thermalHotPass; } diff --git a/Runtime/Graphics/CModel.hpp b/Runtime/Graphics/CModel.hpp index b3b77803b..24295b4c7 100644 --- a/Runtime/Graphics/CModel.hpp +++ b/Runtime/Graphics/CModel.hpp @@ -164,6 +164,7 @@ private: boo::ObjToken GetBooVBO(const CBooModel& model, boo::IGraphicsDataFactory::Context& ctx); }; std::vector m_instances; + ModelInstance m_ballShadowInstance; boo::ObjToken m_staticVbo; boo::ObjToken m_staticIbo; diff --git a/Runtime/Graphics/CModelBoo.cpp b/Runtime/Graphics/CModelBoo.cpp index a24c8d692..54c1a4d6d 100644 --- a/Runtime/Graphics/CModelBoo.cpp +++ b/Runtime/Graphics/CModelBoo.cpp @@ -456,6 +456,19 @@ bool CBooModel::TryLockTextures() const { allLoad = false; } + if (allLoad) { + for (auto& pipeline : *m_pipelines) { + for (auto& subpipeline : *pipeline.second) { + if (!subpipeline->isReady()) { + allLoad = false; + break; + } + } + if (!allLoad) + break; + } + } + const_cast(this)->x40_24_texturesLoaded = allLoad; } @@ -730,8 +743,10 @@ void CBooModel::UVAnimationBuffer::PadOutBuffer(u8*& bufStart, u8*& bufOut) { bufOut = bufStart + ROUND_UP_256(bufOut - bufStart); } -static const zeus::CMatrix4f MBShadowPost0(1.f, 0.f, 0.f, 0.f, 0.f, -1.f, 0.f, 1.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, - 1.f); +static const zeus::CMatrix4f MBShadowPost0(1.f, 0.f, 0.f, 0.f, + 0.f, -1.f, 0.f, 1.f, + 0.f, 0.f, 0.f, 1.f, + 0.f, 0.f, 0.f, 1.f); static const zeus::CMatrix4f MBShadowPost1(0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 1.f, -0.0625f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 1.f); @@ -746,7 +761,7 @@ void CBooModel::UVAnimationBuffer::Update(u8*& bufOut, const MaterialSet* matSet if (flags.m_extendedShader == EExtendedShader::MorphBallShadow) { /* Special matrices for MorphBall shadow rendering */ zeus::CMatrix4f texMtx = (zeus::CTransform::Scale(1.f / (flags.mbShadowBox.max - flags.mbShadowBox.min)) * - zeus::CTransform::Translate(-flags.mbShadowBox.min) * CGraphics::g_GXModelView) + zeus::CTransform::Translate(-flags.mbShadowBox.min) * CGraphics::g_GXModelMatrix) .toMatrix4f(); for (const MaterialSet::Material& mat : matSet->materials) { (void)mat; @@ -1007,7 +1022,7 @@ boo::ObjToken CBooModel::UpdateUniformData(const CModelFl } else if (flags.m_extendedShader == EExtendedShader::MorphBallShadow) /* MorphBall shadow render */ { CModelShaders::MBShadowUniform& shadowOut = *reinterpret_cast(dataCur); - shadowOut.shadowUp = CGraphics::g_GXModelView * zeus::skUp; + shadowOut.shadowUp = CGraphics::g_GXModelView.rotate(zeus::skUp); shadowOut.shadowUp.w() = flags.x4_color.a(); shadowOut.shadowId = flags.x4_color.r(); } else if (flags.m_extendedShader == EExtendedShader::Disintegrate) { diff --git a/Runtime/Graphics/Shaders/CFluidPlaneShader.cpp b/Runtime/Graphics/Shaders/CFluidPlaneShader.cpp index 97154549f..e56c9e117 100644 --- a/Runtime/Graphics/Shaders/CFluidPlaneShader.cpp +++ b/Runtime/Graphics/Shaders/CFluidPlaneShader.cpp @@ -119,10 +119,10 @@ void CFluidPlaneShader::Cache::Clear() { p.reset(); } -void CFluidPlaneShader::PrepareBinding(const ShaderPair& pipeline, u32 maxVertCount) { +void CFluidPlaneShader::PrepareBinding(u32 maxVertCount) { CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(Vertex), maxVertCount); - if (pipeline.m_tessellation) + if (m_pipelines.m_tessellation) m_pvbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(PatchVertex), maxVertCount); m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); @@ -147,12 +147,12 @@ void CFluidPlaneShader::PrepareBinding(const ShaderPair& pipeline, u32 maxVertCo texs[texCount++] = m_envBumpMap->GetBooTexture(); if (m_lightmap) texs[texCount++] = m_lightmap->GetBooTexture(); - auto regular = ctx.newShaderDataBinding(pipeline.m_regular, m_vbo.get(), nullptr, nullptr, 3, ubufs, ubufStages, + auto regular = ctx.newShaderDataBinding(m_pipelines.m_regular, m_vbo.get(), nullptr, nullptr, 3, ubufs, ubufStages, ubufOffs, ubufSizes, texCount, texs, nullptr, nullptr); boo::ObjToken tessellation; - if (pipeline.m_tessellation) { + if (m_pipelines.m_tessellation) { texs[texCount++] = m_rippleMap.get(); - tessellation = ctx.newShaderDataBinding(pipeline.m_tessellation, m_pvbo.get(), nullptr, nullptr, 3, ubufs, + tessellation = ctx.newShaderDataBinding(m_pipelines.m_tessellation, m_pvbo.get(), nullptr, nullptr, 3, ubufs, ubufStages, ubufOffs, ubufSizes, texCount, texs, nullptr, nullptr); } m_dataBind = {regular, tessellation}; @@ -180,8 +180,8 @@ CFluidPlaneShader::CFluidPlaneShader(EFluidType type, const TLockedToken& patternTex1, @@ -190,8 +190,8 @@ CFluidPlaneShader::CFluidPlaneShader(const TLockedToken& patternTex1, : m_patternTex1(patternTex1), m_patternTex2(patternTex2), m_colorTex(colorTex) { SFluidPlaneDoorShaderInfo shaderInfo(m_patternTex1.operator bool(), m_patternTex2.operator bool(), m_colorTex.operator bool()); - ShaderPair pipeline = _cache.GetOrBuildShader(shaderInfo); - PrepareBinding(pipeline, maxVertCount); + m_pipelines = _cache.GetOrBuildShader(shaderInfo); + PrepareBinding(maxVertCount); } void CFluidPlaneShader::prepareDraw(const RenderSetupInfo& info) { diff --git a/Runtime/Graphics/Shaders/CFluidPlaneShader.hpp b/Runtime/Graphics/Shaders/CFluidPlaneShader.hpp index 720f37398..d0d00b424 100644 --- a/Runtime/Graphics/Shaders/CFluidPlaneShader.hpp +++ b/Runtime/Graphics/Shaders/CFluidPlaneShader.hpp @@ -102,6 +102,7 @@ private: boo::ObjToken m_vbo; boo::ObjToken m_pvbo; boo::ObjToken m_uniBuf; + ShaderPair m_pipelines; BindingPair m_dataBind; int m_lastBind = -1; @@ -129,7 +130,7 @@ private: template static void _Shutdown(); - void PrepareBinding(const ShaderPair& pipeline, u32 maxVertCount); + void PrepareBinding(u32 maxVertCount); public: CFluidPlaneShader(EFluidType type, const TLockedToken& patternTex1, @@ -158,6 +159,10 @@ public: } void doneDrawing() { m_lastBind = -1; } void loadVerts(const std::vector& verts, const std::vector& pVerts); + bool isReady() const { + return m_pipelines.m_regular->isReady() && + (!m_pipelines.m_tessellation || m_pipelines.m_tessellation->isReady()); + } static void Shutdown(); }; diff --git a/Runtime/MP1/CMFGame.cpp b/Runtime/MP1/CMFGame.cpp index 469cc142a..ac64a4784 100644 --- a/Runtime/MP1/CMFGame.cpp +++ b/Runtime/MP1/CMFGame.cpp @@ -339,6 +339,9 @@ CIOWin::EMessageReturn CMFGameLoader::OnMessage(const CArchitectureMessage& msg, x1c_loadList.clear(); + if (!CGraphics::g_BooFactory->areShadersReady()) + return EMessageReturn::Exit; + wtMgr->StartTextFadeOut(); x2c_25_transitionFinished = wtMgr->IsTransitionFinished(); return EMessageReturn::Exit; diff --git a/Runtime/MP1/World/CPuddleToadGamma.cpp b/Runtime/MP1/World/CPuddleToadGamma.cpp index 831db878a..9ffc37bf8 100644 --- a/Runtime/MP1/World/CPuddleToadGamma.cpp +++ b/Runtime/MP1/World/CPuddleToadGamma.cpp @@ -4,6 +4,7 @@ #include "CStateManager.hpp" #include "World/CPlayer.hpp" #include "Collision/CGameCollision.hpp" +#include "Weapon/CBomb.hpp" #include "TCastTo.hpp" namespace urde::MP1 { @@ -12,23 +13,24 @@ const zeus::CVector3f CPuddleToadGamma::skBellyOffset(0.f, 0.1f, -.3f); CPuddleToadGamma::CPuddleToadGamma(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, - const CActorParameters& aParms, float f1, float f2, float f3, - const zeus::CVector3f& v1, float f4, float f5, float f6, const CDamageInfo& dInfo1, - const CDamageInfo& dInfo2, CAssetId dcln) + const CActorParameters& aParms, float suckForceMultiplier, float suckAngle, + float playerSuckRange, const zeus::CVector3f& localShootDir, float playerShootSpeed, + float shouldAttackWaitTime, float spotPlayerWaitTime, + const CDamageInfo& playerShootDamage, const CDamageInfo& dInfo2, CAssetId dcln) : CPatterned(ECharacter::PuddleToad, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer, EColliderType::Zero, EBodyType::Restricted, aParms, EKnockBackVariant::Large) -, x570_(dInfo1) +, x570_playerShootDamage(playerShootDamage) , x58c_(dInfo2) -, x5a8_(f1) -, x5ac_(std::cos(zeus::degToRad(f2 * 0.5f))) -, x5b0_(f3) -, x5b4_(v1) -, x5c0_(f4) -, x5c4_(f5) -, x5c8_(f6) -, x5e8_24_(false) -, x5e8_25_(false) -, x5e8_26_(false) { +, x5a8_suckForceMultiplier(suckForceMultiplier) +, x5ac_minSuckAngleProj(std::cos(zeus::degToRad(suckAngle * 0.5f))) +, x5b0_playerSuckRange(playerSuckRange) +, x5b4_localShootDir(localShootDir) +, x5c0_playerShootSpeed(playerShootSpeed) +, x5c4_shouldAttackWaitTime(shouldAttackWaitTime) +, x5c8_spotPlayerWaitTime(spotPlayerWaitTime) +, x5e8_24_playerInside(false) +, x5e8_25_waitTimerActive(false) +, x5e8_26_shotPlayer(false) { x401_26_disableMove = true; x460_knockBackController.SetEnableBurn(false); x460_knockBackController.SetEnableLaggedBurnDeath(false); @@ -70,7 +72,7 @@ void CPuddleToadGamma::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, x450_bodyController->Activate(mgr); zeus::CTransform bellyXf = GetLctrTransform(mBellyLocatorName); zeus::CVector3f bellyOffset = GetTransform().rotate(skBellyOffset); - x5d8_ = x5cc_ = bellyXf.origin + bellyOffset; + x5d8_damageablePoint = x5cc_suckPoint = bellyXf.origin + bellyOffset; RemoveMaterial(EMaterialTypes::Target, EMaterialTypes::Orbit, mgr); AddMaterial(EMaterialTypes::Immovable, mgr); AddMaterial(EMaterialTypes::SolidCharacter); @@ -79,8 +81,8 @@ void CPuddleToadGamma::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, void CPuddleToadGamma::Think(float dt, CStateManager& mgr) { CPatterned::Think(dt, mgr); - if (x5e8_25_) - x56c_ += dt; + if (x5e8_25_waitTimerActive) + x56c_waitTimer += dt; } std::optional CPuddleToadGamma::GetTouchBounds() const { @@ -91,14 +93,14 @@ std::optional CPuddleToadGamma::GetTouchBounds() const { } void CPuddleToadGamma::CenterPlayer(CStateManager& mgr, const zeus::CVector3f& pos, float dt) { - zeus::CVector3f dir = (mgr.GetPlayer().GetTranslation() - pos).normalized(); + zeus::CVector3f dir = (pos - mgr.GetPlayer().GetTranslation()).normalized(); mgr.GetPlayer().SetVelocityWR((1.f / (2.f * dt)) * dir); } const CDamageVulnerability* CPuddleToadGamma::GetDamageVulnerability(const zeus::CVector3f& pos, const zeus::CVector3f& dir, const CDamageInfo& dInfo) const { - if (x5e8_24_ && (x5d8_ - pos).magSquared() < 4.f) + if (x5e8_24_playerInside && (x5d8_damageablePoint - pos).magSquared() < 4.f) return CAi::GetDamageVulnerability(); return &CDamageVulnerability::ImmuneVulnerabilty(); @@ -106,16 +108,16 @@ const CDamageVulnerability* CPuddleToadGamma::GetDamageVulnerability(const zeus: void CPuddleToadGamma::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) { if (type == EUserEventType::Projectile) { - ShootPlayer(mgr, x5c0_); + ShootPlayer(mgr, x5c0_playerShootSpeed); return; } CPatterned::DoUserAnimEvent(mgr, node, type, dt); } -bool CPuddleToadGamma::SpotPlayer(CStateManager&, float arg) { return x56c_ >= x5c8_; } +bool CPuddleToadGamma::SpotPlayer(CStateManager&, float arg) { return x56c_waitTimer >= x5c8_spotPlayerWaitTime; } -bool CPuddleToadGamma::ShouldAttack(CStateManager&, float) { return x56c_ >= x5c4_; } +bool CPuddleToadGamma::ShouldAttack(CStateManager&, float) { return x56c_waitTimer >= x5c4_shouldAttackWaitTime; } bool CPuddleToadGamma::LostInterest(CStateManager& mgr, float) { zeus::CAABox box = *GetTouchBounds(); @@ -123,7 +125,28 @@ bool CPuddleToadGamma::LostInterest(CStateManager& mgr, float) { return !box.intersects(plBox); } -void CPuddleToadGamma::ShootPlayer(CStateManager&, float) {} +void CPuddleToadGamma::ShootPlayer(CStateManager& mgr, float speed) { + zeus::CVector3f shootDir = x34_transform.rotate(x5b4_localShootDir.normalized()); + mgr.GetPlayer().SetLeaveMorphBallAllowed(true); + if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) { + x5e8_26_shotPlayer = true; + mgr.GetPlayer().Stop(); + mgr.GetPlayer().SetVelocityWR(zeus::skZero3f); + mgr.GetPlayer().ApplyImpulseWR(mgr.GetPlayer().GetMass() * shootDir * speed, {}); + mgr.GetPlayer().SetMoveState(CPlayer::EPlayerMovementState::ApplyJump, mgr); + mgr.ApplyDamage(GetUniqueId(), mgr.GetPlayer().GetUniqueId(), GetUniqueId(), x570_playerShootDamage, + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), zeus::skZero3f); + mgr.GetPlayer().GetMorphBall()->SetAsProjectile(); + rstl::reserved_vector nearList; + mgr.BuildNearList(nearList, GetBoundingBox(), CMaterialFilter::MakeInclude({EMaterialTypes::Bomb}), this); + for (TUniqueId id : nearList) { + if (TCastToPtr bomb = mgr.ObjectById(id)) { + bomb->SetVelocityWR((mgr.GetActiveRandom()->Float() * 5.f + 20.f) * shootDir); + bomb->SetConstantAccelerationWR({0.f, 0.f, -24.525f}); + } + } + } +} bool CPuddleToadGamma::InAttackPosition(CStateManager& mgr, float) { return mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed && @@ -140,27 +163,28 @@ bool CPuddleToadGamma::PlayerInVortexArea(const CStateManager& mgr) { zeus::CVector3f playerOffset = player.GetTranslation() + zeus::CVector3f{0.f, 0.f, player.GetMorphBall()->GetBallRadius()}; - zeus::CVector3f rotatedOffset = GetTransform().rotate(zeus::skForward); + zeus::CVector3f rotatedDir = GetTransform().rotate(zeus::skForward); - zeus::CVector3f vec1 = (playerOffset - (xf.origin - (1.f * rotatedOffset))); - float f31 = vec1.normalized().dot(rotatedOffset); - float f28 = vec1.magnitude(); - float f26 = (player.GetTranslation() - (xf.origin - (4.f * rotatedOffset))).normalized().dot(rotatedOffset); - if (f28 > 2.f) { + zeus::CVector3f suckPointToPlayer = (playerOffset - (xf.origin - (1.f * rotatedDir))); + float suckProj = suckPointToPlayer.normalized().dot(rotatedDir); + float playerDist = suckPointToPlayer.magnitude(); + float suckAngleProj = (player.GetTranslation() - (xf.origin - (4.f * rotatedDir))).normalized().dot(rotatedDir); + if (playerDist > 2.f) { CRayCastResult result = - mgr.RayStaticIntersection(vec1, 1.f / f28 * vec1, f28 - player.GetMorphBall()->GetBallRadius(), kSolidFilter); + mgr.RayStaticIntersection(suckPointToPlayer, 1.f / playerDist * suckPointToPlayer, + playerDist - player.GetMorphBall()->GetBallRadius(), kSolidFilter); if (result.IsValid()) return false; } - return (f28 < x5b0_ && f31 > 0.f && f26 > x5ac_); + return (playerDist < x5b0_playerSuckRange && suckProj > 0.f && suckAngleProj > x5ac_minSuckAngleProj); } void CPuddleToadGamma::InActive(CStateManager& mgr, EStateMsg msg, float) { if (msg == EStateMsg::Activate) { x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); SetSolid(mgr, true); - mgr.GetPlayer().Set_X590(true); + mgr.GetPlayer().SetLeaveMorphBallAllowed(true); x330_stateMachineState.SetDelay(2.f); } } @@ -169,31 +193,30 @@ void CPuddleToadGamma::Active(CStateManager& mgr, EStateMsg msg, float) { if (msg == EStateMsg::Activate) { x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); zeus::CTransform xf = GetLctrTransform(mBellyLocatorName); - x5cc_ = xf.origin + GetTransform().rotate(skBellyOffset); - x56c_ = 0.f; - x5e8_25_ = true; + x5cc_suckPoint = xf.origin + GetTransform().rotate(skBellyOffset); + x56c_waitTimer = 0.f; + x5e8_25_waitTimerActive = true; SetSolid(mgr, true); - mgr.GetPlayer().Set_X590(true); + mgr.GetPlayer().SetLeaveMorphBallAllowed(true); } else if (msg == EStateMsg::Deactivate) { - x5e8_25_ = false; + x5e8_25_waitTimerActive = false; } } void CPuddleToadGamma::Suck(CStateManager& mgr, EStateMsg msg, float arg) { - return; if (msg == EStateMsg::Activate) { SetSolid(mgr, false); - mgr.GetPlayer().Set_X590(false); + mgr.GetPlayer().SetLeaveMorphBallAllowed(false); mgr.GetPlayer().GetMorphBall()->DisableHalfPipeStatus(); } else if (msg == EStateMsg::Update) { - if (x568_ == 0) { + if (x568_stateProg == 0) { if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::LoopReaction) { - x568_ = 1; + x568_stateProg = 1; return; } x450_bodyController->GetCommandMgr().DeliverCmd(CBCLoopReactionCmd(pas::EReactionType::Zero)); - } else if (x568_ == 1) + } else if (x568_stateProg == 1) SuckPlayer(mgr, arg); } else if (msg == EStateMsg::Deactivate) { x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::ExitState)); @@ -205,38 +228,38 @@ void CPuddleToadGamma::SuckPlayer(CStateManager& mgr, float arg) { if (player.GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) return; - zeus::CVector3f posDiff = player.GetTranslation() - x5cc_; - if (posDiff.magnitude() < 3.f) { + zeus::CVector3f posDiff = player.GetTranslation() - x5cc_suckPoint; + float posMag = posDiff.magnitude(); + if (posMag < 3.f) { player.Stop(); - CenterPlayer(mgr, x5cc_, arg); + CenterPlayer(mgr, x5cc_suckPoint, arg); return; } - float d = x5a8_ * (x5b0_ / (posDiff.magnitude() * posDiff.magnitude())); - zeus::CVector3f force = d * (player.GetMass() * -posDiff); + float forceMag = x5a8_suckForceMultiplier * (x5b0_playerSuckRange / (posMag * posMag)); + zeus::CVector3f force = forceMag * (player.GetMass() * -posDiff); player.ApplyForceWR(force, zeus::CAxisAngle()); } void CPuddleToadGamma::Attack(CStateManager& mgr, EStateMsg msg, float) { - return; if (msg == EStateMsg::Activate) { mgr.GetPlayer().Stop(); mgr.GetPlayer().SetVelocityWR({}); x450_bodyController->GetCommandMgr().DeliverCmd(CBCMeleeAttackCmd(pas::ESeverity::One)); - x5e8_26_ = false; + x5e8_26_shotPlayer = false; mgr.GetPlayer().GetMorphBall()->SetBombJumpState(CMorphBall::EBombJumpState::BombJumpDisabled); } else if (msg == EStateMsg::Update) { - if (!x5e8_26_) { + if (!x5e8_26_shotPlayer) { zeus::CTransform xf = GetLctrTransform(mBellyLocatorName); - x5cc_ = xf.origin + GetTransform().rotate(skBellyOffset); - SetPlayerPosition(mgr, x5cc_); + x5cc_suckPoint = xf.origin + GetTransform().rotate(skBellyOffset); + SetPlayerPosition(mgr, x5cc_suckPoint); } else if (LostInterest(mgr, 0.f)) SetSolid(mgr, true); } else if (msg == EStateMsg::Deactivate) { SetSolid(mgr, true); - mgr.GetPlayer().Set_X590(true); + mgr.GetPlayer().SetLeaveMorphBallAllowed(true); mgr.GetPlayer().GetMorphBall()->SetBombJumpState(CMorphBall::EBombJumpState::BombJumpAvailable); - x5e8_24_ = false; + x5e8_24_playerInside = false; } } @@ -272,42 +295,41 @@ bool CPuddleToadGamma::Inside(CStateManager& mgr, float) { if (mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) return false; - zeus::CVector3f posDiff = mgr.GetPlayer().GetTranslation() - x5cc_; + zeus::CVector3f posDiff = mgr.GetPlayer().GetTranslation() - x5cc_suckPoint; return posDiff.dot(GetTransform().frontVector()) <= 0.f && posDiff.magSquared() < 2.f; } void CPuddleToadGamma::Crouch(CStateManager& mgr, EStateMsg msg, float) { - return; if (msg == EStateMsg::Activate) { - x568_ = 0; - x56c_ = 0.f; - x5e8_25_ = true; - x5e8_24_ = true; + x568_stateProg = 0; + x56c_waitTimer = 0.f; + x5e8_25_waitTimerActive = true; + x5e8_24_playerInside = true; mgr.GetPlayer().Stop(); mgr.GetPlayer().SetVelocityWR({}); SendScriptMsgs(EScriptObjectState::Inside, mgr, EScriptObjectMessage::None); if (!mgr.GetPlayer().AttachActorToPlayer(GetUniqueId(), false)) - x56c_ = 100.f; + x56c_waitTimer = 100.f; SetSolid(mgr, false); - mgr.GetPlayer().Set_X590(false); + mgr.GetPlayer().SetLeaveMorphBallAllowed(false); mgr.GetPlayer().GetMorphBall()->DisableHalfPipeStatus(); SetSolid(mgr, false); } else if (msg == EStateMsg::Update) { zeus::CTransform xf = GetLctrTransform(mBellyLocatorName); - x5cc_ = xf.origin + GetTransform().rotate(skBellyOffset); - SetPlayerPosition(mgr, x5cc_); - if (x568_ == 0) { + x5cc_suckPoint = xf.origin + GetTransform().rotate(skBellyOffset); + SetPlayerPosition(mgr, x5cc_suckPoint); + if (x568_stateProg == 0) { if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Locomotion) - x568_ = 1; + x568_stateProg = 1; else x450_bodyController->SetLocomotionType(pas::ELocomotionType::Crouch); } } else if (msg == EStateMsg::Deactivate) { if (mgr.GetPlayer().GetAttachedActor() == GetUniqueId()) mgr.GetPlayer().DetachActorFromPlayer(); - mgr.GetPlayer().Set_X590(true); - x5e8_25_ = false; + mgr.GetPlayer().SetLeaveMorphBallAllowed(true); + x5e8_25_waitTimerActive = false; } } diff --git a/Runtime/MP1/World/CPuddleToadGamma.hpp b/Runtime/MP1/World/CPuddleToadGamma.hpp index a66022b80..d12e1846c 100644 --- a/Runtime/MP1/World/CPuddleToadGamma.hpp +++ b/Runtime/MP1/World/CPuddleToadGamma.hpp @@ -9,23 +9,23 @@ class CPuddleToadGamma final : public CPatterned { static constexpr std::string_view mMouthLocatorName = "MOUTH_LCTR_SDK"sv; static constexpr std::string_view mBellyLocatorName = "SAMUS_POS_LCTR_SDK"sv; static const zeus::CVector3f skBellyOffset; - u32 x568_ = 0; - float x56c_ = 0.f; - CDamageInfo x570_; + u32 x568_stateProg = 0; + float x56c_waitTimer = 0.f; + CDamageInfo x570_playerShootDamage; CDamageInfo x58c_; - float x5a8_; - float x5ac_; - float x5b0_; - zeus::CVector3f x5b4_; - float x5c0_; - float x5c4_; - float x5c8_; - zeus::CVector3f x5cc_; - zeus::CVector3f x5d8_; + float x5a8_suckForceMultiplier; + float x5ac_minSuckAngleProj; + float x5b0_playerSuckRange; + zeus::CVector3f x5b4_localShootDir; + float x5c0_playerShootSpeed; + float x5c4_shouldAttackWaitTime; + float x5c8_spotPlayerWaitTime; + zeus::CVector3f x5cc_suckPoint; + zeus::CVector3f x5d8_damageablePoint; std::unique_ptr x5e4_collisionTreePrim; - bool x5e8_24_ : 1; - bool x5e8_25_ : 1; - bool x5e8_26_ : 1; + bool x5e8_24_playerInside : 1; + bool x5e8_25_waitTimerActive : 1; + bool x5e8_26_shotPlayer : 1; void SetSolid(CStateManager&, bool); @@ -40,8 +40,10 @@ public: CPuddleToadGamma(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, - const CActorParameters& aParms, float f1, float f2, float f3, const zeus::CVector3f& v1, float f4, - float f5, float f6, const CDamageInfo& dInfo1, const CDamageInfo& dInfo2, CAssetId dcln); + const CActorParameters& aParms, float suckForceMultiplier, float suckAngle, float playerSuckRange, + const zeus::CVector3f& localShootDir, float playerShootSpeed, float shouldAttackWaitTime, + float spotPlayerWaitTime, const CDamageInfo& playerShootDamage, const CDamageInfo& dInfo2, + CAssetId dcln); void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); void Think(float dt, CStateManager& mgr); diff --git a/Runtime/Weapon/CBomb.cpp b/Runtime/Weapon/CBomb.cpp index fe604a3d4..603b778ef 100644 --- a/Runtime/Weapon/CBomb.cpp +++ b/Runtime/Weapon/CBomb.cpp @@ -87,12 +87,12 @@ void CBomb::Think(float dt, urde::CStateManager& mgr) { if (x190_24_isNotDetonated) { - if (x164_.magSquared() > 0.f) - x158_ += dt * x164_; + if (x164_acceleration.magSquared() > 0.f) + x158_velocity += dt * x164_acceleration; - if (x158_.magSquared() > 0.f) { + if (x158_velocity.magSquared() > 0.f) { x170_prevLocation = GetTranslation(); - CActor::SetTranslation((dt * x158_) + GetTranslation()); + CActor::SetTranslation((dt * x158_velocity) + GetTranslation()); zeus::CVector3f diffVec = (GetTranslation() - x170_prevLocation); float diffMag = diffVec.magnitude(); diff --git a/Runtime/Weapon/CBomb.hpp b/Runtime/Weapon/CBomb.hpp index 295e6b6f9..cb0fb9f61 100644 --- a/Runtime/Weapon/CBomb.hpp +++ b/Runtime/Weapon/CBomb.hpp @@ -8,8 +8,8 @@ namespace urde { class CElementGen; class CBomb : public CWeapon { - zeus::CVector3f x158_; - zeus::CVector3f x164_; + zeus::CVector3f x158_velocity; + zeus::CVector3f x164_acceleration; zeus::CVector3f x170_prevLocation; float x17c_fuseTime; std::unique_ptr x180_particle1; @@ -33,6 +33,8 @@ public: void Explode(const zeus::CVector3f&, CStateManager&); void UpdateLight(float, CStateManager&); std::optional GetTouchBounds() const; + void SetVelocityWR(const zeus::CVector3f& vel) { x158_velocity = vel; } + void SetConstantAccelerationWR(const zeus::CVector3f& acc) { x164_acceleration = acc; } }; } // namespace urde diff --git a/Runtime/World/CActor.cpp b/Runtime/World/CActor.cpp index ef64ef409..8330a3245 100644 --- a/Runtime/World/CActor.cpp +++ b/Runtime/World/CActor.cpp @@ -14,7 +14,6 @@ #include "CTimeProvider.hpp" #include "Graphics/CSkinnedModel.hpp" #include "hecl/CVarManager.hpp" -#include "zeus/CEulerAngles.hpp" namespace urde { static CMaterialList MakeActorMaterialList(const CMaterialList& materialList, const CActorParameters& params) { @@ -494,8 +493,6 @@ void CActor::SetTransform(const zeus::CTransform& tr) { xe4_27_notInSortedLists = true; xe4_28_transformDirty = true; xe4_29_actorLightsDirty = true; - //if (TCastToPtr(this)) - // printf("ACC %f\n", zeus::radToDeg(zeus::CEulerAngles(tr).z())); } void CActor::SetAddedToken(u32 tok) { xcc_addedToken = tok; } diff --git a/Runtime/World/CFluidPlaneCPU.cpp b/Runtime/World/CFluidPlaneCPU.cpp index c5a2f361a..909ffc87a 100644 --- a/Runtime/World/CFluidPlaneCPU.cpp +++ b/Runtime/World/CFluidPlaneCPU.cpp @@ -742,6 +742,9 @@ void CFluidPlaneCPU::Render(const CStateManager& mgr, float alpha, const zeus::C TCastToConstPtr water = mgr.GetObjectById(waterId); CFluidPlaneShader::RenderSetupInfo setupInfo = RenderSetup(mgr, alpha, xf, areaXf, aabb, water.GetPtr()); + if (!m_shader->isReady()) + return; + CFluidPlaneRender::NormalMode normalMode; if (xb0_bumpMap && kEnableWaterBumpMaps) normalMode = CFluidPlaneRender::NormalMode::NBT; diff --git a/Runtime/World/CFluidPlaneDoor.cpp b/Runtime/World/CFluidPlaneDoor.cpp index 4c886167f..29b28c04d 100644 --- a/Runtime/World/CFluidPlaneDoor.cpp +++ b/Runtime/World/CFluidPlaneDoor.cpp @@ -63,6 +63,10 @@ void CFluidPlaneDoor::Render(const CStateManager& mgr, float alpha, const zeus:: const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const { CFluidPlaneShader::RenderSetupInfo setupInfo = RenderSetup(mgr, alpha, xf, aabb, noNormals); + + if (!m_shader->isReady()) + return; + CFluidPlaneRender::numSubdivisionsInTile = xa4_tileSubdivisions; CFluidPlaneRender::numTilesInHField = 42 / xa4_tileSubdivisions; CFluidPlaneRender::numSubdivisionsInHField = CFluidPlaneRender::numTilesInHField * xa4_tileSubdivisions; diff --git a/Runtime/World/CGameArea.cpp b/Runtime/World/CGameArea.cpp index 46284c2dd..1ef25d3c4 100644 --- a/Runtime/World/CGameArea.cpp +++ b/Runtime/World/CGameArea.cpp @@ -996,6 +996,10 @@ void CGameArea::PostConstructArea() { x12c_postConstructed->x10c0_areaObjs.reset(new CAreaObjectList(x4_selfIdx)); x12c_postConstructed->x10c4_areaFog.reset(new CAreaFog()); + /* URDE addition: preemptively fill in area models so shaders may be polled for completion */ + if (!x12c_postConstructed->x1108_25_modelsConstructed) + FillInStaticGeometry(); + xf0_24_postConstructed = true; /* Resolve layer pointers */ @@ -1036,7 +1040,7 @@ void CGameArea::FillInStaticGeometry(bool textures) { CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { /* Reserve extra buffers for 16 cubemaps and shadow rendering */ - matSet.m_geomLayout->ReserveSharedBuffers(ctx, 98); + matSet.m_geomLayout->ReserveSharedBuffers(ctx, 96 + int(EWorldShadowMode::MAX)); /* Models */ for (CMetroidModelInstance& inst : x12c_postConstructed->x4c_insts) { diff --git a/Runtime/World/CMorphBallShadow.cpp b/Runtime/World/CMorphBallShadow.cpp index 813a72060..4fd947330 100644 --- a/Runtime/World/CMorphBallShadow.cpp +++ b/Runtime/World/CMorphBallShadow.cpp @@ -118,6 +118,7 @@ void CMorphBallShadow::Render(const CStateManager& mgr, float alpha) { CModelFlags flags; flags.x4_color.a() = alpha; flags.m_extendedShader = EExtendedShader::MorphBallShadow; + flags.mbShadowBox = xb8_shadowVolume; int alphaVal = 4; for (const CActor* actor : x0_actors) { diff --git a/Runtime/World/CPatterned.hpp b/Runtime/World/CPatterned.hpp index e2c4bbeec..ff8a8f076 100644 --- a/Runtime/World/CPatterned.hpp +++ b/Runtime/World/CPatterned.hpp @@ -258,7 +258,7 @@ public: void Accept(IVisitor&); void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void PreThink(float, CStateManager& mgr) { CEntity::Think(x500_preThinkDt, mgr); } + void PreThink(float dt, CStateManager& mgr) { x500_preThinkDt = dt; CEntity::Think(x500_preThinkDt, mgr); } void Think(float, CStateManager&); void PreRender(CStateManager&, const zeus::CFrustum&); void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; diff --git a/Runtime/World/CPhysicsActor.cpp b/Runtime/World/CPhysicsActor.cpp index 25abcc222..4f3881b7e 100644 --- a/Runtime/World/CPhysicsActor.cpp +++ b/Runtime/World/CPhysicsActor.cpp @@ -1,7 +1,5 @@ #include "CPhysicsActor.hpp" #include "TCastTo.hpp" -#include "MP1/World/CActorContraption.hpp" -#include "zeus/CEulerAngles.hpp" namespace urde { @@ -93,10 +91,8 @@ void CPhysicsActor::AddMotionState(const CMotionState& mst) { zeus::CNUQuaternion q{x34_transform.buildMatrix3f()}; q += mst.xc_orientation; zeus::CQuaternion quat = zeus::CQuaternion::fromNUQuaternion(q); - //if (TCastToPtr(this)) { - // float a1 = zeus::radToDeg(zeus::CEulerAngles(zeus::CQuaternion(x34_transform.buildMatrix3f())).z()); - // float a2 = zeus::radToDeg(zeus::CEulerAngles(quat).z()); - // printf("ADD %f\n", a2 - a1); + //if (TCastToPtr(this)) { + // printf("ADD %f %f %f\n", float(mst.x0_translation.x()), float(mst.x0_translation.y()), float(mst.x0_translation.z())); //} SetTransform(zeus::CTransform(quat, x34_transform.origin)); diff --git a/Runtime/World/CPlayer.cpp b/Runtime/World/CPlayer.cpp index 25dcc371d..9797418c7 100644 --- a/Runtime/World/CPlayer.cpp +++ b/Runtime/World/CPlayer.cpp @@ -5284,7 +5284,7 @@ void CPlayer::SetMorphBallState(EPlayerMorphBallState state, CStateManager& mgr) } bool CPlayer::CanLeaveMorphBallState(CStateManager& mgr, zeus::CVector3f& pos) const { - if (x768_morphball->IsProjectile() || !x590_ || + if (x768_morphball->IsProjectile() || !x590_leaveMorphballAllowed || (IsUnderBetaMetroidAttack(mgr) && x2f8_morphBallState == EPlayerMorphBallState::Morphed)) return false; if (!x9c4_28_canLeaveMorphBall) diff --git a/Runtime/World/CPlayer.hpp b/Runtime/World/CPlayer.hpp index 487790f53..13932577a 100644 --- a/Runtime/World/CPlayer.hpp +++ b/Runtime/World/CPlayer.hpp @@ -233,7 +233,7 @@ private: int x584_ballTransitionAnim = -1; float x588_alpha = 1.f; float x58c_transitionVel = 0.f; - bool x590_ = true; + bool x590_leaveMorphballAllowed = true; TReservedAverage x594_transisionBeamXfs; TReservedAverage x658_transitionModelXfs; TReservedAverage x71c_transitionModelAlphas; @@ -611,7 +611,7 @@ public: EPlayerOrbitRequest GetOrbitRequest() const { return x30c_orbitRequest; } bool IsShowingCrosshairs() const { return x9c4_25_showCrosshairs; } bool IsSidewaysDashing() const { return x37c_sidewaysDashing; } - void Set_X590(bool b) { x590_ = b; } + void SetLeaveMorphBallAllowed(bool b) { x590_leaveMorphballAllowed = b; } const zeus::CVector3f& GetOrbitPoint() const { return x314_orbitPoint; } float GetAverageSpeed() const; bool IsInWaterMovement() const { return x9c4_31_inWaterMovement; } diff --git a/Runtime/World/CScriptDoor.cpp b/Runtime/World/CScriptDoor.cpp index 0efda3ba1..fdb2c78c0 100644 --- a/Runtime/World/CScriptDoor.cpp +++ b/Runtime/World/CScriptDoor.cpp @@ -81,16 +81,17 @@ void CScriptDoor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStat case EScriptObjectMessage::Action: { if (x27c_partner1 != kInvalidUniqueId) { if (TCastToPtr door = mgr.ObjectById(x27c_partner1)) { - if (!x2a8_26_isOpen) - return; - x2a8_30_doClose = true; - mgr.SendScriptMsg(door, GetUniqueId(), EScriptObjectMessage::Close); + if (door->x2a8_26_isOpen) { + x2a8_30_doClose = true; + mgr.SendScriptMsg(door, GetUniqueId(), EScriptObjectMessage::Close); + door->x2a8_30_doClose = true; + } } } else if (x2a8_26_isOpen) { x2a8_30_doClose = true; if (TCastToPtr door = mgr.ObjectById(x27e_partner2)) { mgr.SendScriptMsg(door, GetUniqueId(), EScriptObjectMessage::Close); - x2a8_30_doClose = true; + door->x2a8_30_doClose = true; } x2a8_26_isOpen = false; SetDoorAnimation(EDoorAnimType::Close); @@ -102,13 +103,14 @@ void CScriptDoor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStat if (!GetActive() || x2a8_26_isOpen) return; - u32 doorCond = TCastToConstPtr(mgr.GetObjectById(uid)) ? 2 : GetDoorOpenCondition(mgr); + EDoorOpenCondition doorCond = + TCastToConstPtr(mgr.GetObjectById(uid)) ? EDoorOpenCondition::Ready : GetDoorOpenCondition(mgr); switch (doorCond) { - case 1: + case EDoorOpenCondition::Loading: x2a8_27_conditionsMet = true; x280_prevDoor = uid; break; - case 2: + case EDoorOpenCondition::Ready: OpenDoor(uid, mgr); break; default: @@ -151,7 +153,7 @@ void CScriptDoor::Think(float dt, CStateManager& mgr) { if (!x2a8_26_isOpen && x25c_animTime < 0.5f) x25c_animTime += dt; - if (x2a8_27_conditionsMet && GetDoorOpenCondition(mgr) == 2) { + if (x2a8_27_conditionsMet && GetDoorOpenCondition(mgr) == EDoorOpenCondition::Ready) { x2a8_27_conditionsMet = false; OpenDoor(x280_prevDoor, mgr); } @@ -176,6 +178,8 @@ void CScriptDoor::Think(float dt, CStateManager& mgr) { x2a8_28_projectilesCollide = false; x2a8_27_conditionsMet = false; SendScriptMsgs(EScriptObjectState::Closed, mgr, EScriptObjectMessage::None); + x25c_animTime = 0.f; + x2a8_30_doClose = false; } if (GetScannableObjectInfo()) @@ -282,23 +286,23 @@ void CScriptDoor::OpenDoor(TUniqueId uid, CStateManager& mgr) { } /* ORIGINAL 0-00 OFFSET: 8007ED4C */ -u32 CScriptDoor::GetDoorOpenCondition(CStateManager& mgr) { +CScriptDoor::EDoorOpenCondition CScriptDoor::GetDoorOpenCondition(CStateManager& mgr) { const TCastToPtr dock = mgr.ObjectById(x282_dockId); if (!dock) - return 2; + return EDoorOpenCondition::Ready; if (x25c_animTime < 0.05f || x2a8_30_doClose) - return 1; + return EDoorOpenCondition::Loading; TAreaId destArea = dock->GetAreaId(); if (destArea < 0 || destArea >= mgr.GetWorld()->GetNumAreas()) - return 0; + return EDoorOpenCondition::NotReady; if (!mgr.GetWorld()->GetAreaAlways(destArea)->IsPostConstructed()) - return 1; + return EDoorOpenCondition::Loading; if (!mgr.GetWorld()->AreSkyNeedsMet()) - return 1; + return EDoorOpenCondition::Loading; TAreaId connArea = mgr.GetWorld() ->GetAreaAlways(dock->GetAreaId()) @@ -306,18 +310,18 @@ u32 CScriptDoor::GetDoorOpenCondition(CStateManager& mgr) { ->GetConnectedAreaId(dock->GetDockReference(mgr)); if (connArea == kInvalidAreaId) - return 0; + return EDoorOpenCondition::NotReady; const CWorld* world = mgr.GetWorld(); const CGameArea* area = world->GetAreaAlways(connArea); if (!area->IsPostConstructed()) { mgr.SendScriptMsg(dock, GetUniqueId(), EScriptObjectMessage::SetToMax); - return 1; + return EDoorOpenCondition::Loading; } if (area->GetPostConstructed()->x113c_playerActorsLoading != 0) - return 1; + return EDoorOpenCondition::Loading; for (CEntity* ent : mgr.GetPlatformAndDoorObjectList()) { TCastToPtr door(ent); @@ -326,7 +330,7 @@ u32 CScriptDoor::GetDoorOpenCondition(CStateManager& mgr) { if (door->GetAreaIdAlways() == GetAreaIdAlways() && door->x2a8_25_wasOpen) { if (door->x282_dockId != kInvalidUniqueId) - return 1; + return EDoorOpenCondition::Loading; } } @@ -335,16 +339,19 @@ u32 CScriptDoor::GetDoorOpenCondition(CStateManager& mgr) { continue; if (!aliveArea.IsFinishedOccluding()) - return 1; + return EDoorOpenCondition::Loading; } // if (area->TryTakingOutOfARAM()) { if (world->GetMapWorld()->IsMapAreasStreaming()) - return 1; + return EDoorOpenCondition::Loading; } - return 2; + if (!CGraphics::g_BooFactory->areShadersReady()) + return EDoorOpenCondition::Loading; + + return EDoorOpenCondition::Ready; } /* ORIGINAL 0-00 OFFSET: 8007E9D0 */ diff --git a/Runtime/World/CScriptDoor.hpp b/Runtime/World/CScriptDoor.hpp index 1edec89a8..6ebd6c3ba 100644 --- a/Runtime/World/CScriptDoor.hpp +++ b/Runtime/World/CScriptDoor.hpp @@ -12,6 +12,12 @@ public: Ready, }; + enum class EDoorOpenCondition { + NotReady, + Loading, + Ready + }; + float x258_animLen; float x25c_animTime = 0.f; EDoorAnimType x260_doorAnimState = EDoorAnimType::Open; @@ -45,7 +51,7 @@ public: void ForceClosed(CStateManager&); bool IsConnectedToArea(const CStateManager& mgr, TAreaId area); void OpenDoor(TUniqueId, CStateManager&); - u32 GetDoorOpenCondition(CStateManager& mgr); + EDoorOpenCondition GetDoorOpenCondition(CStateManager& mgr); void SetDoorAnimation(EDoorAnimType); std::optional GetTouchBounds() const; std::optional GetProjectileBounds() const; diff --git a/Runtime/World/CWorldShadow.cpp b/Runtime/World/CWorldShadow.cpp index 6b15c0220..9eb4cd780 100644 --- a/Runtime/World/CWorldShadow.cpp +++ b/Runtime/World/CWorldShadow.cpp @@ -79,7 +79,7 @@ void CWorldShadow::BuildLightShadowTexture(const CStateManager& mgr, TAreaId aid CGraphics::SetModelMatrix(zeus::CTransform()); CBooModel::SetDrawingOccluders(true); g_Renderer->PrepareDynamicLights({}); - g_Renderer->UpdateAreaUniforms(aid, true); + g_Renderer->UpdateAreaUniforms(aid, EWorldShadowMode::WorldOnActorShadow); g_Renderer->DrawUnsortedGeometry(aid, 0, 0, true); CBooModel::SetDrawingOccluders(false); diff --git a/Runtime/World/ScriptLoader.cpp b/Runtime/World/ScriptLoader.cpp index 9754e38ca..27b1a51de 100644 --- a/Runtime/World/ScriptLoader.cpp +++ b/Runtime/World/ScriptLoader.cpp @@ -1671,21 +1671,22 @@ CEntity* ScriptLoader::LoadPuddleToadGamma(CStateManager& mgr, CInputStream& in, CPatternedInfo pInfo(in, pair.second); CActorParameters actParms = LoadActorParameters(in); - float f1 = in.readFloatBig(); - float f2 = in.readFloatBig(); - float f3 = in.readFloatBig(); - zeus::CVector3f vec = zeus::CVector3f::ReadBig(in); - float f4 = in.readFloatBig(); - float f5 = in.readFloatBig(); - float f6 = in.readFloatBig(); - CDamageInfo dInfo1(in); + float suckForceMultiplier = in.readFloatBig(); + float suckAngle = in.readFloatBig(); + float playerSuckRange = in.readFloatBig(); + zeus::CVector3f localShootDir = zeus::CVector3f::ReadBig(in); + float playerShootSpeed = in.readFloatBig(); + float shouldAttackWaitTime = in.readFloatBig(); + float spotPlayerWaitTime = in.readFloatBig(); + CDamageInfo playerShootDamage(in); CDamageInfo dInfo2(in); CAssetId collisionData(in); const CAnimationParameters& animParms = pInfo.GetAnimationParameters(); CModelData mData( CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), scale, animParms.GetInitialAnimation(), true)); return new MP1::CPuddleToadGamma(mgr.AllocateUniqueId(), name, flavor, info, xf, std::move(mData), pInfo, actParms, - f1, f2, f3, vec, f4, f5, f6, dInfo1, dInfo2, collisionData); + suckForceMultiplier, suckAngle, playerSuckRange, localShootDir, playerShootSpeed, + shouldAttackWaitTime, spotPlayerWaitTime, playerShootDamage, dInfo2, collisionData); } CEntity* ScriptLoader::LoadDistanceFog(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { @@ -2029,7 +2030,7 @@ CEntity* ScriptLoader::LoadDebrisExtended(CStateManager& mgr, CInputStream& in, CScriptDebris::EOrientationType particle2Or = CScriptDebris::EOrientationType(in.readUint32Big()); CAssetId particle3 = in.readUint32Big(); - //zeus::CVector3f particle3Scale = zeus::CVector3f::ReadBig(in); /* Not actually used, go figure */ + /*zeus::CVector3f particle3Scale =*/ zeus::CVector3f::ReadBig(in); /* Not actually used, go figure */ CScriptDebris::EOrientationType particle3Or = CScriptDebris::EOrientationType(in.readUint32Big()); bool solid = in.readBool(); diff --git a/Shaders/CModelShaders.frag.glsl b/Shaders/CModelShaders.frag.glsl index fa2407197..862c3ebdf 100644 --- a/Shaders/CModelShaders.frag.glsl +++ b/Shaders/CModelShaders.frag.glsl @@ -289,7 +289,7 @@ vec4 PostFunc(vec4 colorIn) { #if defined(URDE_MB_SHADOW) vec4 PostFunc(vec4 colorIn) { float idTexel = texture(extTex0, vtf.extUvs[0]).a; - float sphereTexel = texture(extTex1, vtf.extUvs[1]).a; + float sphereTexel = texture(extTex1, vtf.extUvs[1]).r; float fadeTexel = texture(extTex2, vtf.extUvs[2]).a; float val = ((abs(idTexel - shadowId) < 0.001) ? (dot(vtf.mvNorm.xyz, shadowUp.xyz) * shadowUp.w) : 0.0) * diff --git a/Shaders/CModelShaders.frag.hlsl b/Shaders/CModelShaders.frag.hlsl index 52f0c5421..340684168 100644 --- a/Shaders/CModelShaders.frag.hlsl +++ b/Shaders/CModelShaders.frag.hlsl @@ -287,8 +287,8 @@ float4 PostFunc(in VertToFrag vtf, float4 colorIn) { #if defined(URDE_MB_SHADOW) float4 PostFunc(in VertToFrag vtf, float4 colorIn) { float idTexel = extTex0.Sample(samp, vtf.extUvs[0]).a; - float sphereTexel = extTex1.Sample(samp, vtf.extUvs[1]).a; - float fadeTexel = extTex2.Sample(samp, vtf.extUvs[2]).a; + float sphereTexel = extTex1.Sample(clampSamp, vtf.extUvs[1]).r; + float fadeTexel = extTex2.Sample(clampSamp, vtf.extUvs[2]).a; float val = ((abs(idTexel - shadowId) < 0.001) ? (dot(vtf.mvNorm.xyz, shadowUp.xyz) * shadowUp.w) : 0.0) * sphereTexel * fadeTexel; diff --git a/Shaders/CModelShaders.frag.metal b/Shaders/CModelShaders.frag.metal index d1a8ff7e9..b917cee43 100644 --- a/Shaders/CModelShaders.frag.metal +++ b/Shaders/CModelShaders.frag.metal @@ -246,7 +246,7 @@ float4 FogFunc(thread VertToFrag& vtf, constant LightingUniform& lu, float4 colo #if defined(URDE_LIGHTING) || defined(URDE_LIGHTING_SHADOW) || defined(URDE_LIGHTING_CUBE_REFLECTION) || defined(URDE_LIGHTING_CUBE_REFLECTION_SHADOW) float4 PostFunc(thread VertToFrag& vtf, constant LightingUniform& lu, texture2d extTex0, texture2d extTex1, texture2d extTex2, - sampler samp, float4 colorIn) { + sampler samp, sampler clampSamp, float4 colorIn) { return FogFunc(vtf, lu, colorIn) * lu.mulColor + lu.addColor; } #endif @@ -254,7 +254,7 @@ float4 PostFunc(thread VertToFrag& vtf, constant LightingUniform& lu, #if defined(URDE_THERMAL_HOT) float4 PostFunc(thread VertToFrag& vtf, constant LightingUniform& lu, texture2d extTex0, texture2d extTex1, texture2d extTex2, - sampler samp, float4 colorIn) { + sampler samp, sampler clampSamp, float4 colorIn) { return extTex0.sample(samp, vtf.extUvs0).rrrr * lu.tmulColor + lu.taddColor; } #endif @@ -262,7 +262,7 @@ float4 PostFunc(thread VertToFrag& vtf, constant LightingUniform& lu, #if defined(URDE_THERMAL_COLD) float4 PostFunc(thread VertToFrag& vtf, constant LightingUniform& lu, texture2d extTex0, texture2d extTex1, texture2d extTex2, - sampler samp, float4 colorIn) { + sampler samp, sampler clampSamp, float4 colorIn) { return colorIn * float4(0.75, 0.75, 0.75, 0.75); } #endif @@ -270,7 +270,7 @@ float4 PostFunc(thread VertToFrag& vtf, constant LightingUniform& lu, #if defined(URDE_SOLID) float4 PostFunc(thread VertToFrag& vtf, constant LightingUniform& lu, texture2d extTex0, texture2d extTex1, texture2d extTex2, - sampler samp, float4 colorIn) { + sampler samp, sampler clampSamp, float4 colorIn) { return lu.solidColor; } #endif @@ -278,10 +278,10 @@ float4 PostFunc(thread VertToFrag& vtf, constant LightingUniform& lu, #if defined(URDE_MB_SHADOW) float4 PostFunc(thread VertToFrag& vtf, constant LightingUniform& lu, texture2d extTex0, texture2d extTex1, texture2d extTex2, - sampler samp, float4 colorIn) { + sampler samp, sampler clampSamp, float4 colorIn) { float idTexel = extTex0.sample(samp, vtf.extUvs0).a; - float sphereTexel = extTex1.sample(samp, vtf.extUvs1).a; - float fadeTexel = extTex2.sample(samp, vtf.extUvs2).a; + float sphereTexel = extTex1.sample(clampSamp, vtf.extUvs1).r; + float fadeTexel = extTex2.sample(clampSamp, vtf.extUvs2).a; float val = ((abs(idTexel - lu.shadowId) < 0.001) ? (dot(vtf.mvNorm.xyz, lu.shadowUp.xyz) * lu.shadowUp.w) : 0.0) * sphereTexel * fadeTexel; @@ -292,7 +292,7 @@ float4 PostFunc(thread VertToFrag& vtf, constant LightingUniform& lu, #if defined(URDE_DISINTEGRATE) float4 PostFunc(thread VertToFrag& vtf, constant LightingUniform& lu, texture2d extTex0, texture2d extTex1, texture2d extTex2, - sampler samp, float4 colorIn) { + sampler samp, sampler clampSamp, float4 colorIn) { float4 texel0 = extTex0.sample(samp, vtf.extUvs0); float4 texel1 = extTex0.sample(samp, vtf.extUvs1); colorIn = mix(float4(0.0, 0.0, 0.0, 0.0), texel1, texel0); @@ -370,7 +370,7 @@ fragment float4 fmain(VertToFrag vtf [[ stage_in ]], SampleTexture_reflection() + ReflectionFunc(); tmp.a = SampleTextureAlpha_alpha(); #endif - float4 colorOut = PostFunc(vtf, lu, extTex0, extTex1, extTex2, samp, tmp); + float4 colorOut = PostFunc(vtf, lu, extTex0, extTex1, extTex2, samp, clampSamp, tmp); #if defined(URDE_ALPHA_TEST) if (colorOut.a < 0.25) discard_fragment(); diff --git a/hecl b/hecl index 8085bc967..223e613f5 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit 8085bc96753ef27a84210a7c4226a8ff76d98437 +Subproject commit 223e613f56343c95be5d0f1f1641268a5545db22 diff --git a/lldb-extras/.lldbinit b/lldb-extras/.lldbinit index c4c9cb3c8..130bb0d8b 100644 --- a/lldb-extras/.lldbinit +++ b/lldb-extras/.lldbinit @@ -24,6 +24,11 @@ type summary add --summary-string "${var.origin}" zeus::CTransform type summary add --summary-string "${var.id%x} area=${var.id[16-25]}, layer=${var.id[26-31]}, id=${var.id[0-15]}" urde::TEditorId type summary add --summary-string "${var.id}" urde::TUniqueId +type summary add --summary-string "${var.x0_time}" urde::CCharAnimTime + +type summary add --summary-string "${var.id%x}" urde::CAssetId +type summary add --summary-string "${var.type.fcc} ${var.id.id%x}" urde::SObjectTag + # \s*(\S+) \((\S+)\) # type summary add --summary-string "\${var.x10_name} \${var.xc_editorId}" $2::$1\n type summary add --summary-string "${var.x10_name} ${var.xc_editorId}, active=${var.x30_24_active}" urde::CEntity