mirror of https://github.com/AxioDL/metaforce.git
Merge branch 'master' of ssh+git://git.axiodl.com:6431/AxioDL/urde
This commit is contained in:
commit
8a974d6e5e
|
@ -15,10 +15,11 @@
|
|||
namespace DataSpec::DNAANCS {
|
||||
|
||||
template <class PAKRouter, class ANCSDNA, class MaterialSet, class SurfaceHeader, atUint32 CMDLVersion>
|
||||
bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, const hecl::ProjectPath& outPath,
|
||||
bool ReadANCSToBlender(hecl::blender::Token& btok, const ANCSDNA& ancs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, const SpecBase& dataspec,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged, bool force) {
|
||||
/* Extract character CMDL/CSKR first */
|
||||
auto& conn = btok.getBlenderConnection();
|
||||
/* Extract character CMDL/CSKR/CINF first */
|
||||
std::vector<CharacterResInfo<typename PAKRouter::IDType>> chResInfo;
|
||||
ancs.getCharacterResInfo(chResInfo);
|
||||
for (const auto& info : chResInfo) {
|
||||
|
@ -49,11 +50,19 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con
|
|||
conn.saveBlend();
|
||||
}
|
||||
}
|
||||
if (const typename PAKRouter::EntryType* cinfE = pakRouter.lookupEntry(info.cinf, &node, true, false)) {
|
||||
hecl::ProjectPath cinfPath = pakRouter.getWorking(cinfE);
|
||||
if (cinfPath.getPathType() == hecl::ProjectPath::Type::None) {
|
||||
PAKEntryReadStream rs = cinfE->beginReadStream(*node);
|
||||
ANCSDNA::CINFType::Extract(dataspec, rs, cinfPath, pakRouter, *cinfE, false, btok, fileChanged);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Extract attachment CMDL/CSKRs first */
|
||||
/* Extract attachment CMDL/CSKR/CINFs first */
|
||||
auto attRange = pakRouter.lookupCharacterAttachmentRigs(entry.id);
|
||||
for (auto it = attRange.first; it != attRange.second; ++it) {
|
||||
auto cinfid = it->second.first.cinf;
|
||||
auto cmdlid = it->second.first.cmdl;
|
||||
|
||||
const nod::Node* node;
|
||||
|
@ -61,8 +70,9 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con
|
|||
hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
|
||||
if (force || cmdlPath.isNone()) {
|
||||
cmdlPath.makeDirChain(false);
|
||||
if (!conn.createBlend(cmdlPath, hecl::blender::BlendType::Mesh))
|
||||
if (!conn.createBlend(cmdlPath, hecl::blender::BlendType::Mesh)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string bestName = pakRouter.getBestEntryName(*cmdlE);
|
||||
hecl::SystemStringConv bestNameView(bestName);
|
||||
|
@ -84,6 +94,15 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con
|
|||
conn.saveBlend();
|
||||
}
|
||||
}
|
||||
if (cinfid.isValid()) {
|
||||
if (const typename PAKRouter::EntryType* cinfE = pakRouter.lookupEntry(cinfid, &node, true, false)) {
|
||||
hecl::ProjectPath cinfPath = pakRouter.getWorking(cinfE);
|
||||
if (cinfPath.getPathType() == hecl::ProjectPath::Type::None) {
|
||||
PAKEntryReadStream rs = cinfE->beginReadStream(*node);
|
||||
ANCSDNA::CINFType::Extract(dataspec, rs, cinfPath, pakRouter, *cinfE, false, btok, fileChanged);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string bestName = pakRouter.getBestEntryName(entry);
|
||||
|
@ -253,17 +272,17 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, con
|
|||
|
||||
template bool
|
||||
ReadANCSToBlender<PAKRouter<DNAMP1::PAKBridge>, DNAMP1::ANCS, DNAMP1::MaterialSet, DNACMDL::SurfaceHeader_1, 2>(
|
||||
hecl::blender::Connection& conn, const DNAMP1::ANCS& ancs, const hecl::ProjectPath& outPath,
|
||||
hecl::blender::Token& btok, const DNAMP1::ANCS& ancs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP1::PAKBridge>& pakRouter, const typename PAKRouter<DNAMP1::PAKBridge>::EntryType& entry,
|
||||
const SpecBase& dataspec, std::function<void(const hecl::SystemChar*)> fileChanged, bool force);
|
||||
template bool
|
||||
ReadANCSToBlender<PAKRouter<DNAMP2::PAKBridge>, DNAMP2::ANCS, DNAMP2::MaterialSet, DNACMDL::SurfaceHeader_2, 4>(
|
||||
hecl::blender::Connection& conn, const DNAMP2::ANCS& ancs, const hecl::ProjectPath& outPath,
|
||||
hecl::blender::Token& btok, const DNAMP2::ANCS& ancs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP2::PAKBridge>& pakRouter, const typename PAKRouter<DNAMP2::PAKBridge>::EntryType& entry,
|
||||
const SpecBase& dataspec, std::function<void(const hecl::SystemChar*)> fileChanged, bool force);
|
||||
template bool
|
||||
ReadANCSToBlender<PAKRouter<DNAMP3::PAKBridge>, DNAMP3::CHAR, DNAMP3::MaterialSet, DNACMDL::SurfaceHeader_3, 4>(
|
||||
hecl::blender::Connection& conn, const DNAMP3::CHAR& ancs, const hecl::ProjectPath& outPath,
|
||||
hecl::blender::Token& btok, const DNAMP3::CHAR& ancs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP3::PAKBridge>& pakRouter, const typename PAKRouter<DNAMP3::PAKBridge>::EntryType& entry,
|
||||
const SpecBase& dataspec, std::function<void(const hecl::SystemChar*)> fileChanged, bool force);
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ struct AnimationResInfo {
|
|||
};
|
||||
|
||||
template <class PAKRouter, class ANCSDNA, class MaterialSet, class SurfaceHeader, atUint32 CMDLVersion>
|
||||
bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, const hecl::ProjectPath& outPath,
|
||||
bool ReadANCSToBlender(hecl::blender::Token& btok, const ANCSDNA& ancs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, const SpecBase& dataspec,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged, bool force = false);
|
||||
|
||||
|
|
|
@ -975,9 +975,8 @@ bool ANCS::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl:
|
|||
}
|
||||
|
||||
if (force || blendType == hecl::ProjectPath::Type::None) {
|
||||
hecl::blender::Connection& conn = btok.getBlenderConnection();
|
||||
DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, ANCS, MaterialSet, DNACMDL::SurfaceHeader_1, 2>(
|
||||
conn, ancs, blendPath, pakRouter, entry, dataSpec, fileChanged, force);
|
||||
btok, ancs, blendPath, pakRouter, entry, dataSpec, fileChanged, force);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -215,9 +215,8 @@ struct ANCS : BigDNA {
|
|||
}
|
||||
|
||||
if (force || blendType == hecl::ProjectPath::Type::None) {
|
||||
hecl::blender::Connection& conn = btok.getBlenderConnection();
|
||||
DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, ANCS, MaterialSet, DNACMDL::SurfaceHeader_2, 4>(
|
||||
conn, ancs, blendPath, pakRouter, entry, dataSpec, fileChanged, force);
|
||||
btok, ancs, blendPath, pakRouter, entry, dataSpec, fileChanged, force);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -283,9 +283,8 @@ struct CHAR : BigDNA {
|
|||
}
|
||||
|
||||
if (force || blendType == hecl::ProjectPath::Type::None) {
|
||||
hecl::blender::Connection& conn = btok.getBlenderConnection();
|
||||
DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, CHAR, MaterialSet, DNACMDL::SurfaceHeader_3, 4>(
|
||||
conn, aChar, blendPath, pakRouter, entry, dataSpec, fileChanged, force);
|
||||
btok, aChar, blendPath, pakRouter, entry, dataSpec, fileChanged, force);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,15 +22,10 @@ namespace DataSpec::DNAMP3 {
|
|||
logvisor::Module Log("urde::DNAMP3");
|
||||
|
||||
static bool GetNoShare(std::string_view name) {
|
||||
if (name == "UniverseArea.pak"sv)
|
||||
return false;
|
||||
std::string lowerName(name);
|
||||
std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), tolower);
|
||||
if (!lowerName.compare(0, 7, "metroid"))
|
||||
return false;
|
||||
if (!lowerName.compare(0, 5, "rs5fe"))
|
||||
return false;
|
||||
return true;
|
||||
return !lowerName.starts_with("metroid"sv) && !lowerName.starts_with("frontend"sv) &&
|
||||
!lowerName.starts_with("rs5fe"sv) && !lowerName.starts_with("universearea"sv);
|
||||
}
|
||||
|
||||
PAKBridge::PAKBridge(const nod::Node& node, bool doExtract)
|
||||
|
|
|
@ -29,7 +29,7 @@ void ViewManager::InitMP1(MP1::CMain& main) {
|
|||
if (!m_noShaderWarmup)
|
||||
main.WarmupShaders();
|
||||
|
||||
m_testGameView.reset(new TestGameView(*this, m_viewResources, *m_rootView));
|
||||
m_testGameView.reset(new TestGameView(*this, m_viewResources, *m_rootView, m_cvarManager));
|
||||
|
||||
m_rootView->accessContentViews().clear();
|
||||
m_rootView->accessContentViews().push_back(m_testGameView.get());
|
||||
|
@ -62,17 +62,11 @@ void ViewManager::TestGameView::think() {
|
|||
|
||||
if (m_debugText) {
|
||||
std::string overlayText;
|
||||
const hecl::CVar* showFrameIdx = hecl::CVarManager::instance()->findCVar("debugOverlay.showFrameCounter");
|
||||
const hecl::CVar* playerInfo = hecl::CVarManager::instance()->findCVar("debugOverlay.playerInfo");
|
||||
const hecl::CVar* worldInfo = hecl::CVarManager::instance()->findCVar("debugOverlay.worldInfo");
|
||||
const hecl::CVar* areaInfo = hecl::CVarManager::instance()->findCVar("debugOverlay.areaInfo");
|
||||
const hecl::CVar* showInGameTime = hecl::CVarManager::instance()->findCVar("debugOverlay.showInGameTime");
|
||||
const hecl::CVar* showResourceStats = hecl::CVarManager::instance()->findCVar("debugOverlay.showResourceStats");
|
||||
if (g_StateManager) {
|
||||
if (showFrameIdx && showFrameIdx->toBoolean())
|
||||
if (m_cvarCommons.m_debugOverlayShowFrameCounter->toBoolean())
|
||||
overlayText += fmt::format(FMT_STRING("Frame: {}\n"), g_StateManager->GetUpdateFrameIndex());
|
||||
|
||||
if (showInGameTime && showInGameTime->toBoolean()) {
|
||||
if (m_cvarCommons.m_debugOverlayShowInGameTime->toBoolean()) {
|
||||
double igt = g_GameState->GetTotalPlayTime();
|
||||
u32 ms = u64(igt * 1000) % 1000;
|
||||
auto pt = std::div(igt, 3600);
|
||||
|
@ -80,7 +74,7 @@ void ViewManager::TestGameView::think() {
|
|||
fmt::format(FMT_STRING("PlayTime: {:02d}:{:02d}:{:02d}.{:03d}\n"), pt.quot, pt.rem / 60, pt.rem % 60, ms);
|
||||
}
|
||||
|
||||
if (g_StateManager->Player() && playerInfo && playerInfo->toBoolean()) {
|
||||
if (g_StateManager->Player() && m_cvarCommons.m_debugOverlayPlayerInfo->toBoolean()) {
|
||||
const CPlayer& pl = g_StateManager->GetPlayer();
|
||||
const zeus::CQuaternion plQ = zeus::CQuaternion(pl.GetTransform().getRotation().buildMatrix3f());
|
||||
const zeus::CTransform camXf = g_StateManager->GetCameraManager()->GetCurrentCameraTransform(*g_StateManager);
|
||||
|
@ -98,7 +92,7 @@ void ViewManager::TestGameView::think() {
|
|||
camXf.origin.y(), camXf.origin.z(), zeus::radToDeg(camQ.roll()),
|
||||
zeus::radToDeg(camQ.pitch()), zeus::radToDeg(camQ.yaw()));
|
||||
}
|
||||
if (worldInfo && worldInfo->toBoolean()) {
|
||||
if (m_cvarCommons.m_debugOverlayWorldInfo->toBoolean()) {
|
||||
TLockedToken<CStringTable> tbl =
|
||||
g_SimplePool->GetObj({FOURCC('STRG'), g_StateManager->GetWorld()->IGetStringTableAssetId()});
|
||||
const urde::TAreaId aId = g_GameState->CurrentWorldState().GetCurrentAreaId();
|
||||
|
@ -107,7 +101,7 @@ void ViewManager::TestGameView::think() {
|
|||
}
|
||||
|
||||
const urde::TAreaId aId = g_GameState->CurrentWorldState().GetCurrentAreaId();
|
||||
if (areaInfo && areaInfo->toBoolean() && g_StateManager->GetWorld() &&
|
||||
if (m_cvarCommons.m_debugOverlayAreaInfo->toBoolean() && g_StateManager->GetWorld() &&
|
||||
g_StateManager->GetWorld()->DoesAreaExist(aId)) {
|
||||
const auto& layerStates = g_GameState->CurrentWorldState().GetLayerState();
|
||||
std::string layerBits;
|
||||
|
@ -126,7 +120,7 @@ void ViewManager::TestGameView::think() {
|
|||
}
|
||||
}
|
||||
|
||||
if (showResourceStats && showResourceStats->toBoolean())
|
||||
if (m_cvarCommons.m_debugOverlayShowResourceStats->toBoolean())
|
||||
overlayText += fmt::format(FMT_STRING("Resource Objects: {}\n"), g_SimplePool->GetLiveObjects());
|
||||
|
||||
if (!overlayText.empty())
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "hecl/CVarManager.hpp"
|
||||
#include "hecl/CVarCommons.hpp"
|
||||
#include "boo/audiodev/IAudioVoiceEngine.hpp"
|
||||
#include "amuse/BooBackend.hpp"
|
||||
#include "ProjectManager.hpp"
|
||||
|
@ -57,9 +58,11 @@ class ViewManager final : public specter::IViewManager {
|
|||
class TestGameView : public specter::View {
|
||||
ViewManager& m_vm;
|
||||
std::unique_ptr<specter::MultiLineTextView> m_debugText;
|
||||
hecl::CVarCommons m_cvarCommons;
|
||||
|
||||
public:
|
||||
TestGameView(ViewManager& vm, specter::ViewResources& res, specter::View& parent) : View(res, parent), m_vm(vm) {}
|
||||
TestGameView(ViewManager& vm, specter::ViewResources& res, specter::View& parent, hecl::CVarManager& cvarMgr)
|
||||
: View(res, parent), m_vm(vm), m_cvarCommons(cvarMgr) {}
|
||||
void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) override;
|
||||
void draw(boo::IGraphicsCommandQueue* gfxQ) override;
|
||||
void think() override;
|
||||
|
|
|
@ -89,7 +89,6 @@ struct Application : boo::IApplicationCallback {
|
|||
|
||||
void initialize(boo::IApplication* app) {
|
||||
zeus::detectCPU();
|
||||
createGlobalCVars();
|
||||
for (const boo::SystemString& arg : app->getArgs()) {
|
||||
if (arg.find(_SYS_STR("--verbosity=")) == 0 || arg.find(_SYS_STR("-v=")) == 0) {
|
||||
hecl::SystemUTF8Conv utf8Arg(arg.substr(arg.find_last_of('=') + 1));
|
||||
|
@ -113,27 +112,6 @@ struct Application : boo::IApplicationCallback {
|
|||
uint32_t getAnisotropy() const { return m_cvarCommons.getAnisotropy(); }
|
||||
|
||||
bool getDeepColor() const { return m_cvarCommons.getDeepColor(); }
|
||||
|
||||
void createGlobalCVars() {
|
||||
m_cvarManager.findOrMakeCVar("debugOverlay.playerInfo"sv,
|
||||
"Displays information about the player, such as location and orientation"sv, false,
|
||||
hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ReadOnly);
|
||||
m_cvarManager.findOrMakeCVar("debugOverlay.worldInfo"sv,
|
||||
"Displays information about the current world, such as world asset ID, and areaId"sv,
|
||||
false,
|
||||
hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ReadOnly);
|
||||
m_cvarManager.findOrMakeCVar(
|
||||
"debugOverlay.areaInfo"sv,
|
||||
"Displays information about the current area, such as asset ID, object/layer counts, and active layer bits"sv,
|
||||
false, hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ReadOnly);
|
||||
m_cvarManager.findOrMakeCVar("debugOverlay.showFrameCounter"sv, "Displays the current frame index"sv, false,
|
||||
hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ReadOnly);
|
||||
m_cvarManager.findOrMakeCVar("debugOverlay.showInGameTime"sv, "Displays the current in game time"sv, false,
|
||||
hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ReadOnly);
|
||||
m_cvarManager.findOrMakeCVar("debugOverlay.showResourceStats"sv,
|
||||
"Displays the current live resource object and token counts"sv, false,
|
||||
hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ReadOnly);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace urde
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
**Official Discord Channel:** https://discord.gg/AMBVFuf
|
||||
|
||||
![URDE screenshot](assets/urde-screen1.png)
|
||||
|
||||
### Download
|
||||
Precompiled builds of the command-line extraction utility (`hecl`) with embedded dataspec libraries are available at https://releases.axiodl.com. This will give you intermediate dumps of original formats as *blender* and *yaml* representations.
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@ class CScannableObjectInfo {
|
|||
public:
|
||||
enum class EPanelType {};
|
||||
|
||||
static constexpr size_t NumBuckets = 4;
|
||||
|
||||
struct SBucket {
|
||||
CAssetId x0_texture;
|
||||
float x4_appearanceRange = 0.f;
|
||||
|
@ -29,14 +31,14 @@ private:
|
|||
float x8_totalDownloadTime = 0.f;
|
||||
u32 xc_category = 0;
|
||||
bool x10_important = false;
|
||||
rstl::reserved_vector<SBucket, 4> x14_buckets;
|
||||
rstl::reserved_vector<SBucket, NumBuckets> x14_buckets;
|
||||
|
||||
public:
|
||||
CScannableObjectInfo(CInputStream&, CAssetId);
|
||||
CAssetId GetScannableObjectId() const { return x0_scannableObjectId; }
|
||||
CAssetId GetStringTableId() const { return x4_stringId; }
|
||||
float GetTotalDownloadTime() const { return x8_totalDownloadTime; }
|
||||
const SBucket& GetBucket(s32 idx) const { return x14_buckets[idx]; }
|
||||
const SBucket& GetBucket(size_t idx) const { return x14_buckets[idx]; }
|
||||
u32 GetCategory() const { return xc_category; }
|
||||
bool IsImportant() const { return x10_important; }
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
#include "Runtime/CPlayerState.hpp"
|
||||
|
@ -120,13 +121,13 @@ private:
|
|||
bool x219_missileShot = false;
|
||||
bool x21a_fullyCharged = false;
|
||||
u8 x21b_ = 0;
|
||||
u32 x21c_;
|
||||
u32 x220_;
|
||||
u32 x228_;
|
||||
u32 x21c_ = 0;
|
||||
u32 x220_ = 0;
|
||||
u32 x228_ = 0;
|
||||
|
||||
struct SScanReticuleRenderer {
|
||||
std::optional<CLineRenderer> m_lineRenderers[2];
|
||||
std::optional<CLineRenderer> m_stripRenderers[2][4];
|
||||
std::array<std::optional<CLineRenderer>, 2> m_lineRenderers;
|
||||
std::array<std::array<std::optional<CLineRenderer>, 4>, 2> m_stripRenderers;
|
||||
SScanReticuleRenderer();
|
||||
};
|
||||
SScanReticuleRenderer m_scanRetRenderer;
|
||||
|
|
|
@ -219,7 +219,7 @@ void CGuiTextSupport::AutoSetExtent() {
|
|||
void CGuiTextSupport::Render() {
|
||||
CheckAndRebuildRenderBuffer();
|
||||
if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) {
|
||||
SCOPED_GRAPHICS_DEBUG_GROUP("CGuiTextSupport::Draw", zeus::skBlue);
|
||||
SCOPED_GRAPHICS_DEBUG_GROUP("CGuiTextSupport::Render", zeus::skBlue);
|
||||
zeus::CTransform oldModel = CGraphics::g_GXModelMatrix;
|
||||
CGraphics::SetModelMatrix(oldModel * zeus::CTransform::Scale(1.f, 1.f, -1.f));
|
||||
buf->Render(x2c_geometryColor, x10_curTimeMod900);
|
||||
|
|
|
@ -15,10 +15,11 @@ CHudBossEnergyInterface::CHudBossEnergyInterface(CGuiFrame& selHud) {
|
|||
|
||||
x18_energybart01_bossbar->SetCoordFunc(BossEnergyCoordFunc);
|
||||
x18_energybart01_bossbar->SetTesselation(0.2f);
|
||||
ITweakGuiColors::VisorEnergyBarColors barColors = g_tweakGuiColors->GetVisorEnergyBarColors(0);
|
||||
x18_energybart01_bossbar->SetFilledColor(barColors.filled);
|
||||
x18_energybart01_bossbar->SetShadowColor(barColors.shadow);
|
||||
x18_energybart01_bossbar->SetEmptyColor(barColors.empty);
|
||||
|
||||
const auto& [filled, empty, shadow] = g_tweakGuiColors->GetVisorEnergyBarColors(0);
|
||||
x18_energybart01_bossbar->SetFilledColor(filled);
|
||||
x18_energybart01_bossbar->SetShadowColor(shadow);
|
||||
x18_energybart01_bossbar->SetEmptyColor(empty);
|
||||
}
|
||||
|
||||
void CHudBossEnergyInterface::Update(float dt) {
|
||||
|
|
|
@ -10,7 +10,7 @@ class CGuiTextPane;
|
|||
class CGuiWidget;
|
||||
|
||||
class CHudBossEnergyInterface {
|
||||
float x0_alpha;
|
||||
float x0_alpha = 0.f;
|
||||
float x4_fader = 0.f;
|
||||
float x8_curEnergy = 0.f;
|
||||
float xc_maxEnergy = 0.f;
|
||||
|
|
|
@ -34,7 +34,7 @@ CHudDecoInterfaceCombat::CHudDecoInterfaceCombat(CGuiFrame& selHud) {
|
|||
x78_basewidget_tickdeco0->SetColor(g_tweakGuiColors->GetTickDecoColor());
|
||||
x38_basePosition = x7c_basewidget_frame->GetLocalPosition();
|
||||
x44_baseRotation = x7c_basewidget_frame->GetLocalTransform().buildMatrix3f();
|
||||
UpdateHudAlpha();
|
||||
CHudDecoInterfaceCombat::UpdateHudAlpha();
|
||||
}
|
||||
|
||||
void CHudDecoInterfaceCombat::UpdateVisibility() {
|
||||
|
@ -127,7 +127,7 @@ CHudDecoInterfaceScan::CHudDecoInterfaceScan(CGuiFrame& selHud) : x14_selHud(sel
|
|||
x250_basewidget_rightside->SetLocalPosition(x250_basewidget_rightside->RotateO2P(x224_rightsidePosition - sidesPos));
|
||||
x234_sidesPositioner = FLT_MAX;
|
||||
|
||||
UpdateHudAlpha();
|
||||
CHudDecoInterfaceScan::UpdateHudAlpha();
|
||||
}
|
||||
|
||||
void CHudDecoInterfaceScan::UpdateVisibility() {
|
||||
|
@ -377,7 +377,7 @@ CHudDecoInterfaceXRay::CHudDecoInterfaceXRay(CGuiFrame& selHud) {
|
|||
if (CGuiWidget* w = selHud.FindWidget("model_threatslider"))
|
||||
w->SetDepthWrite(true);
|
||||
|
||||
UpdateHudAlpha();
|
||||
CHudDecoInterfaceXRay::UpdateHudAlpha();
|
||||
}
|
||||
|
||||
void CHudDecoInterfaceXRay::UpdateVisibility() {
|
||||
|
@ -482,7 +482,7 @@ CHudDecoInterfaceThermal::CHudDecoInterfaceThermal(CGuiFrame& selHud) {
|
|||
}
|
||||
|
||||
x14_pivotPosition = x78_basewidget_pivot->GetIdlePosition();
|
||||
UpdateHudAlpha();
|
||||
CHudDecoInterfaceThermal::UpdateHudAlpha();
|
||||
}
|
||||
|
||||
void CHudDecoInterfaceThermal::UpdateVisibility() {
|
||||
|
|
|
@ -45,20 +45,23 @@ void CHudRadarInterface::DoDrawRadarPaint(const zeus::CVector3f& translate, floa
|
|||
|
||||
void CHudRadarInterface::DrawRadarPaint(const zeus::CVector3f& enemyPos, float radius, float alpha,
|
||||
const SRadarPaintDrawParms& parms) {
|
||||
zeus::CVector2f playerToEnemy = enemyPos.toVec2f() - parms.x0_playerPos.toVec2f();
|
||||
const zeus::CVector2f playerToEnemy = enemyPos.toVec2f() - parms.x0_playerPos.toVec2f();
|
||||
const float zDelta = std::fabs(enemyPos.z() - parms.x0_playerPos.z());
|
||||
|
||||
float zDelta = std::fabs(enemyPos.z() - parms.x0_playerPos.z());
|
||||
if (playerToEnemy.magnitude() > parms.x78_xyRadius || zDelta > parms.x7c_zRadius) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (playerToEnemy.magnitude() <= parms.x78_xyRadius && zDelta <= parms.x7c_zRadius) {
|
||||
if (zDelta > parms.x80_ZCloseRadius)
|
||||
if (zDelta > parms.x80_ZCloseRadius) {
|
||||
alpha *= 1.f - (zDelta - parms.x80_ZCloseRadius) / (parms.x7c_zRadius - parms.x80_ZCloseRadius);
|
||||
zeus::CVector2f scopeScaled = playerToEnemy * parms.x70_scopeScalar;
|
||||
}
|
||||
|
||||
const zeus::CVector2f scopeScaled = playerToEnemy * parms.x70_scopeScalar;
|
||||
zeus::CColor color = g_tweakGuiColors->GetRadarEnemyPaintColor();
|
||||
color.a() *= alpha;
|
||||
color.a() *= parms.x74_alpha;
|
||||
DoDrawRadarPaint(parms.xc_preTranslate * zeus::CVector3f(scopeScaled.x(), 0.f, scopeScaled.y()), radius, color);
|
||||
}
|
||||
}
|
||||
|
||||
void CHudRadarInterface::SetIsVisibleGame(bool v) {
|
||||
x3c_24_visibleGame = v;
|
||||
|
@ -66,29 +69,33 @@ void CHudRadarInterface::SetIsVisibleGame(bool v) {
|
|||
}
|
||||
|
||||
void CHudRadarInterface::Update(float dt, const CStateManager& mgr) {
|
||||
CPlayerState& playerState = *mgr.GetPlayerState();
|
||||
float visorTransFactor = (playerState.GetCurrentVisor() == CPlayerState::EPlayerVisor::Combat)
|
||||
const CPlayerState& playerState = *mgr.GetPlayerState();
|
||||
const float visorTransFactor = (playerState.GetCurrentVisor() == CPlayerState::EPlayerVisor::Combat)
|
||||
? playerState.GetVisorTransitionFactor()
|
||||
: 0.f;
|
||||
zeus::CColor color = g_tweakGuiColors->GetRadarStuffColor();
|
||||
color.a() *= g_GameState->GameOptions().GetHUDAlpha() / 255.f * visorTransFactor;
|
||||
x40_BaseWidget_RadarStuff->SetColor(color);
|
||||
bool tweakVis = g_tweakGui->GetHudVisMode() >= ITweakGui::EHudVisMode::Three;
|
||||
if (tweakVis != x3c_25_visibleDebug) {
|
||||
const bool tweakVis = g_tweakGui->GetHudVisMode() >= ITweakGui::EHudVisMode::Three;
|
||||
|
||||
if (tweakVis == x3c_25_visibleDebug) {
|
||||
return;
|
||||
}
|
||||
|
||||
x3c_25_visibleDebug = tweakVis;
|
||||
x40_BaseWidget_RadarStuff->SetVisibility(x3c_25_visibleDebug && x3c_24_visibleGame, ETraversalMode::Children);
|
||||
}
|
||||
}
|
||||
|
||||
void CHudRadarInterface::Draw(const CStateManager& mgr, float alpha) {
|
||||
alpha *= g_GameState->GameOptions().GetHUDAlpha() / 255.f;
|
||||
if (g_tweakGui->GetHudVisMode() == ITweakGui::EHudVisMode::Zero || !x3c_24_visibleGame || !x0_txtrRadarPaint ||
|
||||
!x0_txtrRadarPaint.IsLoaded())
|
||||
!x0_txtrRadarPaint.IsLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SRadarPaintDrawParms drawParms;
|
||||
|
||||
CPlayer& player = mgr.GetPlayer();
|
||||
const CPlayer& player = mgr.GetPlayer();
|
||||
if (player.IsOverrideRadarRadius()) {
|
||||
drawParms.x78_xyRadius = player.GetRadarXYRadiusOverride();
|
||||
drawParms.x7c_zRadius = player.GetRadarZRadiusOverride();
|
||||
|
@ -102,13 +109,13 @@ void CHudRadarInterface::Draw(const CStateManager& mgr, float alpha) {
|
|||
drawParms.x6c_scopeRadius = g_tweakGui->GetRadarScopeCoordRadius();
|
||||
drawParms.x70_scopeScalar = drawParms.x6c_scopeRadius / drawParms.x78_xyRadius;
|
||||
|
||||
float camZ =
|
||||
const float camZ =
|
||||
zeus::CEulerAngles(zeus::CQuaternion(mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTransform().basis)).z();
|
||||
zeus::CRelAngle angleZ(camZ);
|
||||
angleZ.makeRel();
|
||||
drawParms.xc_preTranslate = zeus::CTransform::RotateY(angleZ);
|
||||
drawParms.x3c_postTranslate = x40_BaseWidget_RadarStuff->GetWorldTransform();
|
||||
float enemyRadius = g_tweakGui->GetRadarEnemyPaintRadius();
|
||||
const float enemyRadius = g_tweakGui->GetRadarEnemyPaintRadius();
|
||||
|
||||
m_paintInsts.clear();
|
||||
x44_camera->Draw(CGuiWidgetDrawParms{0.f, zeus::CVector3f{}});
|
||||
|
@ -118,7 +125,7 @@ void CHudRadarInterface::Draw(const CStateManager& mgr, float alpha) {
|
|||
playerColor.a() *= alpha;
|
||||
DoDrawRadarPaint(zeus::skZero3f, g_tweakGui->GetRadarPlayerPaintRadius(), playerColor);
|
||||
|
||||
zeus::CAABox radarBounds(
|
||||
const zeus::CAABox radarBounds(
|
||||
player.GetTranslation().x() - drawParms.x78_xyRadius, player.GetTranslation().y() - drawParms.x78_xyRadius,
|
||||
player.GetTranslation().z() - drawParms.x7c_zRadius, player.GetTranslation().x() + drawParms.x78_xyRadius,
|
||||
player.GetTranslation().y() + drawParms.x78_xyRadius, player.GetTranslation().z() + drawParms.x7c_zRadius);
|
||||
|
@ -132,15 +139,17 @@ void CHudRadarInterface::Draw(const CStateManager& mgr, float alpha) {
|
|||
drawParms.x0_playerPos = mgr.GetPlayer().GetTranslation();
|
||||
drawParms.x74_alpha = alpha;
|
||||
|
||||
for (TUniqueId id : nearList) {
|
||||
if (TCastToConstPtr<CActor> act = mgr.GetObjectById(id)) {
|
||||
if (!act->GetActive())
|
||||
for (const TUniqueId id : nearList) {
|
||||
if (const TCastToConstPtr<CActor> act = mgr.GetObjectById(id)) {
|
||||
if (!act->GetActive()) {
|
||||
continue;
|
||||
if (TCastToConstPtr<CWallCrawlerSwarm> swarm = act.GetPtr()) {
|
||||
float radius = enemyRadius * 0.5f;
|
||||
}
|
||||
if (const TCastToConstPtr<CWallCrawlerSwarm> swarm = act.GetPtr()) {
|
||||
const float radius = enemyRadius * 0.5f;
|
||||
for (const CWallCrawlerSwarm::CBoid& boid : swarm->GetBoids()) {
|
||||
if (!boid.GetActive())
|
||||
if (!boid.GetActive()) {
|
||||
continue;
|
||||
}
|
||||
DrawRadarPaint(boid.GetTranslation(), radius, 0.5f, drawParms);
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -71,9 +71,10 @@ void CScanDisplay::CDataDot::SetDestPosition(const zeus::CVector2f& pos) {
|
|||
|
||||
CScanDisplay::CScanDisplay(const CGuiFrame& selHud) : xa0_selHud(selHud) {
|
||||
x0_dataDot = g_SimplePool->GetObj("TXTR_DataDot");
|
||||
for (int i = 0; i < 4; ++i)
|
||||
for (size_t i = 0; i < xbc_dataDots.capacity(); ++i) {
|
||||
xbc_dataDots.emplace_back(x0_dataDot);
|
||||
x170_paneStates.resize(4);
|
||||
}
|
||||
x170_paneStates.resize(x170_paneStates.capacity());
|
||||
}
|
||||
|
||||
void CScanDisplay::ProcessInput(const CFinalInput& input) {
|
||||
|
@ -139,26 +140,34 @@ void CScanDisplay::ProcessInput(const CFinalInput& input) {
|
|||
xb8_dash->SetColor(zeus::CColor(0.53f, 0.84f, 1.f, dashAlpha));
|
||||
}
|
||||
|
||||
float CScanDisplay::GetDownloadStartTime(int idx) const {
|
||||
if (!x14_scannableInfo)
|
||||
float CScanDisplay::GetDownloadStartTime(size_t idx) const {
|
||||
if (!x14_scannableInfo) {
|
||||
return 0.f;
|
||||
float nTime = x14_scannableInfo->GetBucket(idx).x4_appearanceRange;
|
||||
}
|
||||
|
||||
const float nTime = x14_scannableInfo->GetBucket(idx).x4_appearanceRange;
|
||||
float maxTime = 0.f;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
float iTime = x14_scannableInfo->GetBucket(i).x4_appearanceRange;
|
||||
if (iTime < nTime)
|
||||
for (size_t i = 0; i < CScannableObjectInfo::NumBuckets; ++i) {
|
||||
const float iTime = x14_scannableInfo->GetBucket(i).x4_appearanceRange;
|
||||
if (iTime < nTime) {
|
||||
maxTime = std::max(iTime, maxTime);
|
||||
}
|
||||
}
|
||||
|
||||
return maxTime + g_tweakGui->GetScanAppearanceDuration();
|
||||
}
|
||||
|
||||
float CScanDisplay::GetDownloadFraction(int idx, float scanningTime) const {
|
||||
if (!x14_scannableInfo)
|
||||
float CScanDisplay::GetDownloadFraction(size_t idx, float scanningTime) const {
|
||||
if (!x14_scannableInfo) {
|
||||
return 0.f;
|
||||
float appearTime = GetDownloadStartTime(idx);
|
||||
float appearRange = x14_scannableInfo->GetBucket(idx).x4_appearanceRange;
|
||||
if (appearTime == appearRange)
|
||||
}
|
||||
|
||||
const float appearTime = GetDownloadStartTime(idx);
|
||||
const float appearRange = x14_scannableInfo->GetBucket(idx).x4_appearanceRange;
|
||||
if (appearTime == appearRange) {
|
||||
return 1.f;
|
||||
}
|
||||
|
||||
return zeus::clamp(0.f, (scanningTime - appearTime) / (appearRange - appearTime), 1.f);
|
||||
}
|
||||
|
||||
|
@ -182,26 +191,26 @@ void CScanDisplay::StartScan(TUniqueId id, const CScannableObjectInfo& scanInfo,
|
|||
xa8_message->TextSupport().SetText(u"");
|
||||
xac_scrollMessage->TextSupport().SetText(u"");
|
||||
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
CAuiImagePane* pane =
|
||||
static_cast<CAuiImagePane*>(xa0_selHud.FindWidget(MP1::CPauseScreenBase::GetImagePaneName(i)));
|
||||
for (size_t i = 0; i < 20; ++i) {
|
||||
auto* pane = static_cast<CAuiImagePane*>(xa0_selHud.FindWidget(MP1::CPauseScreenBase::GetImagePaneName(i)));
|
||||
zeus::CColor color = g_tweakGuiColors->GetScanDisplayImagePaneColor();
|
||||
color.a() = 0.f;
|
||||
pane->SetColor(color);
|
||||
pane->SetTextureID0({}, g_SimplePool);
|
||||
pane->SetAnimationParms(zeus::skZero2f, 0.f, 0.f);
|
||||
int pos = -1;
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
size_t pos = SIZE_MAX;
|
||||
for (size_t j = 0; j < CScannableObjectInfo::NumBuckets; ++j) {
|
||||
if (x14_scannableInfo->GetBucket(j).x8_imagePos == i) {
|
||||
pos = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pos >= 0)
|
||||
if (pos != SIZE_MAX) {
|
||||
x170_paneStates[pos].second = pane;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < x170_paneStates.size(); ++i) {
|
||||
for (size_t i = 0; i < x170_paneStates.size(); ++i) {
|
||||
std::pair<float, CAuiImagePane*>& state = x170_paneStates[i];
|
||||
if (state.second) {
|
||||
const CScannableObjectInfo::SBucket& bucket = x14_scannableInfo->GetBucket(i);
|
||||
|
@ -211,22 +220,25 @@ void CScanDisplay::StartScan(TUniqueId id, const CScannableObjectInfo& scanInfo,
|
|||
}
|
||||
state.second->SetTextureID0(bucket.x0_texture, g_SimplePool);
|
||||
state.second->SetFlashFactor(0.f);
|
||||
float startTime = GetDownloadStartTime(i);
|
||||
if (scanTime >= startTime)
|
||||
|
||||
const float startTime = GetDownloadStartTime(i);
|
||||
if (scanTime >= startTime) {
|
||||
x170_paneStates[i].first = 0.f;
|
||||
else
|
||||
} else {
|
||||
x170_paneStates[i].first = -1.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CAssetId strId = x14_scannableInfo->GetStringTableId();
|
||||
if (strId.IsValid())
|
||||
const CAssetId strId = x14_scannableInfo->GetStringTableId();
|
||||
if (strId.IsValid()) {
|
||||
x194_scanStr = g_SimplePool->GetObj({FOURCC('STRG'), strId});
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
int pos = x14_scannableInfo->GetBucket(i).x8_imagePos;
|
||||
for (size_t i = 0; i < CScannableObjectInfo::NumBuckets; ++i) {
|
||||
const u32 pos = x14_scannableInfo->GetBucket(i).x8_imagePos;
|
||||
CDataDot& dot = xbc_dataDots[i];
|
||||
if (pos != -1) {
|
||||
if (pos != UINT32_MAX) {
|
||||
if (GetDownloadStartTime(i) - g_tweakGui->GetScanAppearanceDuration() < scanTime) {
|
||||
dot.SetAlpha(0.f);
|
||||
dot.SetDotState(CDataDot::EDotState::Done);
|
||||
|
@ -243,12 +255,14 @@ void CScanDisplay::StartScan(TUniqueId id, const CScannableObjectInfo& scanInfo,
|
|||
}
|
||||
|
||||
void CScanDisplay::StopScan() {
|
||||
if (xc_state == EScanState::Done || xc_state == EScanState::Inactive)
|
||||
if (xc_state == EScanState::Done || xc_state == EScanState::Inactive) {
|
||||
return;
|
||||
}
|
||||
|
||||
xc_state = EScanState::Done;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
xbc_dataDots[i].SetDesiredAlpha(0.f);
|
||||
for (auto& dataDot : xbc_dataDots) {
|
||||
dataDot.SetDesiredAlpha(0.f);
|
||||
}
|
||||
}
|
||||
|
||||
void CScanDisplay::SetScanMessageTypeEffect(CGuiTextPane* pane, bool type) {
|
||||
|
@ -310,25 +324,30 @@ void CScanDisplay::Update(float dt, float scanningTime) {
|
|||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (x170_paneStates[i].second == nullptr)
|
||||
for (size_t i = 0; i < x170_paneStates.size(); ++i) {
|
||||
if (x170_paneStates[i].second == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (x170_paneStates[i].first > 0.f) {
|
||||
x170_paneStates[i].first = std::max(0.f, x170_paneStates[i].first - dt);
|
||||
float tmp;
|
||||
if (x170_paneStates[i].first > g_tweakGui->GetScanPaneFadeOutTime())
|
||||
if (x170_paneStates[i].first > g_tweakGui->GetScanPaneFadeOutTime()) {
|
||||
tmp = 1.f -
|
||||
(x170_paneStates[i].first - g_tweakGui->GetScanPaneFadeOutTime()) / g_tweakGui->GetScanPaneFadeInTime();
|
||||
else
|
||||
} else {
|
||||
tmp = x170_paneStates[i].first / g_tweakGui->GetScanPaneFadeOutTime();
|
||||
}
|
||||
x170_paneStates[i].second->SetFlashFactor(tmp * g_tweakGui->GetScanPaneFlashFactor() * x1a8_bodyAlpha);
|
||||
}
|
||||
float alphaMul =
|
||||
|
||||
const float alphaMul =
|
||||
((xc_state == EScanState::Downloading) ? GetDownloadFraction(i, scanningTime) : 1.f) * x1a8_bodyAlpha;
|
||||
zeus::CColor color = g_tweakGuiColors->GetScanDisplayImagePaneColor();
|
||||
color.a() *= alphaMul;
|
||||
x170_paneStates[i].second->SetColor(color);
|
||||
x170_paneStates[i].second->SetDeResFactor(1.f - alphaMul);
|
||||
|
||||
if (GetDownloadStartTime(i) - g_tweakGui->GetScanAppearanceDuration() < scanningTime) {
|
||||
CDataDot& dot = xbc_dataDots[i];
|
||||
switch (dot.GetDotState()) {
|
||||
|
@ -338,7 +357,7 @@ void CScanDisplay::Update(float dt, float scanningTime) {
|
|||
dot.StartTransitionTo(zeus::skZero2f, g_tweakGui->GetScanAppearanceDuration());
|
||||
break;
|
||||
case CDataDot::EDotState::RevealPane: {
|
||||
float tmp = dot.GetTransitionFactor();
|
||||
const float tmp = dot.GetTransitionFactor();
|
||||
if (tmp == 0.f) {
|
||||
dot.SetDotState(CDataDot::EDotState::Done);
|
||||
dot.SetDesiredAlpha(0.f);
|
||||
|
@ -353,7 +372,7 @@ void CScanDisplay::Update(float dt, float scanningTime) {
|
|||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
for (size_t i = 0; i < xbc_dataDots.size(); ++i) {
|
||||
CDataDot& dot = xbc_dataDots[i];
|
||||
switch (dot.GetDotState()) {
|
||||
case CDataDot::EDotState::Hidden:
|
||||
|
|
|
@ -79,8 +79,8 @@ private:
|
|||
float x1b0_aPulse = 1.f;
|
||||
bool x1b4_scanComplete = false;
|
||||
|
||||
float GetDownloadStartTime(int idx) const;
|
||||
float GetDownloadFraction(int idx, float scanningTime) const;
|
||||
float GetDownloadStartTime(size_t idx) const;
|
||||
float GetDownloadFraction(size_t idx, float scanningTime) const;
|
||||
static void SetScanMessageTypeEffect(CGuiTextPane* pane, bool type);
|
||||
|
||||
public:
|
||||
|
|
|
@ -27,8 +27,8 @@ class CTextExecuteBuffer {
|
|||
CBlockInstruction* xa0_curBlock = nullptr;
|
||||
CLineInstruction* xa4_curLine = nullptr;
|
||||
InstList::iterator xa8_curWordIt;
|
||||
s32 xac_curY;
|
||||
s32 xb0_curX;
|
||||
s32 xac_curY = 0;
|
||||
s32 xb0_curX = 0;
|
||||
s32 xb4_curWordX = 0;
|
||||
s32 xb8_curWordY = 0;
|
||||
s32 xbc_spaceDistance = 0;
|
||||
|
@ -37,7 +37,7 @@ class CTextExecuteBuffer {
|
|||
u32 xd8_ = 0;
|
||||
|
||||
public:
|
||||
CTextExecuteBuffer() { xa8_curWordIt = x0_instList.begin(); }
|
||||
CTextExecuteBuffer() : xa8_curWordIt{x0_instList.begin()} {}
|
||||
|
||||
CTextRenderBuffer BuildRenderBuffer(CGuiWidget::EGuiModelDrawFlags df) const;
|
||||
CTextRenderBuffer BuildRenderBufferPage(InstList::const_iterator start, InstList::const_iterator pgStart,
|
||||
|
|
|
@ -214,10 +214,11 @@ void CLogBookScreen::UpdateBodyImagesAndText() {
|
|||
pane->SetAnimationParms(zeus::skZero2f, 0.f, 0.f);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
for (size_t i = 0; i < CScannableObjectInfo::NumBuckets; ++i) {
|
||||
const CScannableObjectInfo::SBucket& bucket = scan->GetBucket(i);
|
||||
if (bucket.x8_imagePos == UINT32_MAX)
|
||||
if (bucket.x8_imagePos == UINT32_MAX) {
|
||||
continue;
|
||||
}
|
||||
CAuiImagePane* pane = xf0_imagePanes[bucket.x8_imagePos];
|
||||
if (bucket.x14_interval > 0.f) {
|
||||
pane->SetAnimationParms(zeus::CVector2f(bucket.xc_size.x, bucket.xc_size.y), bucket.x14_interval,
|
||||
|
|
|
@ -536,7 +536,7 @@ void CPauseScreenBase::OnWidgetScroll(CGuiWidget* widget, const boo::SScrollDelt
|
|||
}
|
||||
}
|
||||
|
||||
std::string CPauseScreenBase::GetImagePaneName(u32 i) {
|
||||
std::string CPauseScreenBase::GetImagePaneName(size_t i) {
|
||||
static constexpr std::array PaneSuffixes{
|
||||
"0", "1", "2", "3", "01", "12", "23", "012", "123", "0123",
|
||||
"4", "5", "6", "7", "45", "56", "67", "456", "567", "4567",
|
||||
|
|
|
@ -102,7 +102,7 @@ protected:
|
|||
void OnWidgetScroll(CGuiWidget* widget, const boo::SScrollDelta& delta, int accumX, int accumY);
|
||||
|
||||
public:
|
||||
static std::string GetImagePaneName(u32 i);
|
||||
static std::string GetImagePaneName(size_t i);
|
||||
|
||||
CPauseScreenBase(const CStateManager& mgr, CGuiFrame& frame, const CStringTable& pauseStrg, bool isLogBook = false);
|
||||
|
||||
|
|
|
@ -714,6 +714,7 @@ void CMain::Init(const hecl::Runtime::FileStoreManager& storeMgr, hecl::CVarMana
|
|||
InitializeDiscord();
|
||||
m_mainWindow = window;
|
||||
m_cvarMgr = cvarMgr;
|
||||
m_cvarCommons = std::make_unique<hecl::CVarCommons>(*m_cvarMgr);
|
||||
m_console = std::make_unique<hecl::Console>(m_cvarMgr);
|
||||
m_console->init(window);
|
||||
m_console->registerCommand(
|
||||
|
@ -847,16 +848,16 @@ bool CMain::Proc() {
|
|||
}
|
||||
|
||||
float dt = 1 / 60.f;
|
||||
#if MP1_VARIABLE_DELTA_TIME
|
||||
if (m_cvarCommons->m_variableDt->toBoolean()) {
|
||||
auto now = delta_clock::now();
|
||||
if (m_firstFrame) {
|
||||
m_firstFrame = false;
|
||||
} else {
|
||||
using delta_duration = std::chrono::duration<float, std::ratio<1>>;
|
||||
dt = std::min(std::chrono::duration_cast<delta_duration>(now - m_prevFrameTime).count(), dt);
|
||||
dt = std::min(std::chrono::duration_cast<delta_duration>(now - m_prevFrameTime).count(), 1 / 30.f);
|
||||
}
|
||||
m_prevFrameTime = now;
|
||||
#endif
|
||||
}
|
||||
|
||||
m_console->proc();
|
||||
if (!m_console->isOpen()) {
|
||||
|
|
|
@ -3,9 +3,6 @@
|
|||
#ifndef MP1_USE_BOO
|
||||
#define MP1_USE_BOO 0
|
||||
#endif
|
||||
#ifndef MP1_VARIABLE_DELTA_TIME
|
||||
#define MP1_VARIABLE_DELTA_TIME 1
|
||||
#endif
|
||||
|
||||
#include "Runtime/IMain.hpp"
|
||||
#include "Runtime/MP1/CTweaks.hpp"
|
||||
|
@ -41,6 +38,7 @@
|
|||
#include "DataSpec/DNAMP1/Tweaks/CTweakPlayer.hpp"
|
||||
#include "DataSpec/DNAMP1/Tweaks/CTweakGame.hpp"
|
||||
#include "hecl/Console.hpp"
|
||||
#include "hecl/CVarCommons.hpp"
|
||||
|
||||
struct DiscordUser;
|
||||
|
||||
|
@ -234,6 +232,7 @@ private:
|
|||
boo::IWindow* m_mainWindow = nullptr;
|
||||
|
||||
hecl::CVarManager* m_cvarMgr = nullptr;
|
||||
std::unique_ptr<hecl::CVarCommons> m_cvarCommons;
|
||||
std::unique_ptr<hecl::Console> m_console;
|
||||
// Warmup state
|
||||
std::vector<SObjectTag> m_warmupTags;
|
||||
|
@ -242,11 +241,9 @@ private:
|
|||
bool m_loadedPersistentResources = false;
|
||||
bool m_doQuit = false;
|
||||
|
||||
#if MP1_VARIABLE_DELTA_TIME
|
||||
bool m_firstFrame = true;
|
||||
using delta_clock = std::chrono::high_resolution_clock;
|
||||
std::chrono::time_point<delta_clock> m_prevFrameTime;
|
||||
#endif
|
||||
|
||||
void InitializeSubsystems();
|
||||
static void InitializeDiscord();
|
||||
|
|
|
@ -1136,8 +1136,7 @@ void CElementGen::RenderLines() {
|
|||
|
||||
m_lineRenderer->Reset();
|
||||
|
||||
for (size_t i = 0; i < x30_particles.size(); ++i) {
|
||||
CParticle& particle = x30_particles[i];
|
||||
for (auto& particle : x30_particles) {
|
||||
g_currentParticle = &particle;
|
||||
|
||||
int partFrame = x74_curFrame - particle.x28_startFrame;
|
||||
|
|
|
@ -60,7 +60,7 @@ private:
|
|||
int x70_internalStartFrame = 0;
|
||||
int x74_curFrame = 0;
|
||||
double x78_curSeconds = 0.f;
|
||||
float x80_timeDeltaScale;
|
||||
float x80_timeDeltaScale = 0.f;
|
||||
int x84_prevFrame = -1;
|
||||
bool x88_particleEmission = true;
|
||||
float x8c_generatorRemainder = 0.f;
|
||||
|
|
|
@ -137,7 +137,7 @@ class CIESampleAndHold : public CIntElement {
|
|||
mutable int x8_nextSampleFrame = 0;
|
||||
std::unique_ptr<CIntElement> xc_waitFramesMin;
|
||||
std::unique_ptr<CIntElement> x10_waitFramesMax;
|
||||
mutable int x14_holdVal;
|
||||
mutable int x14_holdVal = 0;
|
||||
|
||||
public:
|
||||
CIESampleAndHold(std::unique_ptr<CIntElement>&& a, std::unique_ptr<CIntElement>&& b, std::unique_ptr<CIntElement>&& c)
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "Runtime/Particle/CParticleElectric.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "Runtime/GameGlobalObjects.hpp"
|
||||
#include "Runtime/Graphics/CBooRenderer.hpp"
|
||||
#include "Runtime/Graphics/CGraphics.hpp"
|
||||
|
@ -31,18 +33,21 @@ CParticleElectric::CParticleElectric(const TToken<CElectricDescription>& token)
|
|||
|
||||
CElectricDescription* desc = x1c_elecDesc.GetObj();
|
||||
|
||||
if (CIntElement* sseg = desc->x10_SSEG.get())
|
||||
if (CIntElement* sseg = desc->x10_SSEG.get()) {
|
||||
sseg->GetValue(x28_currentFrame, x150_SSEG);
|
||||
}
|
||||
|
||||
if (CIntElement* scnt = desc->xc_SCNT.get())
|
||||
if (CIntElement* scnt = desc->xc_SCNT.get()) {
|
||||
scnt->GetValue(x28_currentFrame, x154_SCNT);
|
||||
}
|
||||
|
||||
x154_SCNT = std::min(x154_SCNT, 32);
|
||||
|
||||
if (CIntElement* life = desc->x0_LIFE.get())
|
||||
if (CIntElement* life = desc->x0_LIFE.get()) {
|
||||
life->GetValue(0, x2c_LIFE);
|
||||
else
|
||||
} else {
|
||||
x2c_LIFE = INT_MAX;
|
||||
}
|
||||
|
||||
if (desc->x40_SSWH) {
|
||||
x450_27_haveSSWH = true;
|
||||
|
@ -84,9 +89,10 @@ CParticleElectric::CParticleElectric(const TToken<CElectricDescription>& token)
|
|||
}
|
||||
|
||||
void CParticleElectric::RenderSwooshes() {
|
||||
for (CParticleElectricManager& elec : x3e8_electricManagers)
|
||||
for (const CParticleElectricManager& elec : x3e8_electricManagers) {
|
||||
x1e0_swooshGenerators[elec.x0_idx]->Render();
|
||||
}
|
||||
}
|
||||
|
||||
void CParticleElectric::SetupLineGXMaterial() {
|
||||
// Konst color/alpha 0
|
||||
|
@ -94,18 +100,21 @@ void CParticleElectric::SetupLineGXMaterial() {
|
|||
|
||||
void CParticleElectric::DrawLineStrip(const std::vector<zeus::CVector3f>& verts, float width,
|
||||
const zeus::CColor& color) {
|
||||
size_t useIdx = m_nextLineRenderer;
|
||||
if (++m_nextLineRenderer > m_lineRenderers.size())
|
||||
const size_t useIdx = m_nextLineRenderer;
|
||||
if (++m_nextLineRenderer > m_lineRenderers.size()) {
|
||||
m_lineRenderers.resize(m_nextLineRenderer);
|
||||
if (!m_lineRenderers[useIdx])
|
||||
}
|
||||
if (!m_lineRenderers[useIdx]) {
|
||||
m_lineRenderers[useIdx] =
|
||||
std::make_unique<CLineRenderer>(CLineRenderer::EPrimitiveMode::LineStrip, x150_SSEG, nullptr, true, true);
|
||||
}
|
||||
CLineRenderer& renderer = *m_lineRenderers[useIdx];
|
||||
zeus::CColor useColor = x1b8_moduColor * color;
|
||||
const zeus::CColor useColor = x1b8_moduColor * color;
|
||||
|
||||
renderer.Reset();
|
||||
for (const zeus::CVector3f& vert : verts)
|
||||
for (const zeus::CVector3f& vert : verts) {
|
||||
renderer.AddVertex(vert, useColor, width);
|
||||
}
|
||||
renderer.Render(g_Renderer->IsThermalVisorHotPass());
|
||||
}
|
||||
|
||||
|
@ -122,13 +131,16 @@ void CParticleElectric::RenderLines() {
|
|||
SetupLineGXMaterial();
|
||||
for (CParticleElectricManager& elec : x3e8_electricManagers) {
|
||||
CLineManager& line = *x2e4_lineManagers[elec.x0_idx];
|
||||
if (x1c_elecDesc->x28_LWD1)
|
||||
if (x1c_elecDesc->x28_LWD1) {
|
||||
DrawLineStrip(line.x0_verts, line.x10_widths[0], line.x1c_colors[0]);
|
||||
if (x1c_elecDesc->x2c_LWD2)
|
||||
}
|
||||
if (x1c_elecDesc->x2c_LWD2) {
|
||||
DrawLineStrip(line.x0_verts, line.x10_widths[1], line.x1c_colors[1]);
|
||||
if (x1c_elecDesc->x30_LWD3)
|
||||
}
|
||||
if (x1c_elecDesc->x30_LWD3) {
|
||||
DrawLineStrip(line.x0_verts, line.x10_widths[2], line.x1c_colors[2]);
|
||||
}
|
||||
}
|
||||
|
||||
// Enable culling
|
||||
// Line Width 1
|
||||
|
@ -140,51 +152,61 @@ void CParticleElectric::UpdateCachedTransform() {
|
|||
x450_29_transformDirty = false;
|
||||
}
|
||||
|
||||
void CParticleElectric::UpdateLine(int idx, int frame) {
|
||||
void CParticleElectric::UpdateLine(size_t idx, int frame) {
|
||||
CLineManager& line = *x2e4_lineManagers[idx];
|
||||
|
||||
if (CColorElement* lcl1 = x1c_elecDesc->x34_LCL1.get())
|
||||
if (CColorElement* lcl1 = x1c_elecDesc->x34_LCL1.get()) {
|
||||
lcl1->GetValue(frame, line.x1c_colors[0]);
|
||||
if (CColorElement* lcl2 = x1c_elecDesc->x38_LCL2.get())
|
||||
}
|
||||
if (CColorElement* lcl2 = x1c_elecDesc->x38_LCL2.get()) {
|
||||
lcl2->GetValue(frame, line.x1c_colors[1]);
|
||||
if (CColorElement* lcl3 = x1c_elecDesc->x3c_LCL3.get())
|
||||
}
|
||||
if (CColorElement* lcl3 = x1c_elecDesc->x3c_LCL3.get()) {
|
||||
lcl3->GetValue(frame, line.x1c_colors[2]);
|
||||
}
|
||||
|
||||
if (CRealElement* lwd1 = x1c_elecDesc->x28_LWD1.get())
|
||||
if (CRealElement* lwd1 = x1c_elecDesc->x28_LWD1.get()) {
|
||||
lwd1->GetValue(frame, line.x10_widths[0]);
|
||||
if (CRealElement* lwd2 = x1c_elecDesc->x2c_LWD2.get())
|
||||
}
|
||||
if (CRealElement* lwd2 = x1c_elecDesc->x2c_LWD2.get()) {
|
||||
lwd2->GetValue(frame, line.x10_widths[1]);
|
||||
if (CRealElement* lwd3 = x1c_elecDesc->x30_LWD3.get())
|
||||
}
|
||||
if (CRealElement* lwd3 = x1c_elecDesc->x30_LWD3.get()) {
|
||||
lwd3->GetValue(frame, line.x10_widths[2]);
|
||||
}
|
||||
}
|
||||
|
||||
void CParticleElectric::UpdateElectricalEffects() {
|
||||
for (auto it = x3e8_electricManagers.begin(); it != x3e8_electricManagers.end();) {
|
||||
CParticleElectricManager& elec = *it;
|
||||
if (elec.x4_slif <= 1) {
|
||||
x1bc_allocated[elec.x0_idx] = false;
|
||||
if (elec.x10_gpsmIdx != -1)
|
||||
if (elec.x10_gpsmIdx != -1) {
|
||||
x400_gpsmGenerators[elec.x10_gpsmIdx]->SetParticleEmission(false);
|
||||
if (elec.x14_epsmIdx != -1)
|
||||
}
|
||||
if (elec.x14_epsmIdx != -1) {
|
||||
x410_epsmGenerators[elec.x14_epsmIdx]->SetParticleEmission(false);
|
||||
}
|
||||
it = x3e8_electricManagers.erase(it);
|
||||
continue;
|
||||
}
|
||||
|
||||
CParticleGlobals::instance()->SetParticleLifetime(elec.xc_endFrame - elec.x8_startFrame);
|
||||
int frame = x28_currentFrame - elec.x8_startFrame;
|
||||
CParticleGlobals::instance()->SetParticleLifetime(int(elec.xc_endFrame - elec.x8_startFrame));
|
||||
const int frame = x28_currentFrame - int(elec.x8_startFrame);
|
||||
CParticleGlobals::instance()->UpdateParticleLifetimeTweenValues(frame);
|
||||
|
||||
if (x450_27_haveSSWH) {
|
||||
CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx];
|
||||
zeus::CColor color = zeus::skWhite;
|
||||
if (CColorElement* colr = x1c_elecDesc->x14_COLR.get())
|
||||
if (CColorElement* colr = x1c_elecDesc->x14_COLR.get()) {
|
||||
colr->GetValue(frame, color);
|
||||
}
|
||||
swoosh.SetModulationColor(color * x1b8_moduColor);
|
||||
}
|
||||
|
||||
if (x450_28_haveLWD)
|
||||
if (x450_28_haveLWD) {
|
||||
UpdateLine(elec.x0_idx, frame);
|
||||
}
|
||||
|
||||
elec.x4_slif -= 1;
|
||||
++it;
|
||||
|
@ -192,28 +214,34 @@ void CParticleElectric::UpdateElectricalEffects() {
|
|||
}
|
||||
|
||||
void CParticleElectric::CalculateFractal(int start, int end, float ampl, float ampd) {
|
||||
float tmp = (end - start) / float(x430_fractalMags.size()) * ampl;
|
||||
int storeIdx = (start + end) / 2;
|
||||
const float tmp = float(end - start) / float(x430_fractalMags.size()) * ampl;
|
||||
const int storeIdx = (start + end) / 2;
|
||||
x430_fractalMags[storeIdx] = (x430_fractalMags[start] + x430_fractalMags[end]) * 0.5f + tmp * x14c_randState.Float() -
|
||||
tmp * 0.5f + ampd * x14c_randState.Float() - ampd * 0.5f;
|
||||
if ((start + end) & 1)
|
||||
if (((start + end) & 1) != 0) {
|
||||
x430_fractalMags[end - 1] = x430_fractalMags[end];
|
||||
}
|
||||
|
||||
if (storeIdx - start > 1)
|
||||
if (storeIdx - start > 1) {
|
||||
CalculateFractal(start, storeIdx, ampl, ampd);
|
||||
if (end - storeIdx > 1)
|
||||
}
|
||||
if (end - storeIdx > 1) {
|
||||
CalculateFractal(storeIdx, end, ampl, ampd);
|
||||
}
|
||||
}
|
||||
|
||||
void CParticleElectric::CalculatePoints() {
|
||||
zeus::CVector3f pos, vel;
|
||||
if (CEmitterElement* iemt = x1c_elecDesc->x18_IEMT.get())
|
||||
if (CEmitterElement* iemt = x1c_elecDesc->x18_IEMT.get()) {
|
||||
iemt->GetValue(x28_currentFrame, pos, vel);
|
||||
}
|
||||
|
||||
if (x178_overrideIPos)
|
||||
if (x178_overrideIPos) {
|
||||
pos = *x178_overrideIPos;
|
||||
if (x188_overrideIVel)
|
||||
}
|
||||
if (x188_overrideIVel) {
|
||||
vel = *x188_overrideIVel;
|
||||
}
|
||||
|
||||
rstl::reserved_vector<zeus::CVector3f, 4> points;
|
||||
|
||||
|
@ -227,13 +255,16 @@ void CParticleElectric::CalculatePoints() {
|
|||
|
||||
zeus::CVector3f fpos = zeus::skForward;
|
||||
zeus::CVector3f fvel;
|
||||
if (CEmitterElement* femt = x1c_elecDesc->x1c_FEMT.get())
|
||||
if (CEmitterElement* femt = x1c_elecDesc->x1c_FEMT.get()) {
|
||||
femt->GetValue(x28_currentFrame, fpos, fvel);
|
||||
}
|
||||
|
||||
if (x198_overrideFPos)
|
||||
if (x198_overrideFPos) {
|
||||
fpos = *x198_overrideFPos;
|
||||
if (x1a8_overrideFVel)
|
||||
}
|
||||
if (x1a8_overrideFVel) {
|
||||
fvel = *x1a8_overrideFVel;
|
||||
}
|
||||
|
||||
if (!fvel.isZero()) {
|
||||
if (points.size() == 3) {
|
||||
|
@ -249,21 +280,21 @@ void CParticleElectric::CalculatePoints() {
|
|||
}
|
||||
|
||||
if (points.size() == 4) {
|
||||
int segs = x150_SSEG - 1;
|
||||
float segDiv = 1.f / float(segs);
|
||||
const int segs = x150_SSEG - 1;
|
||||
const float segDiv = 1.f / float(segs);
|
||||
float curDiv = segDiv;
|
||||
for (int i = 1; i < segs; ++i) {
|
||||
float t = segDiv * x14c_randState.Range(-0.45f, 0.45f) + curDiv;
|
||||
const float t = segDiv * x14c_randState.Range(-0.45f, 0.45f) + curDiv;
|
||||
x420_calculatedVerts[i] = zeus::getBezierPoint(points[0], points[1], points[2], points[3], t);
|
||||
curDiv += segDiv;
|
||||
}
|
||||
x420_calculatedVerts[segs] = points[3];
|
||||
} else {
|
||||
x420_calculatedVerts[0] = pos;
|
||||
int segs = x150_SSEG - 1;
|
||||
float segDiv = 1.f / float(segs);
|
||||
const int segs = x150_SSEG - 1;
|
||||
const float segDiv = 1.f / float(segs);
|
||||
zeus::CVector3f accum = x420_calculatedVerts[0];
|
||||
zeus::CVector3f segDelta = (fpos - pos) * segDiv;
|
||||
const zeus::CVector3f segDelta = (fpos - pos) * segDiv;
|
||||
for (int i = 1; i < segs; ++i) {
|
||||
float r = x14c_randState.Range(-0.45f, 0.45f);
|
||||
x420_calculatedVerts[i] = segDelta * r + accum;
|
||||
|
@ -272,8 +303,9 @@ void CParticleElectric::CalculatePoints() {
|
|||
x420_calculatedVerts[segs] = fpos;
|
||||
}
|
||||
|
||||
for (int i = 0; i < x150_SSEG; ++i)
|
||||
for (int i = 0; i < x150_SSEG; ++i) {
|
||||
x430_fractalMags[i] = 0.f;
|
||||
}
|
||||
|
||||
float amplVal = 1.f;
|
||||
if (CRealElement* ampl = x1c_elecDesc->x20_AMPL.get()) {
|
||||
|
@ -282,8 +314,9 @@ void CParticleElectric::CalculatePoints() {
|
|||
}
|
||||
|
||||
float ampdVal = 0.f;
|
||||
if (CRealElement* ampd = x1c_elecDesc->x24_AMPD.get())
|
||||
if (CRealElement* ampd = x1c_elecDesc->x24_AMPD.get()) {
|
||||
ampd->GetValue(x28_currentFrame, ampdVal);
|
||||
}
|
||||
|
||||
CalculateFractal(0, x420_calculatedVerts.size() - 1, amplVal, ampdVal);
|
||||
|
||||
|
@ -294,55 +327,63 @@ void CParticleElectric::CalculatePoints() {
|
|||
v0.normalize();
|
||||
v1.normalize();
|
||||
float dot = v0.dot(v1);
|
||||
if (dot < 0)
|
||||
if (dot < 0) {
|
||||
dot = -dot;
|
||||
if (std::fabs(dot - 1.f) < 0.00001f)
|
||||
}
|
||||
if (std::fabs(dot - 1.f) < 0.00001f) {
|
||||
upVec = zeus::lookAt(x420_calculatedVerts[0], x420_calculatedVerts[1]).basis[2];
|
||||
else
|
||||
} else {
|
||||
upVec = v0.cross(v1).normalized();
|
||||
}
|
||||
} else if (x420_calculatedVerts[0] != x420_calculatedVerts[1]) {
|
||||
upVec = zeus::lookAt(x420_calculatedVerts[0], x420_calculatedVerts[1]).basis[2];
|
||||
}
|
||||
|
||||
float commonRand = x14c_randState.Range(0.f, 360.f);
|
||||
const float commonRand = x14c_randState.Range(0.f, 360.f);
|
||||
|
||||
for (int i = 1; i < x420_calculatedVerts.size() - 1; ++i) {
|
||||
zeus::CVector3f delta = x420_calculatedVerts[i] - x420_calculatedVerts[i - 1];
|
||||
for (size_t i = 1; i < x420_calculatedVerts.size() - 1; ++i) {
|
||||
const zeus::CVector3f delta = x420_calculatedVerts[i] - x420_calculatedVerts[i - 1];
|
||||
if (!delta.isZero()) {
|
||||
zeus::CRelAngle angle =
|
||||
const zeus::CRelAngle angle =
|
||||
zeus::degToRad(x430_fractalMags[i] / amplVal * 16.f * x14c_randState.Range(-1.f, 1.f) + commonRand);
|
||||
x440_fractalOffsets[i] = zeus::CQuaternion::fromAxisAngle(delta, angle).transform(x430_fractalMags[i] * upVec);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 1; i < x420_calculatedVerts.size() - 1; ++i)
|
||||
for (size_t i = 1; i < x420_calculatedVerts.size() - 1; ++i) {
|
||||
x420_calculatedVerts[i] += x440_fractalOffsets[i];
|
||||
}
|
||||
|
||||
if (x1c_elecDesc->x70_ZERY)
|
||||
for (int i = 0; i < x420_calculatedVerts.size(); ++i)
|
||||
x420_calculatedVerts[i].y() = 0.f;
|
||||
if (x1c_elecDesc->x70_ZERY) {
|
||||
for (auto& calculatedVert : x420_calculatedVerts) {
|
||||
calculatedVert.y() = 0.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CParticleElectric::CreateNewParticles(int count) {
|
||||
int allocIdx = 0;
|
||||
for (int i = 0; i < count; ++i) {
|
||||
if (x3e8_electricManagers.size() < x154_SCNT) {
|
||||
zeus::CTransform cachedRot = xf8_cachedXf.getRotation();
|
||||
size_t allocIdx = 0;
|
||||
|
||||
int toAdd = x1bc_allocated.size() - allocIdx;
|
||||
for (int j = 0; j < toAdd; ++j, ++allocIdx) {
|
||||
if (x1bc_allocated[allocIdx])
|
||||
for (int i = 0; i < count; ++i) {
|
||||
if (x3e8_electricManagers.size() < size_t(x154_SCNT)) {
|
||||
const zeus::CTransform cachedRot = xf8_cachedXf.getRotation();
|
||||
|
||||
const size_t toAdd = x1bc_allocated.size() - allocIdx;
|
||||
for (size_t j = 0; j < toAdd; ++j, ++allocIdx) {
|
||||
if (x1bc_allocated[allocIdx]) {
|
||||
continue;
|
||||
}
|
||||
x1bc_allocated[allocIdx] = true;
|
||||
|
||||
int lifetime = 1;
|
||||
if (CIntElement* slif = x1c_elecDesc->x4_SLIF.get())
|
||||
if (CIntElement* slif = x1c_elecDesc->x4_SLIF.get()) {
|
||||
slif->GetValue(x28_currentFrame, lifetime);
|
||||
}
|
||||
|
||||
x3e8_electricManagers.emplace_back(allocIdx, lifetime, x28_currentFrame);
|
||||
CParticleElectricManager& elec = x3e8_electricManagers.back();
|
||||
CParticleGlobals::instance()->SetParticleLifetime(elec.xc_endFrame - elec.x8_startFrame);
|
||||
int frame = x28_currentFrame - elec.x8_startFrame;
|
||||
const int frame = x28_currentFrame - int(elec.x8_startFrame);
|
||||
CParticleGlobals::instance()->UpdateParticleLifetimeTweenValues(frame);
|
||||
CalculatePoints();
|
||||
|
||||
|
@ -354,8 +395,9 @@ void CParticleElectric::CreateNewParticles(int count) {
|
|||
swoosh.SetGlobalScale(xe0_globalScale);
|
||||
swoosh.SetLocalScale(xec_localScale);
|
||||
zeus::CColor color = zeus::skWhite;
|
||||
if (CColorElement* colr = x1c_elecDesc->x14_COLR.get())
|
||||
if (CColorElement* colr = x1c_elecDesc->x14_COLR.get()) {
|
||||
colr->GetValue(frame, color);
|
||||
}
|
||||
swoosh.SetModulationColor(color * x1b8_moduColor);
|
||||
swoosh.DoElectricCreate(x420_calculatedVerts);
|
||||
}
|
||||
|
@ -366,8 +408,9 @@ void CParticleElectric::CreateNewParticles(int count) {
|
|||
UpdateLine(allocIdx, 0);
|
||||
if (x450_27_haveSSWH) {
|
||||
x130_buildBounds = zeus::CAABox();
|
||||
for (const zeus::CVector3f& vec : x420_calculatedVerts)
|
||||
for (const zeus::CVector3f& vec : x420_calculatedVerts) {
|
||||
x130_buildBounds.accumulateBounds(vec);
|
||||
}
|
||||
line.x28_aabb = x130_buildBounds;
|
||||
}
|
||||
}
|
||||
|
@ -376,7 +419,7 @@ void CParticleElectric::CreateNewParticles(int count) {
|
|||
for (int k = 0; k < x154_SCNT; ++k) {
|
||||
CElementGen& gen = *x400_gpsmGenerators[k];
|
||||
if (!gen.GetParticleEmission()) {
|
||||
zeus::CTransform scale =
|
||||
const zeus::CTransform scale =
|
||||
zeus::CTransform::Scale(xe0_globalScale) * zeus::CTransform::Scale(xec_localScale);
|
||||
gen.SetTranslation(scale * x420_calculatedVerts.front());
|
||||
gen.SetParticleEmission(true);
|
||||
|
@ -390,7 +433,7 @@ void CParticleElectric::CreateNewParticles(int count) {
|
|||
for (int k = 0; k < x154_SCNT; ++k) {
|
||||
CElementGen& gen = *x410_epsmGenerators[k];
|
||||
if (!gen.GetParticleEmission()) {
|
||||
zeus::CTransform scale =
|
||||
const zeus::CTransform scale =
|
||||
zeus::CTransform::Scale(xe0_globalScale) * zeus::CTransform::Scale(xec_localScale);
|
||||
gen.SetTranslation(scale * x420_calculatedVerts.back());
|
||||
gen.SetParticleEmission(true);
|
||||
|
@ -411,8 +454,7 @@ void CParticleElectric::AddElectricalEffects() {
|
|||
if (CRealElement* grat = x1c_elecDesc->x8_GRAT.get()) {
|
||||
if (grat->GetValue(x28_currentFrame, genRate)) {
|
||||
x3e8_electricManagers.clear();
|
||||
for (int i = 0; i < x1bc_allocated.size(); ++i)
|
||||
x1bc_allocated[i] = false;
|
||||
std::fill(x1bc_allocated.begin(), x1bc_allocated.end(), false);
|
||||
return;
|
||||
} else {
|
||||
genRate = std::max(0.f, genRate);
|
||||
|
@ -420,9 +462,9 @@ void CParticleElectric::AddElectricalEffects() {
|
|||
}
|
||||
|
||||
x15c_genRem += genRate;
|
||||
int partCount = std::floor(x15c_genRem);
|
||||
const float partCount = std::floor(x15c_genRem);
|
||||
x15c_genRem -= partCount;
|
||||
CreateNewParticles(partCount);
|
||||
CreateNewParticles(int(partCount));
|
||||
}
|
||||
|
||||
void CParticleElectric::BuildBounds() {
|
||||
|
@ -434,14 +476,15 @@ void CParticleElectric::BuildBounds() {
|
|||
x160_systemBounds = zeus::CAABox();
|
||||
|
||||
if (x450_27_haveSSWH) {
|
||||
for (CParticleElectricManager& elec : x3e8_electricManagers) {
|
||||
CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx];
|
||||
if (auto bounds = swoosh.GetBounds())
|
||||
for (const CParticleElectricManager& elec : x3e8_electricManagers) {
|
||||
const CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx];
|
||||
if (const auto bounds = swoosh.GetBounds()) {
|
||||
x160_systemBounds.accumulateBounds(*bounds);
|
||||
}
|
||||
}
|
||||
} else if (x450_28_haveLWD) {
|
||||
zeus::CAABox tmp = zeus::CAABox();
|
||||
for (CParticleElectricManager& elec : x3e8_electricManagers) {
|
||||
for (const CParticleElectricManager& elec : x3e8_electricManagers) {
|
||||
CLineManager& line = *x2e4_lineManagers[elec.x0_idx];
|
||||
tmp.accumulateBounds(line.x28_aabb);
|
||||
}
|
||||
|
@ -453,44 +496,52 @@ void CParticleElectric::BuildBounds() {
|
|||
}
|
||||
|
||||
if (x450_25_haveGPSM) {
|
||||
for (int i = 0; i < x154_SCNT; ++i)
|
||||
if (auto bounds = x400_gpsmGenerators[i]->GetBounds())
|
||||
for (int i = 0; i < x154_SCNT; ++i) {
|
||||
if (auto bounds = x400_gpsmGenerators[i]->GetBounds()) {
|
||||
x160_systemBounds.accumulateBounds(*bounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (x450_26_haveEPSM) {
|
||||
for (int i = 0; i < x154_SCNT; ++i)
|
||||
if (auto bounds = x410_epsmGenerators[i]->GetBounds())
|
||||
for (int i = 0; i < x154_SCNT; ++i) {
|
||||
if (auto bounds = x410_epsmGenerators[i]->GetBounds()) {
|
||||
x160_systemBounds.accumulateBounds(*bounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CParticleElectric::Update(double dt) {
|
||||
CGlobalRandom gr(x14c_randState);
|
||||
[[maybe_unused]] CGlobalRandom gr(x14c_randState);
|
||||
bool ret = false;
|
||||
|
||||
if (x450_25_haveGPSM) {
|
||||
for (int i = 0; i < x154_SCNT; ++i)
|
||||
if (!x400_gpsmGenerators[i]->IsSystemDeletable())
|
||||
for (int i = 0; i < x154_SCNT; ++i) {
|
||||
if (!x400_gpsmGenerators[i]->IsSystemDeletable()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (x450_26_haveEPSM) {
|
||||
for (int i = 0; i < x154_SCNT; ++i)
|
||||
if (!x410_epsmGenerators[i]->IsSystemDeletable())
|
||||
for (int i = 0; i < x154_SCNT; ++i) {
|
||||
if (!x410_epsmGenerators[i]->IsSystemDeletable()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool emitting = x450_24_emitting && x28_currentFrame < x2c_LIFE;
|
||||
const bool emitting = x450_24_emitting && x28_currentFrame < x2c_LIFE;
|
||||
|
||||
double evalTime = x28_currentFrame / 60.0;
|
||||
x30_curTime += dt;
|
||||
|
||||
if (x450_29_transformDirty) {
|
||||
UpdateCachedTransform();
|
||||
zeus::CTransform globalOrient = xf8_cachedXf.getRotation();
|
||||
const zeus::CTransform globalOrient = xf8_cachedXf.getRotation();
|
||||
if (x450_27_haveSSWH) {
|
||||
for (CParticleElectricManager& elec : x3e8_electricManagers) {
|
||||
for (const CParticleElectricManager& elec : x3e8_electricManagers) {
|
||||
CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx];
|
||||
swoosh.SetGlobalTranslation(xf8_cachedXf.origin);
|
||||
swoosh.SetGlobalOrientation(globalOrient);
|
||||
|
@ -500,7 +551,7 @@ bool CParticleElectric::Update(double dt) {
|
|||
}
|
||||
|
||||
if (x450_25_haveGPSM) {
|
||||
for (CParticleElectricManager& elec : x3e8_electricManagers) {
|
||||
for (const CParticleElectricManager& elec : x3e8_electricManagers) {
|
||||
CElementGen& gen = *x400_gpsmGenerators[elec.x0_idx];
|
||||
gen.SetGlobalTranslation(xf8_cachedXf.origin);
|
||||
gen.SetGlobalOrientation(globalOrient);
|
||||
|
@ -510,7 +561,7 @@ bool CParticleElectric::Update(double dt) {
|
|||
}
|
||||
|
||||
if (x450_26_haveEPSM) {
|
||||
for (CParticleElectricManager& elec : x3e8_electricManagers) {
|
||||
for (const CParticleElectricManager& elec : x3e8_electricManagers) {
|
||||
CElementGen& gen = *x410_epsmGenerators[elec.x0_idx];
|
||||
gen.SetGlobalTranslation(xf8_cachedXf.origin);
|
||||
gen.SetGlobalOrientation(globalOrient);
|
||||
|
@ -529,28 +580,35 @@ bool CParticleElectric::Update(double dt) {
|
|||
AddElectricalEffects();
|
||||
|
||||
if (x450_25_haveGPSM) {
|
||||
if (x28_currentFrame >= x2c_LIFE)
|
||||
for (int i = 0; i < x154_SCNT; ++i)
|
||||
if (x28_currentFrame >= x2c_LIFE) {
|
||||
for (int i = 0; i < x154_SCNT; ++i) {
|
||||
x400_gpsmGenerators[i]->EndLifetime();
|
||||
for (int i = 0; i < x154_SCNT; ++i)
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < x154_SCNT; ++i) {
|
||||
x400_gpsmGenerators[i]->Update(1.0 / 60.0);
|
||||
}
|
||||
}
|
||||
|
||||
if (x450_26_haveEPSM) {
|
||||
if (x28_currentFrame >= x2c_LIFE)
|
||||
for (int i = 0; i < x154_SCNT; ++i)
|
||||
if (x28_currentFrame >= x2c_LIFE) {
|
||||
for (int i = 0; i < x154_SCNT; ++i) {
|
||||
x410_epsmGenerators[i]->EndLifetime();
|
||||
for (int i = 0; i < x154_SCNT; ++i)
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < x154_SCNT; ++i) {
|
||||
x410_epsmGenerators[i]->Update(1.0 / 60.0);
|
||||
}
|
||||
}
|
||||
|
||||
ret = true;
|
||||
evalTime += (1.0 / 60.0);
|
||||
x28_currentFrame += 1;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
if (ret) {
|
||||
BuildBounds();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -559,25 +617,30 @@ void CParticleElectric::Render(const CActorLights* lights) {
|
|||
SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(FMT_STRING("CParticleElectric::Render {}"),
|
||||
*x1c_elecDesc.GetObjectTag()).c_str(), zeus::skYellow);
|
||||
|
||||
if (x3e8_electricManagers.size()) {
|
||||
if (x450_29_transformDirty)
|
||||
if (!x3e8_electricManagers.empty()) {
|
||||
if (x450_29_transformDirty) {
|
||||
UpdateCachedTransform();
|
||||
if (x450_27_haveSSWH)
|
||||
}
|
||||
if (x450_27_haveSSWH) {
|
||||
RenderSwooshes();
|
||||
if (x450_28_haveLWD)
|
||||
}
|
||||
if (x450_28_haveLWD) {
|
||||
RenderLines();
|
||||
}
|
||||
}
|
||||
|
||||
if (x450_25_haveGPSM) {
|
||||
for (int i = 0; i < x154_SCNT; ++i)
|
||||
for (int i = 0; i < x154_SCNT; ++i) {
|
||||
x400_gpsmGenerators[i]->Render(lights);
|
||||
}
|
||||
}
|
||||
|
||||
if (x450_26_haveEPSM) {
|
||||
for (int i = 0; i < x154_SCNT; ++i)
|
||||
for (int i = 0; i < x154_SCNT; ++i) {
|
||||
x410_epsmGenerators[i]->Render(lights);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CParticleElectric::SetOrientation(const zeus::CTransform& orientation) {
|
||||
x44_orientation = orientation;
|
||||
|
@ -595,44 +658,48 @@ void CParticleElectric::SetGlobalOrientation(const zeus::CTransform& orientation
|
|||
x450_29_transformDirty = true;
|
||||
|
||||
if (x450_27_haveSSWH) {
|
||||
for (CParticleElectricManager& elec : x3e8_electricManagers) {
|
||||
for (const CParticleElectricManager& elec : x3e8_electricManagers) {
|
||||
CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx];
|
||||
swoosh.SetGlobalOrientation(xb0_globalOrientation);
|
||||
}
|
||||
}
|
||||
|
||||
if (x450_25_haveGPSM) {
|
||||
for (int i = 0; i < x154_SCNT; ++i)
|
||||
for (int i = 0; i < x154_SCNT; ++i) {
|
||||
x400_gpsmGenerators[i]->SetGlobalOrientation(xb0_globalOrientation);
|
||||
}
|
||||
}
|
||||
|
||||
if (x450_26_haveEPSM) {
|
||||
for (int i = 0; i < x154_SCNT; ++i)
|
||||
for (int i = 0; i < x154_SCNT; ++i) {
|
||||
x410_epsmGenerators[i]->SetGlobalOrientation(xb0_globalOrientation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CParticleElectric::SetGlobalTranslation(const zeus::CVector3f& translation) {
|
||||
xa4_globalTranslation = translation;
|
||||
x450_29_transformDirty = true;
|
||||
|
||||
if (x450_27_haveSSWH) {
|
||||
for (CParticleElectricManager& elec : x3e8_electricManagers) {
|
||||
for (const CParticleElectricManager& elec : x3e8_electricManagers) {
|
||||
CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx];
|
||||
swoosh.SetGlobalTranslation(xa4_globalTranslation);
|
||||
}
|
||||
}
|
||||
|
||||
if (x450_25_haveGPSM) {
|
||||
for (int i = 0; i < x154_SCNT; ++i)
|
||||
for (int i = 0; i < x154_SCNT; ++i) {
|
||||
x400_gpsmGenerators[i]->SetGlobalTranslation(xa4_globalTranslation);
|
||||
}
|
||||
}
|
||||
|
||||
if (x450_26_haveEPSM) {
|
||||
for (int i = 0; i < x154_SCNT; ++i)
|
||||
for (int i = 0; i < x154_SCNT; ++i) {
|
||||
x410_epsmGenerators[i]->SetGlobalTranslation(xa4_globalTranslation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CParticleElectric::SetGlobalScale(const zeus::CVector3f& scale) {
|
||||
xe0_globalScale = scale;
|
||||
|
@ -644,22 +711,24 @@ void CParticleElectric::SetLocalScale(const zeus::CVector3f& scale) {
|
|||
x450_29_transformDirty = true;
|
||||
|
||||
if (x450_27_haveSSWH) {
|
||||
for (CParticleElectricManager& elec : x3e8_electricManagers) {
|
||||
for (const CParticleElectricManager& elec : x3e8_electricManagers) {
|
||||
CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx];
|
||||
swoosh.SetLocalScale(xec_localScale);
|
||||
}
|
||||
}
|
||||
|
||||
if (x450_25_haveGPSM) {
|
||||
for (int i = 0; i < x154_SCNT; ++i)
|
||||
for (int i = 0; i < x154_SCNT; ++i) {
|
||||
x400_gpsmGenerators[i]->SetLocalScale(xec_localScale);
|
||||
}
|
||||
}
|
||||
|
||||
if (x450_26_haveEPSM) {
|
||||
for (int i = 0; i < x154_SCNT; ++i)
|
||||
for (int i = 0; i < x154_SCNT; ++i) {
|
||||
x410_epsmGenerators[i]->SetLocalScale(xec_localScale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CParticleElectric::SetParticleEmission(bool emitting) { x450_24_emitting = emitting; }
|
||||
|
||||
|
@ -678,24 +747,30 @@ const zeus::CVector3f& CParticleElectric::GetGlobalScale() const { return xe0_gl
|
|||
const zeus::CColor& CParticleElectric::GetModulationColor() const { return x1b8_moduColor; }
|
||||
|
||||
bool CParticleElectric::IsSystemDeletable() const {
|
||||
if (x450_24_emitting && x28_currentFrame < x2c_LIFE)
|
||||
return false;
|
||||
|
||||
if (x3e8_electricManagers.size())
|
||||
return false;
|
||||
|
||||
if (x450_25_haveGPSM) {
|
||||
for (int i = 0; i < x154_SCNT; ++i)
|
||||
if (!x400_gpsmGenerators[i]->IsSystemDeletable())
|
||||
if (x450_24_emitting && x28_currentFrame < x2c_LIFE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (x450_26_haveEPSM) {
|
||||
for (int i = 0; i < x154_SCNT; ++i)
|
||||
if (!x410_epsmGenerators[i]->IsSystemDeletable())
|
||||
if (!x3e8_electricManagers.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (x450_25_haveGPSM) {
|
||||
for (int i = 0; i < x154_SCNT; ++i) {
|
||||
if (!x400_gpsmGenerators[i]->IsSystemDeletable()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (x450_26_haveEPSM) {
|
||||
for (int i = 0; i < x154_SCNT; ++i) {
|
||||
if (!x410_epsmGenerators[i]->IsSystemDeletable()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -711,38 +786,46 @@ u32 CParticleElectric::GetParticleCount() const {
|
|||
u32 ret = 0;
|
||||
|
||||
for (const CParticleElectricManager& elec : x3e8_electricManagers) {
|
||||
if (x450_27_haveSSWH)
|
||||
if (x450_27_haveSSWH) {
|
||||
ret += x1e0_swooshGenerators[elec.x0_idx]->GetParticleCount();
|
||||
if (x450_28_haveLWD)
|
||||
}
|
||||
if (x450_28_haveLWD) {
|
||||
ret += x150_SSEG;
|
||||
}
|
||||
}
|
||||
|
||||
if (x450_25_haveGPSM) {
|
||||
for (int i = 0; i < x154_SCNT; ++i)
|
||||
for (int i = 0; i < x154_SCNT; ++i) {
|
||||
ret += x400_gpsmGenerators[i]->GetParticleCount();
|
||||
}
|
||||
}
|
||||
|
||||
if (x450_26_haveEPSM) {
|
||||
for (int i = 0; i < x154_SCNT; ++i)
|
||||
for (int i = 0; i < x154_SCNT; ++i) {
|
||||
ret += x410_epsmGenerators[i]->GetParticleCount();
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CParticleElectric::SystemHasLight() const {
|
||||
if (x450_25_haveGPSM)
|
||||
if (x450_25_haveGPSM) {
|
||||
return x400_gpsmGenerators.front()->SystemHasLight();
|
||||
else if (x450_26_haveEPSM)
|
||||
}
|
||||
if (x450_26_haveEPSM) {
|
||||
return x410_epsmGenerators.front()->SystemHasLight();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CLight CParticleElectric::GetLight() const {
|
||||
if (x450_25_haveGPSM)
|
||||
if (x450_25_haveGPSM) {
|
||||
return x400_gpsmGenerators.front()->GetLight();
|
||||
else if (x450_26_haveEPSM)
|
||||
}
|
||||
if (x450_26_haveEPSM) {
|
||||
return x410_epsmGenerators.front()->GetLight();
|
||||
}
|
||||
return CLight::BuildLocalAmbient(GetGlobalTranslation(), zeus::skOrange);
|
||||
}
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ private:
|
|||
void RenderLines();
|
||||
void RenderSwooshes();
|
||||
void UpdateCachedTransform();
|
||||
void UpdateLine(int idx, int frame);
|
||||
void UpdateLine(size_t idx, int frame);
|
||||
void UpdateElectricalEffects();
|
||||
void CalculateFractal(int start, int end, float ampl, float ampd);
|
||||
void CalculatePoints();
|
||||
|
|
|
@ -21,24 +21,24 @@ public:
|
|||
float m_EmitterTimeReal = 0.f;
|
||||
void SetEmitterTime(int frame) {
|
||||
m_EmitterTime = frame;
|
||||
m_EmitterTimeReal = frame;
|
||||
m_EmitterTimeReal = float(frame);
|
||||
}
|
||||
|
||||
int m_ParticleLifetime = 0;
|
||||
float m_ParticleLifetimeReal = 0.f;
|
||||
void SetParticleLifetime(int frame) {
|
||||
m_ParticleLifetime = frame;
|
||||
m_ParticleLifetimeReal = frame;
|
||||
m_ParticleLifetimeReal = float(frame);
|
||||
}
|
||||
|
||||
int m_ParticleLifetimePercentage = 0;
|
||||
float m_ParticleLifetimePercentageReal = 0.f;
|
||||
float m_ParticleLifetimePercentageRemainder = 0.f;
|
||||
void UpdateParticleLifetimeTweenValues(int frame) {
|
||||
float lt = m_ParticleLifetime != 0.0f ? m_ParticleLifetime : 1.0f;
|
||||
m_ParticleLifetimePercentageReal = 100.0f * frame / lt;
|
||||
const float lt = m_ParticleLifetime != 0 ? float(m_ParticleLifetime) : 1.0f;
|
||||
m_ParticleLifetimePercentageReal = 100.0f * float(frame) / lt;
|
||||
m_ParticleLifetimePercentage = int(m_ParticleLifetimePercentageReal);
|
||||
m_ParticleLifetimePercentageRemainder = m_ParticleLifetimePercentageReal - m_ParticleLifetimePercentage;
|
||||
m_ParticleLifetimePercentageRemainder = m_ParticleLifetimePercentageReal - float(m_ParticleLifetimePercentage);
|
||||
m_ParticleLifetimePercentage = zeus::clamp(0, m_ParticleLifetimePercentage, 100);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,38 +28,43 @@ CParticleSwoosh::CParticleSwoosh(const TToken<CSwooshDescription>& desc, int len
|
|||
, x1d1_24_constantUv(false) {
|
||||
++g_ParticleSystemAliveCount;
|
||||
|
||||
if (leng > 0)
|
||||
if (leng > 0) {
|
||||
x1b4_LENG = leng;
|
||||
else if (CIntElement* leng = x1c_desc->x10_LENG.get())
|
||||
leng->GetValue(0, x1b4_LENG);
|
||||
} else if (CIntElement* lengElement = x1c_desc->x10_LENG.get()) {
|
||||
lengElement->GetValue(0, x1b4_LENG);
|
||||
}
|
||||
x1b4_LENG += 1;
|
||||
|
||||
if (CIntElement* side = x1c_desc->x18_SIDE.get())
|
||||
if (CIntElement* side = x1c_desc->x18_SIDE.get()) {
|
||||
side->GetValue(0, x1b8_SIDE);
|
||||
}
|
||||
|
||||
x1d0_28_LLRD = x1c_desc->x44_24_LLRD;
|
||||
x1d0_29_VLS1 = x1c_desc->x44_26_VLS1;
|
||||
x1d0_30_VLS2 = x1c_desc->x44_27_VLS2;
|
||||
|
||||
if (IsValid()) {
|
||||
if (CIntElement* pslt = x1c_desc->x0_PSLT.get())
|
||||
if (CIntElement* pslt = x1c_desc->x0_PSLT.get()) {
|
||||
pslt->GetValue(0, x2c_PSLT);
|
||||
else
|
||||
} else {
|
||||
x2c_PSLT = INT_MAX;
|
||||
}
|
||||
|
||||
x1d0_25_AALP = x1c_desc->x44_31_AALP;
|
||||
|
||||
if (CIntElement* spln = x1c_desc->x38_SPLN.get())
|
||||
if (CIntElement* spln = x1c_desc->x38_SPLN.get()) {
|
||||
spln->GetValue(0, x1b0_SPLN);
|
||||
if (x1b0_SPLN < 0)
|
||||
}
|
||||
if (x1b0_SPLN < 0) {
|
||||
x1b0_SPLN = 0;
|
||||
}
|
||||
|
||||
x15c_swooshes.clear();
|
||||
x15c_swooshes.reserve(x1b4_LENG);
|
||||
for (int i = 0; i < x1b4_LENG; ++i)
|
||||
x15c_swooshes.emplace_back(zeus::skZero3f, zeus::skZero3f, 0.f, 0.f, 0, false,
|
||||
zeus::CTransform(), zeus::skZero3f, 0.f, 0.f,
|
||||
zeus::skClear);
|
||||
for (int i = 0; i < x1b4_LENG; ++i) {
|
||||
x15c_swooshes.emplace_back(zeus::skZero3f, zeus::skZero3f, 0.f, 0.f, 0, false, zeus::CTransform(), zeus::skZero3f,
|
||||
0.f, 0.f, zeus::skClear);
|
||||
}
|
||||
|
||||
SetOrientation(zeus::CTransform());
|
||||
|
||||
|
@ -69,11 +74,11 @@ CParticleSwoosh::CParticleSwoosh(const TToken<CSwooshDescription>& desc, int len
|
|||
x19c_p3.resize(x1b8_SIDE);
|
||||
|
||||
if (x1c_desc->x44_29_WIRE) {
|
||||
int maxVerts = x1b4_LENG * (x1b0_SPLN + 1) * x1b8_SIDE * 12;
|
||||
const int maxVerts = x1b4_LENG * (x1b0_SPLN + 1) * x1b8_SIDE * 12;
|
||||
m_lineRenderer.reset(
|
||||
new CLineRenderer(CLineRenderer::EPrimitiveMode::Lines, maxVerts * 2, nullptr, x1d0_25_AALP));
|
||||
} else {
|
||||
int maxVerts = x1b4_LENG * (x1b0_SPLN + 1) * x1b8_SIDE * 4;
|
||||
const auto maxVerts = size_t(x1b4_LENG * (x1b0_SPLN + 1) * x1b8_SIDE * 4);
|
||||
m_cachedVerts.reserve(maxVerts);
|
||||
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
|
||||
m_vertBuf = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(CParticleSwooshShaders::Vert), maxVerts);
|
||||
|
@ -133,15 +138,17 @@ void CParticleSwoosh::UpdateTranslationAndOrientation() {
|
|||
swoosh.x68_frame = x28_curFrame - swoosh.x70_startFrame;
|
||||
CParticleGlobals::instance()->UpdateParticleLifetimeTweenValues(swoosh.x68_frame);
|
||||
if (x1c_desc->x44_28_SROT) {
|
||||
if (CRealElement* irot = x1c_desc->x1c_IROT.get())
|
||||
if (CRealElement* irot = x1c_desc->x1c_IROT.get()) {
|
||||
irot->GetValue(x28_curFrame, swoosh.x30_irot);
|
||||
}
|
||||
swoosh.x34_rotm = 0.f;
|
||||
} else {
|
||||
if (CRealElement* rotm = x1c_desc->x20_ROTM.get())
|
||||
if (CRealElement* rotm = x1c_desc->x20_ROTM.get()) {
|
||||
rotm->GetValue(x28_curFrame, swoosh.x34_rotm);
|
||||
else
|
||||
} else {
|
||||
swoosh.x34_rotm = 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
if (CModVectorElement* velm = x1c_desc->x30_VELM.get()) {
|
||||
if (x1d0_29_VLS1) {
|
||||
|
@ -196,8 +203,9 @@ void CParticleSwoosh::UpdateTranslationAndOrientation() {
|
|||
}
|
||||
|
||||
bool CParticleSwoosh::Update(double dt) {
|
||||
if (!IsValid())
|
||||
if (!IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CParticleGlobals::instance()->SetParticleLifetime(x1b4_LENG);
|
||||
CParticleGlobals::instance()->SetEmitterTime(x28_curFrame);
|
||||
|
@ -206,24 +214,27 @@ bool CParticleSwoosh::Update(double dt) {
|
|||
|
||||
double evalTime = x28_curFrame / 60.0;
|
||||
float time = 1.f;
|
||||
if (CRealElement* timeElem = x1c_desc->x4_TIME.get())
|
||||
if (CRealElement* timeElem = x1c_desc->x4_TIME.get()) {
|
||||
timeElem->GetValue(x28_curFrame, time);
|
||||
}
|
||||
|
||||
x30_curTime += std::max(0.0, dt * time);
|
||||
while (x1d0_26_forceOneUpdate || evalTime < x30_curTime) {
|
||||
x1d0_26_forceOneUpdate = false;
|
||||
|
||||
x158_curParticle += 1;
|
||||
if (x158_curParticle >= x15c_swooshes.size())
|
||||
if (x158_curParticle >= x15c_swooshes.size()) {
|
||||
x158_curParticle = 0;
|
||||
}
|
||||
|
||||
if (x1d0_24_emitting && x28_curFrame < x2c_PSLT) {
|
||||
UpdateSwooshTranslation(x38_translation);
|
||||
|
||||
if (CRealElement* irot = x1c_desc->x1c_IROT.get())
|
||||
if (CRealElement* irot = x1c_desc->x1c_IROT.get()) {
|
||||
irot->GetValue(x28_curFrame, x15c_swooshes[x158_curParticle].x30_irot);
|
||||
else
|
||||
} else {
|
||||
x15c_swooshes[x158_curParticle].x30_irot = 0.f;
|
||||
}
|
||||
|
||||
x15c_swooshes[x158_curParticle].x34_rotm = 0.f;
|
||||
x15c_swooshes[x158_curParticle].x70_startFrame = x28_curFrame;
|
||||
|
@ -240,20 +251,23 @@ bool CParticleSwoosh::Update(double dt) {
|
|||
x15c_swooshes[x158_curParticle].x74_velocity = x44_orientation * x15c_swooshes[x158_curParticle].x74_velocity;
|
||||
}
|
||||
|
||||
if (CVectorElement* pofs = x1c_desc->x24_POFS.get())
|
||||
if (CVectorElement* pofs = x1c_desc->x24_POFS.get()) {
|
||||
pofs->GetValue(x28_curFrame, x15c_swooshes[x158_curParticle].x18_offset);
|
||||
}
|
||||
|
||||
x15c_swooshes[x158_curParticle].x24_useOffset = x15c_swooshes[x158_curParticle].x18_offset;
|
||||
|
||||
if (CColorElement* colr = x1c_desc->x14_COLR.get())
|
||||
if (CColorElement* colr = x1c_desc->x14_COLR.get()) {
|
||||
colr->GetValue(x28_curFrame, x15c_swooshes[x158_curParticle].x6c_color);
|
||||
else
|
||||
} else {
|
||||
x15c_swooshes[x158_curParticle].x6c_color = zeus::skWhite;
|
||||
}
|
||||
|
||||
int tspn = 0;
|
||||
if (CIntElement* tspnElem = x1c_desc->x40_TSPN.get())
|
||||
if (CIntElement* tspnElem = x1c_desc->x40_TSPN.get()) {
|
||||
tspnElem->GetValue(x28_curFrame, tspn);
|
||||
x1cc_TSPN = tspn;
|
||||
}
|
||||
x1cc_TSPN = float(tspn);
|
||||
} else if (x15c_swooshes[x158_curParticle].x0_active) {
|
||||
x1ac_particleCount = std::max(0, int(x1ac_particleCount) - 1);
|
||||
x15c_swooshes[x158_curParticle].x0_active = false;
|
||||
|
@ -270,28 +284,32 @@ bool CParticleSwoosh::Update(double dt) {
|
|||
|
||||
zeus::CVector3f CParticleSwoosh::GetSplinePoint(const zeus::CVector3f& p0, const zeus::CVector3f& p1,
|
||||
const zeus::CVector3f& p2, const zeus::CVector3f& p3, float t) {
|
||||
if (t > 0.f)
|
||||
if (t > 0.f) {
|
||||
return p1;
|
||||
if (t >= 1.f)
|
||||
}
|
||||
if (t >= 1.f) {
|
||||
return p2;
|
||||
}
|
||||
|
||||
// Tricubic spline interpolation
|
||||
float t2 = t * t;
|
||||
float t3 = t2 * t;
|
||||
const float t2 = t * t;
|
||||
const float t3 = t2 * t;
|
||||
|
||||
float p0Coef = -0.5f * t3 + t2 - 0.5f * t;
|
||||
float p1Coef = 1.5f * t3 - 2.5f * t2 + 1.f;
|
||||
float p2Coef = -1.5f * t3 + 2.f * t2 + 0.5f * t;
|
||||
float p3Coef = 0.5f * t3 + 0.5f * t2;
|
||||
const float p0Coef = -0.5f * t3 + t2 - 0.5f * t;
|
||||
const float p1Coef = 1.5f * t3 - 2.5f * t2 + 1.f;
|
||||
const float p2Coef = -1.5f * t3 + 2.f * t2 + 0.5f * t;
|
||||
const float p3Coef = 0.5f * t3 + 0.5f * t2;
|
||||
|
||||
return p0 * p0Coef + p1 * p1Coef + p2 * p2Coef + p3 * p3Coef;
|
||||
}
|
||||
|
||||
int CParticleSwoosh::WrapIndex(int i) const {
|
||||
while (i < 0)
|
||||
while (i < 0) {
|
||||
i += x1b4_LENG;
|
||||
while (i >= x1b4_LENG)
|
||||
}
|
||||
while (i >= x1b4_LENG) {
|
||||
i -= x1b4_LENG;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -304,112 +322,125 @@ void CParticleSwoosh::RenderNSidedSpline() {
|
|||
}
|
||||
|
||||
bool cros = x1c_desc->x44_25_CROS;
|
||||
if (x1b8_SIDE >= 4 || x1b8_SIDE & 0x1)
|
||||
if (x1b8_SIDE >= 4 || (x1b8_SIDE & 0x1) != 0) {
|
||||
cros = false;
|
||||
}
|
||||
|
||||
int curIdx = x158_curParticle;
|
||||
for (size_t i = 0; i < x15c_swooshes.size(); ++i) {
|
||||
bool a0 = x15c_swooshes[WrapIndex(curIdx - 1)].x0_active;
|
||||
bool a1 = x15c_swooshes[WrapIndex(curIdx)].x0_active;
|
||||
const bool a0 = x15c_swooshes[WrapIndex(curIdx - 1)].x0_active;
|
||||
const bool a1 = x15c_swooshes[WrapIndex(curIdx)].x0_active;
|
||||
if (!a1 || (a1 && !a0)) {
|
||||
curIdx -= 1;
|
||||
if (curIdx < 0)
|
||||
if (curIdx < 0) {
|
||||
curIdx = x15c_swooshes.size() - 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
SSwooshData& refSwoosh = x15c_swooshes[curIdx];
|
||||
const SSwooshData& refSwoosh = x15c_swooshes[curIdx];
|
||||
|
||||
float sideDiv = 360.f / float(x1b8_SIDE);
|
||||
const float sideDiv = 360.f / float(x1b8_SIDE);
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
int crossRefIdx = 0;
|
||||
if (j == 0) {
|
||||
crossRefIdx = WrapIndex(curIdx + 1);
|
||||
if (!x15c_swooshes[crossRefIdx].x0_active)
|
||||
if (!x15c_swooshes[crossRefIdx].x0_active) {
|
||||
crossRefIdx = curIdx;
|
||||
}
|
||||
} else if (j == 1) {
|
||||
crossRefIdx = WrapIndex(curIdx);
|
||||
} else if (j == 2) {
|
||||
crossRefIdx = WrapIndex(curIdx - 1);
|
||||
} else if (j == 3) {
|
||||
crossRefIdx = WrapIndex(curIdx - 2);
|
||||
if (!x15c_swooshes[crossRefIdx].x0_active)
|
||||
if (!x15c_swooshes[crossRefIdx].x0_active) {
|
||||
crossRefIdx = WrapIndex(curIdx - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (x1b4_LENG == 2) {
|
||||
if (j == 0)
|
||||
if (j == 0) {
|
||||
crossRefIdx = WrapIndex(curIdx);
|
||||
if (j == 3)
|
||||
}
|
||||
if (j == 3) {
|
||||
crossRefIdx = WrapIndex(curIdx - 1);
|
||||
}
|
||||
} else if (x158_curParticle == curIdx && j == 0) {
|
||||
crossRefIdx = x158_curParticle;
|
||||
} else {
|
||||
if (WrapIndex(x158_curParticle + 2) == curIdx && j == 3)
|
||||
if (WrapIndex(x158_curParticle + 2) == curIdx && j == 3) {
|
||||
crossRefIdx = WrapIndex(x158_curParticle + 1);
|
||||
else if (x1ac_particleCount - 2 == i && j == 3)
|
||||
} else if (x1ac_particleCount - 2 == i && j == 3) {
|
||||
crossRefIdx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
SSwooshData& crossSwoosh = x15c_swooshes[crossRefIdx];
|
||||
const SSwooshData& crossSwoosh = x15c_swooshes[crossRefIdx];
|
||||
for (int k = 0; k < x1b8_SIDE; ++k) {
|
||||
float n = sideDiv * k;
|
||||
const float n = sideDiv * k;
|
||||
float ang = zeus::degToRad(n + crossSwoosh.x30_irot + crossSwoosh.x34_rotm);
|
||||
if (std::fabs(ang) > M_PIF) {
|
||||
ang -= std::floor(ang / (2.f * M_PIF)) * 2.f * M_PIF;
|
||||
if (ang > M_PIF)
|
||||
if (ang > M_PIF) {
|
||||
ang -= 2.f * M_PIF;
|
||||
else if (ang < -M_PIF)
|
||||
} else if (ang < -M_PIF) {
|
||||
ang += 2.f * M_PIF;
|
||||
}
|
||||
}
|
||||
|
||||
float z = std::sin(ang);
|
||||
float x = std::cos(ang);
|
||||
const float z = std::sin(ang);
|
||||
const float x = std::cos(ang);
|
||||
|
||||
float rad = (n > 0.f && n <= 180.f) ? crossSwoosh.x4_leftRad : crossSwoosh.x8_rightRad;
|
||||
zeus::CVector3f offset = crossSwoosh.xc_translation + crossSwoosh.x24_useOffset;
|
||||
const float rad = (n > 0.f && n <= 180.f) ? crossSwoosh.x4_leftRad : crossSwoosh.x8_rightRad;
|
||||
const zeus::CVector3f offset = crossSwoosh.xc_translation + crossSwoosh.x24_useOffset;
|
||||
|
||||
if (j == 0)
|
||||
if (j == 0) {
|
||||
x16c_p0[k] = crossSwoosh.x38_orientation * zeus::CVector3f(rad * x, 0.f, rad * z) + offset;
|
||||
else if (j == 1)
|
||||
} else if (j == 1) {
|
||||
x17c_p1[k] = crossSwoosh.x38_orientation * zeus::CVector3f(rad * x, 0.f, rad * z) + offset;
|
||||
else if (j == 2)
|
||||
} else if (j == 2) {
|
||||
x18c_p2[k] = crossSwoosh.x38_orientation * zeus::CVector3f(rad * x, 0.f, rad * z) + offset;
|
||||
else if (j == 3)
|
||||
} else if (j == 3) {
|
||||
x19c_p3[k] = crossSwoosh.x38_orientation * zeus::CVector3f(rad * x, 0.f, rad * z) + offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (x1c_desc->x3c_TEXR) {
|
||||
if (x1ec_TSPN > 0)
|
||||
if (x1ec_TSPN > 0) {
|
||||
x1d4_uvs.xMin = float((i % x1ec_TSPN) * x1e8_uvSpan);
|
||||
else
|
||||
} else {
|
||||
x1d4_uvs.xMin = float(i * x1e8_uvSpan);
|
||||
}
|
||||
}
|
||||
|
||||
float segUvSpan = x1e8_uvSpan / float(x1b0_SPLN + 1);
|
||||
const float segUvSpan = x1e8_uvSpan / float(x1b0_SPLN + 1);
|
||||
for (int j = 0; j < x1b0_SPLN + 1; ++j) {
|
||||
float t0 = j / float(x1b0_SPLN + 1);
|
||||
float t1 = (j + 1) / float(x1b0_SPLN + 1);
|
||||
const float t0 = j / float(x1b0_SPLN + 1);
|
||||
const float t1 = (j + 1) / float(x1b0_SPLN + 1);
|
||||
int faces = x1b8_SIDE;
|
||||
if (x1b8_SIDE <= 2)
|
||||
if (x1b8_SIDE <= 2) {
|
||||
faces = 1;
|
||||
else if (cros)
|
||||
} else if (cros) {
|
||||
faces = x1b8_SIDE / 2;
|
||||
}
|
||||
|
||||
x1d4_uvs.xMax = x1d4_uvs.xMin + segUvSpan;
|
||||
|
||||
for (int k = 0; k < faces; ++k) {
|
||||
int otherK = k + 1;
|
||||
if (k + 1 >= x1b8_SIDE)
|
||||
if (k + 1 >= x1b8_SIDE) {
|
||||
otherK = 0;
|
||||
zeus::CColor color = refSwoosh.x6c_color * x20c_moduColor;
|
||||
}
|
||||
|
||||
const zeus::CColor color = refSwoosh.x6c_color * x20c_moduColor;
|
||||
if (cros) {
|
||||
otherK = k + x1b8_SIDE / 2;
|
||||
zeus::CVector3f v0 = GetSplinePoint(x16c_p0[k], x17c_p1[k], x18c_p2[k], x19c_p3[k], t0);
|
||||
zeus::CVector3f v1 = GetSplinePoint(x16c_p0[otherK], x17c_p1[otherK], x18c_p2[otherK], x19c_p3[otherK], t0);
|
||||
zeus::CVector3f v2 = GetSplinePoint(x16c_p0[otherK], x17c_p1[otherK], x18c_p2[otherK], x19c_p3[otherK], t1);
|
||||
zeus::CVector3f v3 = GetSplinePoint(x16c_p0[k], x17c_p1[k], x18c_p2[k], x19c_p3[k], t1);
|
||||
const auto v0 = GetSplinePoint(x16c_p0[k], x17c_p1[k], x18c_p2[k], x19c_p3[k], t0);
|
||||
const auto v1 = GetSplinePoint(x16c_p0[otherK], x17c_p1[otherK], x18c_p2[otherK], x19c_p3[otherK], t0);
|
||||
const auto v2 = GetSplinePoint(x16c_p0[otherK], x17c_p1[otherK], x18c_p2[otherK], x19c_p3[otherK], t1);
|
||||
const auto v3 = GetSplinePoint(x16c_p0[k], x17c_p1[k], x18c_p2[k], x19c_p3[k], t1);
|
||||
|
||||
m_cachedVerts.push_back({v0, {x1d4_uvs.xMin, x1d4_uvs.yMin}, color});
|
||||
m_cachedVerts.push_back({v1, {x1d4_uvs.xMin, x1d4_uvs.yMax}, color});
|
||||
|
@ -417,10 +448,10 @@ void CParticleSwoosh::RenderNSidedSpline() {
|
|||
m_cachedVerts.push_back({v3, {x1d4_uvs.xMax, x1d4_uvs.yMax}, color});
|
||||
CGraphics::DrawArray(m_cachedVerts.size() - 4, 4);
|
||||
} else {
|
||||
zeus::CVector3f v0 = GetSplinePoint(x16c_p0[k], x17c_p1[k], x18c_p2[k], x19c_p3[k], t0);
|
||||
zeus::CVector3f v1 = GetSplinePoint(x16c_p0[otherK], x17c_p1[otherK], x18c_p2[otherK], x19c_p3[otherK], t0);
|
||||
zeus::CVector3f v2 = GetSplinePoint(x16c_p0[otherK], x17c_p1[otherK], x18c_p2[otherK], x19c_p3[otherK], t1);
|
||||
zeus::CVector3f v3 = GetSplinePoint(x16c_p0[k], x17c_p1[k], x18c_p2[k], x19c_p3[k], t1);
|
||||
const auto v0 = GetSplinePoint(x16c_p0[k], x17c_p1[k], x18c_p2[k], x19c_p3[k], t0);
|
||||
const auto v1 = GetSplinePoint(x16c_p0[otherK], x17c_p1[otherK], x18c_p2[otherK], x19c_p3[otherK], t0);
|
||||
const auto v2 = GetSplinePoint(x16c_p0[otherK], x17c_p1[otherK], x18c_p2[otherK], x19c_p3[otherK], t1);
|
||||
const auto v3 = GetSplinePoint(x16c_p0[k], x17c_p1[k], x18c_p2[k], x19c_p3[k], t1);
|
||||
|
||||
if (x1bc_prim == GX::LINES) {
|
||||
m_lineRenderer->AddVertex(v0, color, 1.f);
|
||||
|
@ -445,57 +476,65 @@ void CParticleSwoosh::RenderNSidedSpline() {
|
|||
}
|
||||
}
|
||||
|
||||
if (x1c_desc->x3c_TEXR && x1b0_SPLN > 0)
|
||||
if (x1c_desc->x3c_TEXR && x1b0_SPLN > 0) {
|
||||
x1d4_uvs.xMin += segUvSpan;
|
||||
}
|
||||
}
|
||||
|
||||
curIdx -= 1;
|
||||
if (curIdx < 0)
|
||||
if (curIdx < 0) {
|
||||
curIdx = x15c_swooshes.size() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (x1bc_prim == GX::LINES)
|
||||
if (x1bc_prim == GX::LINES) {
|
||||
m_lineRenderer->Render(g_Renderer->IsThermalVisorHotPass());
|
||||
}
|
||||
}
|
||||
|
||||
void CParticleSwoosh::RenderNSidedNoSpline() { RenderNSidedSpline(); }
|
||||
|
||||
void CParticleSwoosh::Render3SidedSolidSpline() {
|
||||
if (x15c_swooshes.size() < 2)
|
||||
if (x15c_swooshes.size() < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
int curIdx = x158_curParticle;
|
||||
float curUvSpan = -x1e8_uvSpan;
|
||||
zeus::CColor prevColor0 = zeus::skClear;
|
||||
for (size_t i = 0; i < x15c_swooshes.size(); ++i) {
|
||||
SSwooshData& swoosh = x15c_swooshes[curIdx];
|
||||
const SSwooshData& swoosh = x15c_swooshes[curIdx];
|
||||
|
||||
curIdx -= 1;
|
||||
if (curIdx < 0)
|
||||
if (curIdx < 0) {
|
||||
curIdx = x15c_swooshes.size() - 1;
|
||||
}
|
||||
|
||||
float ang1 = zeus::degToRad(swoosh.x30_irot + swoosh.x34_rotm);
|
||||
if (std::fabs(ang1) > M_PIF) {
|
||||
ang1 -= std::floor(ang1 / (2.f * M_PIF)) * 2.f * M_PIF;
|
||||
if (ang1 > M_PIF)
|
||||
if (ang1 > M_PIF) {
|
||||
ang1 -= 2.f * M_PIF;
|
||||
else if (ang1 < -M_PIF)
|
||||
} else if (ang1 < -M_PIF) {
|
||||
ang1 += 2.f * M_PIF;
|
||||
}
|
||||
}
|
||||
|
||||
zeus::CVector3f ang1Vec(std::sin(ang1) * swoosh.x4_leftRad, 0.f, std::cos(ang1) * swoosh.x4_leftRad);
|
||||
const zeus::CVector3f ang1Vec(std::sin(ang1) * swoosh.x4_leftRad, 0.f, std::cos(ang1) * swoosh.x4_leftRad);
|
||||
|
||||
float ang2 = ang1 + 2.0943952f; // +120 degrees
|
||||
if (ang2 > M_PIF)
|
||||
if (ang2 > M_PIF) {
|
||||
ang2 -= 2.f * M_PIF;
|
||||
}
|
||||
|
||||
zeus::CVector3f ang2Vec(std::sin(ang2) * swoosh.x4_leftRad, 0.f, std::cos(ang2) * swoosh.x4_leftRad);
|
||||
const zeus::CVector3f ang2Vec(std::sin(ang2) * swoosh.x4_leftRad, 0.f, std::cos(ang2) * swoosh.x4_leftRad);
|
||||
|
||||
float ang3 = ang2 + 2.0943952f; // +120 degrees
|
||||
if (ang3 > M_PIF)
|
||||
if (ang3 > M_PIF) {
|
||||
ang3 -= 2.f * M_PIF;
|
||||
}
|
||||
|
||||
zeus::CVector3f ang3Vec(std::sin(ang3) * swoosh.x4_leftRad, 0.f, std::cos(ang3) * swoosh.x4_leftRad);
|
||||
const zeus::CVector3f ang3Vec(std::sin(ang3) * swoosh.x4_leftRad, 0.f, std::cos(ang3) * swoosh.x4_leftRad);
|
||||
|
||||
if (i == 2) {
|
||||
x19c_p3[0] = x17c_p1[0] * 2.f - x16c_p0[0];
|
||||
|
@ -515,15 +554,15 @@ void CParticleSwoosh::Render3SidedSolidSpline() {
|
|||
x17c_p1[1] = x16c_p0[1];
|
||||
x17c_p1[2] = x16c_p0[2];
|
||||
|
||||
zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset;
|
||||
const zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset;
|
||||
x16c_p0[0] = swoosh.x38_orientation * ang1Vec + useOffset;
|
||||
x16c_p0[1] = swoosh.x38_orientation * ang2Vec + useOffset;
|
||||
x16c_p0[2] = swoosh.x38_orientation * ang3Vec + useOffset;
|
||||
|
||||
zeus::CColor useColor0 = prevColor0;
|
||||
const zeus::CColor useColor0 = prevColor0;
|
||||
|
||||
if (swoosh.x0_active) {
|
||||
zeus::CColor prevColor1 = prevColor0;
|
||||
const zeus::CColor prevColor1 = prevColor0;
|
||||
prevColor0 = swoosh.x6c_color * x20c_moduColor;
|
||||
float prevUvSpan = curUvSpan;
|
||||
curUvSpan += x1e8_uvSpan;
|
||||
|
@ -583,8 +622,9 @@ void CParticleSwoosh::Render3SidedSolidSpline() {
|
|||
}
|
||||
|
||||
void CParticleSwoosh::Render3SidedSolidNoSplineNoGaps() {
|
||||
if (x15c_swooshes.size() < 2)
|
||||
if (x15c_swooshes.size() < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::array<zeus::CVector3f, 2> p0;
|
||||
std::array<zeus::CVector3f, 2> p1;
|
||||
|
@ -595,36 +635,40 @@ void CParticleSwoosh::Render3SidedSolidNoSplineNoGaps() {
|
|||
zeus::CColor c0 = zeus::skClear;
|
||||
float uv0 = -x1e8_uvSpan;
|
||||
for (size_t i = 0; i < x15c_swooshes.size(); ++i) {
|
||||
SSwooshData& swoosh = x15c_swooshes[curIdx];
|
||||
const SSwooshData& swoosh = x15c_swooshes[curIdx];
|
||||
|
||||
curIdx -= 1;
|
||||
if (curIdx < 0)
|
||||
if (curIdx < 0) {
|
||||
curIdx = x15c_swooshes.size() - 1;
|
||||
}
|
||||
|
||||
float ang1 = zeus::degToRad(swoosh.x30_irot + swoosh.x34_rotm);
|
||||
if (std::fabs(ang1) > M_PIF) {
|
||||
ang1 -= std::floor(ang1 / (2.f * M_PIF)) * 2.f * M_PIF;
|
||||
if (ang1 > M_PIF)
|
||||
if (ang1 > M_PIF) {
|
||||
ang1 -= 2.f * M_PIF;
|
||||
else if (ang1 < -M_PIF)
|
||||
} else if (ang1 < -M_PIF) {
|
||||
ang1 += 2.f * M_PIF;
|
||||
}
|
||||
}
|
||||
|
||||
zeus::CVector3f ang1Vec(std::sin(ang1) * swoosh.x4_leftRad, 0.f, std::cos(ang1) * swoosh.x4_leftRad);
|
||||
const zeus::CVector3f ang1Vec(std::sin(ang1) * swoosh.x4_leftRad, 0.f, std::cos(ang1) * swoosh.x4_leftRad);
|
||||
|
||||
float ang2 = ang1 + 2.0943952f; // +120 degrees
|
||||
if (ang2 > M_PIF)
|
||||
if (ang2 > M_PIF) {
|
||||
ang2 -= 2.f * M_PIF;
|
||||
}
|
||||
|
||||
zeus::CVector3f ang2Vec(std::sin(ang2) * swoosh.x4_leftRad, 0.f, std::cos(ang2) * swoosh.x4_leftRad);
|
||||
const zeus::CVector3f ang2Vec(std::sin(ang2) * swoosh.x4_leftRad, 0.f, std::cos(ang2) * swoosh.x4_leftRad);
|
||||
|
||||
float ang3 = ang2 + 2.0943952f; // +120 degrees
|
||||
if (ang3 > M_PIF)
|
||||
if (ang3 > M_PIF) {
|
||||
ang3 -= 2.f * M_PIF;
|
||||
}
|
||||
|
||||
zeus::CVector3f ang3Vec(std::sin(ang3) * swoosh.x4_leftRad, 0.f, std::cos(ang3) * swoosh.x4_leftRad);
|
||||
const zeus::CVector3f ang3Vec(std::sin(ang3) * swoosh.x4_leftRad, 0.f, std::cos(ang3) * swoosh.x4_leftRad);
|
||||
|
||||
zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset;
|
||||
const zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset;
|
||||
p0[i & 1] = swoosh.x38_orientation * ang1Vec + useOffset;
|
||||
p1[i & 1] = swoosh.x38_orientation * ang2Vec + useOffset;
|
||||
p2[i & 1] = swoosh.x38_orientation * ang3Vec + useOffset;
|
||||
|
@ -640,10 +684,10 @@ void CParticleSwoosh::Render3SidedSolidNoSplineNoGaps() {
|
|||
}
|
||||
|
||||
lastActive = true;
|
||||
zeus::CColor c1 = c0;
|
||||
const zeus::CColor c1 = c0;
|
||||
c0 = swoosh.x6c_color * x20c_moduColor;
|
||||
|
||||
float uv1 = uv0;
|
||||
const float uv1 = uv0;
|
||||
uv0 += x1e8_uvSpan;
|
||||
|
||||
m_cachedVerts.push_back({p0[i & 1], {uv0, x1d4_uvs.yMin}, c0});
|
||||
|
@ -673,12 +717,13 @@ void CParticleSwoosh::Render2SidedNoSplineGaps() {
|
|||
bool streaming = false;
|
||||
int curIdx = x158_curParticle;
|
||||
for (size_t i = 0; i < x15c_swooshes.size(); ++i) {
|
||||
SSwooshData& swoosh = x15c_swooshes[curIdx];
|
||||
bool otherActive = x15c_swooshes[WrapIndex(curIdx - 1)].x0_active;
|
||||
const SSwooshData& swoosh = x15c_swooshes[curIdx];
|
||||
const bool otherActive = x15c_swooshes[WrapIndex(curIdx - 1)].x0_active;
|
||||
|
||||
curIdx -= 1;
|
||||
if (curIdx < 0)
|
||||
if (curIdx < 0) {
|
||||
curIdx = x15c_swooshes.size() - 2;
|
||||
}
|
||||
|
||||
if (!swoosh.x0_active) {
|
||||
if (streaming) {
|
||||
|
@ -689,10 +734,12 @@ void CParticleSwoosh::Render2SidedNoSplineGaps() {
|
|||
}
|
||||
|
||||
if (!streaming) {
|
||||
if (!otherActive)
|
||||
if (!otherActive) {
|
||||
continue;
|
||||
if (i >= x15c_swooshes.size() - 2)
|
||||
}
|
||||
if (i >= x15c_swooshes.size() - 2) {
|
||||
continue;
|
||||
}
|
||||
streaming = true;
|
||||
drawStart = m_cachedVerts.size();
|
||||
}
|
||||
|
@ -700,24 +747,25 @@ void CParticleSwoosh::Render2SidedNoSplineGaps() {
|
|||
float ang = zeus::degToRad(swoosh.x30_irot + swoosh.x34_rotm);
|
||||
if (std::fabs(ang) > M_PIF) {
|
||||
ang -= std::floor(ang / (2.f * M_PIF)) * 2.f * M_PIF;
|
||||
if (ang > M_PIF)
|
||||
if (ang > M_PIF) {
|
||||
ang -= 2.f * M_PIF;
|
||||
else if (ang < -M_PIF)
|
||||
} else if (ang < -M_PIF) {
|
||||
ang += 2.f * M_PIF;
|
||||
}
|
||||
}
|
||||
|
||||
float sinAng = std::sin(ang);
|
||||
float cosAng = std::cos(ang);
|
||||
const float sinAng = std::sin(ang);
|
||||
const float cosAng = std::cos(ang);
|
||||
|
||||
zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset;
|
||||
zeus::CVector3f v0 =
|
||||
const zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset;
|
||||
const zeus::CVector3f v0 =
|
||||
swoosh.x38_orientation * zeus::CVector3f(cosAng * swoosh.x4_leftRad, 0.f, sinAng * swoosh.x4_leftRad) +
|
||||
useOffset;
|
||||
zeus::CVector3f v1 =
|
||||
const zeus::CVector3f v1 =
|
||||
swoosh.x38_orientation * zeus::CVector3f(-cosAng * swoosh.x8_rightRad, 0.f, -sinAng * swoosh.x8_rightRad) +
|
||||
useOffset;
|
||||
|
||||
zeus::CColor color = swoosh.x6c_color * x20c_moduColor;
|
||||
const zeus::CColor color = swoosh.x6c_color * x20c_moduColor;
|
||||
|
||||
m_cachedVerts.push_back({v0, {1.f, x1d4_uvs.yMin}, color});
|
||||
m_cachedVerts.push_back({v1, {1.f, x1d4_uvs.yMax}, color});
|
||||
|
@ -734,43 +782,47 @@ void CParticleSwoosh::Render2SidedNoSplineNoGaps() {
|
|||
int curIdx = x158_curParticle;
|
||||
int particleCount = x1ac_particleCount;
|
||||
float uvOffset = 0.f;
|
||||
|
||||
if (x1c_desc->x3c_TEXR) {
|
||||
if (x1c_desc->x45_25_ORNT) {
|
||||
zeus::CVector3f camToParticle =
|
||||
const zeus::CVector3f camToParticle =
|
||||
((zeus::CTransform::Translate(xa4_globalTranslation) * xb0_globalOrientation * xec_scaleXf).inverse() *
|
||||
CGraphics::g_ViewMatrix)
|
||||
.origin;
|
||||
zeus::CVector3f dotVec = zeus::skZero3f;
|
||||
|
||||
for (size_t i = 0; i < x15c_swooshes.size(); ++i) {
|
||||
SSwooshData& swoosh = x15c_swooshes[curIdx];
|
||||
const SSwooshData& swoosh = x15c_swooshes[curIdx];
|
||||
|
||||
curIdx -= 1;
|
||||
if (curIdx < 0)
|
||||
if (curIdx < 0) {
|
||||
curIdx = x15c_swooshes.size() - 1;
|
||||
}
|
||||
|
||||
if (swoosh.x0_active) {
|
||||
particleCount -= 1;
|
||||
int otherIdx = curIdx - 1;
|
||||
if (otherIdx < 0)
|
||||
if (otherIdx < 0) {
|
||||
otherIdx = x15c_swooshes.size() - 1;
|
||||
}
|
||||
|
||||
SSwooshData& otherSwoosh = x15c_swooshes[otherIdx];
|
||||
const SSwooshData& otherSwoosh = x15c_swooshes[otherIdx];
|
||||
|
||||
zeus::CVector3f delta = otherSwoosh.xc_translation - swoosh.xc_translation;
|
||||
if (otherIdx == x158_curParticle)
|
||||
if (otherIdx == x158_curParticle) {
|
||||
delta = swoosh.xc_translation - x15c_swooshes[(curIdx + 1) % x15c_swooshes.size()].xc_translation;
|
||||
}
|
||||
|
||||
if (delta.canBeNormalized()) {
|
||||
zeus::CVector3f deltaCross = delta.cross(camToParticle - swoosh.xc_translation);
|
||||
if (deltaCross.canBeNormalized()) {
|
||||
deltaCross.normalize();
|
||||
dotVec = (deltaCross.dot(dotVec) < 0.f ? -1.f : 1.f) * deltaCross;
|
||||
zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset;
|
||||
zeus::CVector3f v0 = dotVec * swoosh.x4_leftRad + useOffset;
|
||||
zeus::CVector3f v1 = dotVec * -swoosh.x8_rightRad + useOffset;
|
||||
const zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset;
|
||||
const zeus::CVector3f v0 = dotVec * swoosh.x4_leftRad + useOffset;
|
||||
const zeus::CVector3f v1 = dotVec * -swoosh.x8_rightRad + useOffset;
|
||||
|
||||
zeus::CColor color = swoosh.x6c_color * x20c_moduColor;
|
||||
const zeus::CColor color = swoosh.x6c_color * x20c_moduColor;
|
||||
|
||||
m_cachedVerts.push_back({v0, {uvOffset, x1d4_uvs.yMin}, color});
|
||||
m_cachedVerts.push_back({v1, {uvOffset, x1d4_uvs.yMax}, color});
|
||||
|
@ -782,21 +834,23 @@ void CParticleSwoosh::Render2SidedNoSplineNoGaps() {
|
|||
m_cachedVerts.push_back({v1, {uvOffset, x1d4_uvs.yMax}, color});
|
||||
}
|
||||
|
||||
if (x1ec_TSPN > 0)
|
||||
if (x1ec_TSPN > 0) {
|
||||
uvOffset += x1e8_uvSpan;
|
||||
else
|
||||
} else {
|
||||
uvOffset = float(i * x1e8_uvSpan);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < x15c_swooshes.size(); ++i) {
|
||||
SSwooshData& swoosh = x15c_swooshes[curIdx];
|
||||
const SSwooshData& swoosh = x15c_swooshes[curIdx];
|
||||
|
||||
curIdx -= 1;
|
||||
if (curIdx < 0)
|
||||
if (curIdx < 0) {
|
||||
curIdx = x15c_swooshes.size() - 1;
|
||||
}
|
||||
|
||||
if (swoosh.x0_active) {
|
||||
particleCount -= 1;
|
||||
|
@ -804,24 +858,25 @@ void CParticleSwoosh::Render2SidedNoSplineNoGaps() {
|
|||
float ang = zeus::degToRad(swoosh.x30_irot + swoosh.x34_rotm);
|
||||
if (std::fabs(ang) > M_PIF) {
|
||||
ang -= std::floor(ang / (2.f * M_PIF)) * 2.f * M_PIF;
|
||||
if (ang > M_PIF)
|
||||
if (ang > M_PIF) {
|
||||
ang -= 2.f * M_PIF;
|
||||
else if (ang < -M_PIF)
|
||||
} else if (ang < -M_PIF) {
|
||||
ang += 2.f * M_PIF;
|
||||
}
|
||||
}
|
||||
|
||||
float sinAng = std::sin(ang);
|
||||
float cosAng = std::cos(ang);
|
||||
|
||||
zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset;
|
||||
zeus::CVector3f v0 =
|
||||
const zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset;
|
||||
const zeus::CVector3f v0 =
|
||||
swoosh.x38_orientation * zeus::CVector3f(cosAng * swoosh.x4_leftRad, 0.f, sinAng * swoosh.x4_leftRad) +
|
||||
useOffset;
|
||||
zeus::CVector3f v1 = swoosh.x38_orientation *
|
||||
zeus::CVector3f(-cosAng * swoosh.x8_rightRad, 0.f, -sinAng * swoosh.x8_rightRad) +
|
||||
const zeus::CVector3f v1 = swoosh.x38_orientation * zeus::CVector3f(-cosAng * swoosh.x8_rightRad, 0.f,
|
||||
-sinAng * swoosh.x8_rightRad) +
|
||||
useOffset;
|
||||
|
||||
zeus::CColor color = swoosh.x6c_color * x20c_moduColor;
|
||||
const zeus::CColor color = swoosh.x6c_color * x20c_moduColor;
|
||||
|
||||
m_cachedVerts.push_back({v0, {uvOffset, x1d4_uvs.yMin}, color});
|
||||
m_cachedVerts.push_back({v1, {uvOffset, x1d4_uvs.yMax}, color});
|
||||
|
@ -833,43 +888,46 @@ void CParticleSwoosh::Render2SidedNoSplineNoGaps() {
|
|||
m_cachedVerts.push_back({v1, {uvOffset, x1d4_uvs.yMax}, color});
|
||||
}
|
||||
|
||||
if (x1ec_TSPN > 0)
|
||||
if (x1ec_TSPN > 0) {
|
||||
uvOffset += x1e8_uvSpan;
|
||||
else
|
||||
} else {
|
||||
uvOffset = float(i * x1e8_uvSpan);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < x15c_swooshes.size(); ++i) {
|
||||
SSwooshData& swoosh = x15c_swooshes[curIdx];
|
||||
const SSwooshData& swoosh = x15c_swooshes[curIdx];
|
||||
|
||||
curIdx -= 1;
|
||||
if (curIdx < 0)
|
||||
if (curIdx < 0) {
|
||||
curIdx = x15c_swooshes.size() - 1;
|
||||
}
|
||||
|
||||
if (swoosh.x0_active) {
|
||||
float ang = zeus::degToRad(swoosh.x30_irot + swoosh.x34_rotm);
|
||||
if (std::fabs(ang) > M_PIF) {
|
||||
ang -= std::floor(ang / (2.f * M_PIF)) * 2.f * M_PIF;
|
||||
if (ang > M_PIF)
|
||||
if (ang > M_PIF) {
|
||||
ang -= 2.f * M_PIF;
|
||||
else if (ang < -M_PIF)
|
||||
} else if (ang < -M_PIF) {
|
||||
ang += 2.f * M_PIF;
|
||||
}
|
||||
}
|
||||
|
||||
float sinAng = std::sin(ang);
|
||||
float cosAng = std::cos(ang);
|
||||
const float sinAng = std::sin(ang);
|
||||
const float cosAng = std::cos(ang);
|
||||
|
||||
zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset;
|
||||
zeus::CVector3f v0 =
|
||||
const zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset;
|
||||
const zeus::CVector3f v0 =
|
||||
swoosh.x38_orientation * zeus::CVector3f(cosAng * swoosh.x4_leftRad, 0.f, sinAng * swoosh.x4_leftRad) +
|
||||
useOffset;
|
||||
zeus::CVector3f v1 =
|
||||
const zeus::CVector3f v1 =
|
||||
swoosh.x38_orientation * zeus::CVector3f(-cosAng * swoosh.x8_rightRad, 0.f, -sinAng * swoosh.x8_rightRad) +
|
||||
useOffset;
|
||||
|
||||
zeus::CColor color = swoosh.x6c_color * x20c_moduColor;
|
||||
const zeus::CColor color = swoosh.x6c_color * x20c_moduColor;
|
||||
m_cachedVerts.push_back({v0, {}, color});
|
||||
m_cachedVerts.push_back({v1, {}, color});
|
||||
}
|
||||
|
@ -880,14 +938,17 @@ void CParticleSwoosh::Render2SidedNoSplineNoGaps() {
|
|||
}
|
||||
|
||||
void CParticleSwoosh::Render(const CActorLights*) {
|
||||
if (x1b4_LENG < 2 || x1ac_particleCount <= 1)
|
||||
if (x1b4_LENG < 2 || x1ac_particleCount <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(FMT_STRING("CParticleSwoosh::Render {}"),
|
||||
*x1c_desc.GetObjectTag()).c_str(), zeus::skYellow);
|
||||
|
||||
m_cachedVerts.clear();
|
||||
if (m_dataBind[0])
|
||||
if (m_dataBind[0]) {
|
||||
CGraphics::SetShaderDataBinding(m_dataBind[g_Renderer->IsThermalVisorHotPass()]);
|
||||
}
|
||||
|
||||
CParticleGlobals::instance()->SetParticleLifetime(x1b4_LENG);
|
||||
CGlobalRandom gr(x1c0_rand);
|
||||
|
@ -910,15 +971,18 @@ void CParticleSwoosh::Render(const CActorLights*) {
|
|||
x1d0_31_constantTex = texr->HasConstantTexture();
|
||||
x1d1_24_constantUv = texr->HasConstantUV();
|
||||
|
||||
if (CIntElement* tspn = x1c_desc->x40_TSPN.get())
|
||||
if (CIntElement* tspn = x1c_desc->x40_TSPN.get()) {
|
||||
tspn->GetValue(x28_curFrame, x1ec_TSPN);
|
||||
}
|
||||
|
||||
if (x1ec_TSPN <= 0)
|
||||
if (x1ec_TSPN <= 0) {
|
||||
x1ec_TSPN = x15c_swooshes.size() - 1;
|
||||
}
|
||||
|
||||
x1e8_uvSpan = 1.f;
|
||||
if (x1ec_TSPN > 0)
|
||||
if (x1ec_TSPN > 0) {
|
||||
x1e8_uvSpan = 1.f / float(x1ec_TSPN);
|
||||
}
|
||||
|
||||
// TEV0 modulate
|
||||
} else {
|
||||
|
@ -929,30 +993,34 @@ void CParticleSwoosh::Render(const CActorLights*) {
|
|||
|
||||
if (x1b8_SIDE == 2) {
|
||||
if (x1b0_SPLN <= 0) {
|
||||
if (x1d0_27_renderGaps)
|
||||
if (x1d0_27_renderGaps) {
|
||||
Render2SidedNoSplineGaps();
|
||||
else
|
||||
} else {
|
||||
Render2SidedNoSplineNoGaps();
|
||||
}
|
||||
} else {
|
||||
Render2SidedSpline();
|
||||
}
|
||||
} else if (x1b8_SIDE == 3) {
|
||||
if (x1b0_SPLN > 0)
|
||||
if (x1b0_SPLN > 0) {
|
||||
Render3SidedSolidSpline();
|
||||
else
|
||||
Render3SidedSolidNoSplineNoGaps();
|
||||
} else {
|
||||
if (x1b0_SPLN > 0)
|
||||
Render3SidedSolidNoSplineNoGaps();
|
||||
}
|
||||
} else {
|
||||
if (x1b0_SPLN > 0) {
|
||||
RenderNSidedSpline();
|
||||
else
|
||||
} else {
|
||||
RenderNSidedNoSpline();
|
||||
}
|
||||
}
|
||||
|
||||
zeus::CMatrix4f mvp = CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f();
|
||||
m_uniformBuf->load(&mvp, sizeof(zeus::CMatrix4f));
|
||||
if (m_cachedVerts.size())
|
||||
if (m_cachedVerts.size()) {
|
||||
m_vertBuf->load(m_cachedVerts.data(), m_cachedVerts.size() * sizeof(CParticleSwooshShaders::Vert));
|
||||
}
|
||||
}
|
||||
|
||||
void CParticleSwoosh::SetOrientation(const zeus::CTransform& xf) {
|
||||
x44_orientation = xf;
|
||||
|
@ -994,18 +1062,19 @@ const zeus::CVector3f& CParticleSwoosh::GetGlobalScale() const { return xe0_glob
|
|||
const zeus::CColor& CParticleSwoosh::GetModulationColor() const { return x20c_moduColor; }
|
||||
|
||||
bool CParticleSwoosh::IsSystemDeletable() const {
|
||||
if (x1d0_24_emitting && x28_curFrame < x2c_PSLT)
|
||||
if (x1d0_24_emitting && x28_curFrame < x2c_PSLT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return GetParticleCount() < 2;
|
||||
}
|
||||
|
||||
std::optional<zeus::CAABox> CParticleSwoosh::GetBounds() const {
|
||||
if (GetParticleCount() <= 1) {
|
||||
zeus::CVector3f trans = x38_translation + xa4_globalTranslation;
|
||||
const zeus::CVector3f trans = x38_translation + xa4_globalTranslation;
|
||||
return zeus::CAABox(trans, trans);
|
||||
} else {
|
||||
zeus::CTransform xf = zeus::CTransform::Translate(xa4_globalTranslation) * xb0_globalOrientation * xec_scaleXf;
|
||||
const zeus::CTransform xf = zeus::CTransform::Translate(xa4_globalTranslation) * xb0_globalOrientation * xec_scaleXf;
|
||||
return zeus::CAABox(x1f0_aabbMin - x208_maxRadius, x1fc_aabbMax + x208_maxRadius).getTransformedAABox(xf);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ class CParticleSwoosh : public CParticleGen {
|
|||
float x30_irot; // Rotation bias once per system update
|
||||
float x34_rotm; // Rotation bias once per particle instance
|
||||
zeus::CTransform x38_orientation; // Updated by user code
|
||||
int x68_frame; // Frame index of evaluated data
|
||||
int x68_frame = 0; // Frame index of evaluated data
|
||||
zeus::CColor x6c_color; // Updated by COLR
|
||||
int x70_startFrame;
|
||||
zeus::CVector3f x74_velocity;
|
||||
|
@ -79,11 +79,11 @@ class CParticleSwoosh : public CParticleGen {
|
|||
int x1b0_SPLN = 0;
|
||||
int x1b4_LENG = 0;
|
||||
int x1b8_SIDE = 0;
|
||||
GX::Primitive x1bc_prim;
|
||||
GX::Primitive x1bc_prim{};
|
||||
CRandom16 x1c0_rand;
|
||||
float x1c4_ = 0.f;
|
||||
float x1c8_ = 0.f;
|
||||
float x1cc_TSPN;
|
||||
float x1cc_TSPN = 0.f;
|
||||
bool x1d0_24_emitting : 1;
|
||||
bool x1d0_25_AALP : 1;
|
||||
bool x1d0_26_forceOneUpdate : 1;
|
||||
|
|
|
@ -28,7 +28,7 @@ constexpr std::array skComboNames{
|
|||
};
|
||||
|
||||
constexpr std::array<u16, 5> skSoundId{
|
||||
1810, 1837, 1847, 1842, 1810,
|
||||
SFXsfx0712, SFXsfx072D, SFXwpn_combo_wavebuster, SFXwpn_combo_flamethrower, SFXsfx0712,
|
||||
};
|
||||
|
||||
CAuxWeapon::CAuxWeapon(TUniqueId playerId)
|
||||
|
|
|
@ -35,8 +35,11 @@ CEnergyProjectile::CEnergyProjectile(bool active, const TToken<CWeaponDescriptio
|
|||
}
|
||||
|
||||
void CEnergyProjectile::PlayImpactSound(const zeus::CVector3f& pos, EWeaponCollisionResponseTypes type) {
|
||||
s32 sfxId = x170_projectile.GetSoundIdForCollision(type);
|
||||
if (sfxId >= 0) {
|
||||
const s32 sfxId = x170_projectile.GetSoundIdForCollision(type);
|
||||
if (sfxId < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
CAudioSys::C3DEmitterParmData parmData = {};
|
||||
parmData.x18_maxDist = x170_projectile.GetAudibleRange();
|
||||
parmData.x1c_distComp = x170_projectile.GetAudibleFallOff();
|
||||
|
@ -45,15 +48,22 @@ void CEnergyProjectile::PlayImpactSound(const zeus::CVector3f& pos, EWeaponColli
|
|||
parmData.x26_maxVol = 1.f;
|
||||
parmData.x27_minVol = 0.16f;
|
||||
parmData.x29_prio = 0x7f;
|
||||
CSfxHandle hnd = CSfxManager::AddEmitter(parmData, true, 0x7f, false, kInvalidAreaId);
|
||||
if (x2e4_26_waterUpdate)
|
||||
CSfxManager::PitchBend(hnd, -1.f);
|
||||
|
||||
const CSfxHandle hnd = CSfxManager::AddEmitter(parmData, true, 0x7f, false, kInvalidAreaId);
|
||||
if (!x2e4_26_waterUpdate) {
|
||||
return;
|
||||
}
|
||||
|
||||
CSfxManager::PitchBend(hnd, -1.f);
|
||||
}
|
||||
|
||||
void CEnergyProjectile::ChangeProjectileOwner(TUniqueId owner, CStateManager& mgr) {
|
||||
if (TCastToConstPtr<CActor> act = mgr.GetObjectById(owner)) {
|
||||
float rDam = g_tweakPlayerGun->GetRichochetDamage(u32(x110_origDamageInfo.GetWeaponMode().GetType()));
|
||||
const TCastToConstPtr<CActor> act = mgr.GetObjectById(owner);
|
||||
if (!act) {
|
||||
return;
|
||||
}
|
||||
|
||||
const float rDam = g_tweakPlayerGun->GetRichochetDamage(u32(x110_origDamageInfo.GetWeaponMode().GetType()));
|
||||
x110_origDamageInfo.MultiplyDamageAndRadius(rDam);
|
||||
mgr.RemoveWeaponId(xec_ownerId, xf0_weaponType);
|
||||
xec_ownerId = owner;
|
||||
|
@ -64,31 +74,35 @@ void CEnergyProjectile::ChangeProjectileOwner(TUniqueId owner, CStateManager& mg
|
|||
xf8_filter.ExcludeList().Remove(EMaterialTypes::Player);
|
||||
xf8_filter = CMaterialFilter::MakeIncludeExclude(xf8_filter.GetIncludeList(), xf8_filter.GetExcludeList());
|
||||
}
|
||||
}
|
||||
|
||||
void CEnergyProjectile::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) {
|
||||
switch (msg) {
|
||||
case EScriptObjectMessage::Deleted:
|
||||
if (x2e4_24_active)
|
||||
if (x2e4_24_active) {
|
||||
mgr.RemoveWeaponId(xec_ownerId, xf0_weaponType);
|
||||
}
|
||||
if (x2e8_sfx) {
|
||||
CSfxManager::RemoveEmitter(x2e8_sfx);
|
||||
x2e8_sfx.reset();
|
||||
}
|
||||
break;
|
||||
case EScriptObjectMessage::Registered: {
|
||||
if (CElementGen* ps1 = x170_projectile.GetAttachedPS1())
|
||||
if (ps1->SystemHasLight())
|
||||
if (CElementGen* ps1 = x170_projectile.GetAttachedPS1()) {
|
||||
if (ps1->SystemHasLight()) {
|
||||
CreateProjectileLight("ProjectileLight_GameProjectile", ps1->GetLight(), mgr);
|
||||
TLockedToken<CWeaponDescription> desc = x170_projectile.GetWeaponDescription();
|
||||
s32 sfx = desc->xa8_PJFX;
|
||||
}
|
||||
}
|
||||
const TLockedToken<CWeaponDescription> desc = x170_projectile.GetWeaponDescription();
|
||||
const s32 sfx = desc->xa8_PJFX;
|
||||
if (sfx != -1) {
|
||||
float range = 50.f;
|
||||
float falloff = 0.2f;
|
||||
if (CRealElement* rnge = desc->xac_RNGE.get())
|
||||
if (CRealElement* rnge = desc->xac_RNGE.get()) {
|
||||
rnge->GetValue(0, range);
|
||||
if (CRealElement* foff = desc->xb0_FOFF.get())
|
||||
}
|
||||
if (CRealElement* foff = desc->xb0_FOFF.get()) {
|
||||
foff->GetValue(0, falloff);
|
||||
}
|
||||
|
||||
CAudioSys::C3DEmitterParmData parmData = {};
|
||||
parmData.x0_pos = x170_projectile.GetTranslation();
|
||||
|
@ -117,22 +131,27 @@ void CEnergyProjectile::Accept(IVisitor& visitor) { visitor.Visit(this); }
|
|||
static constexpr u64 kCheckMaterial = 0xE3FFFE;
|
||||
|
||||
void CEnergyProjectile::ResolveCollisionWithWorld(const CRayCastResult& res, CStateManager& mgr) {
|
||||
EWeaponCollisionResponseTypes crType = CCollisionResponseData::GetWorldCollisionResponseType(
|
||||
const auto crType = CCollisionResponseData::GetWorldCollisionResponseType(
|
||||
CMaterialList::BitPosition((res.GetMaterial().GetValue() & 0xffffffff) & kCheckMaterial));
|
||||
if ((xe8_projectileAttribs & (EProjectileAttrib::Wave | EProjectileAttrib::ComboShot)) !=
|
||||
|
||||
if ((xe8_projectileAttribs & (EProjectileAttrib::Wave | EProjectileAttrib::ComboShot)) ==
|
||||
(EProjectileAttrib::Wave | EProjectileAttrib::ComboShot)) {
|
||||
/* Not wavebuster */
|
||||
if (Explode(res.GetPoint(), res.GetPlane().normal(), crType, mgr, CDamageVulnerability::NormalVulnerabilty(),
|
||||
kInvalidUniqueId))
|
||||
mgr.ApplyDamageToWorld(xec_ownerId, *this, res.GetPoint(), x12c_curDamageInfo, xf8_filter);
|
||||
x2c2_lastResolvedObj = kInvalidUniqueId;
|
||||
return;
|
||||
}
|
||||
|
||||
// Not wavebuster
|
||||
if (Explode(res.GetPoint(), res.GetPlane().normal(), crType, mgr, CDamageVulnerability::NormalVulnerabilty(),
|
||||
kInvalidUniqueId)) {
|
||||
mgr.ApplyDamageToWorld(xec_ownerId, *this, res.GetPoint(), x12c_curDamageInfo, xf8_filter);
|
||||
}
|
||||
|
||||
x2c2_lastResolvedObj = kInvalidUniqueId;
|
||||
}
|
||||
|
||||
void CEnergyProjectile::ResolveCollisionWithActor(const CRayCastResult& res, CActor& act, CStateManager& mgr) {
|
||||
x2c2_lastResolvedObj = act.GetUniqueId();
|
||||
EWeaponCollisionResponseTypes crType = act.GetCollisionResponseType(
|
||||
res.GetPoint(), x34_transform.basis[1].normalized(), x12c_curDamageInfo.GetWeaponMode(), xe8_projectileAttribs);
|
||||
const auto crType = act.GetCollisionResponseType(res.GetPoint(), x34_transform.basis[1].normalized(),
|
||||
x12c_curDamageInfo.GetWeaponMode(), xe8_projectileAttribs);
|
||||
act.Touch(*this, mgr);
|
||||
const CDamageVulnerability* dVuln = act.GetDamageVulnerability();
|
||||
if (!Explode(res.GetPoint(), res.GetPlane().normal(), crType, mgr, *dVuln, act.GetUniqueId())) {
|
||||
|
@ -142,7 +161,7 @@ void CEnergyProjectile::ResolveCollisionWithActor(const CRayCastResult& res, CAc
|
|||
CGameProjectile::ResolveCollisionWithActor(res, act, mgr);
|
||||
ApplyDamageToActors(mgr, x12c_curDamageInfo);
|
||||
}
|
||||
if (TCastToPtr<CEnergyProjectile> proj = act) {
|
||||
if (const TCastToPtr<CEnergyProjectile> proj = act) {
|
||||
proj->Explode(GetTranslation(), x34_transform.basis[1], EWeaponCollisionResponseTypes::OtherProjectile, mgr,
|
||||
*GetDamageVulnerability(), GetUniqueId());
|
||||
}
|
||||
|
@ -151,33 +170,38 @@ void CEnergyProjectile::ResolveCollisionWithActor(const CRayCastResult& res, CAc
|
|||
void CEnergyProjectile::Think(float dt, CStateManager& mgr) {
|
||||
CWeapon::Think(dt, mgr);
|
||||
if (mgr.GetWorld()->GetCurrentAreaId() != GetAreaIdAlways() &&
|
||||
(xe8_projectileAttribs & EProjectileAttrib::ArmCannon) == EProjectileAttrib::ArmCannon)
|
||||
(xe8_projectileAttribs & EProjectileAttrib::ArmCannon) == EProjectileAttrib::ArmCannon) {
|
||||
mgr.SetActorAreaId(*this, mgr.GetWorld()->GetCurrentAreaId());
|
||||
}
|
||||
|
||||
UpdateProjectileMovement(dt, mgr);
|
||||
TUniqueId id = kInvalidUniqueId;
|
||||
CRayCastResult res = DoCollisionCheck(id, mgr);
|
||||
const CRayCastResult res = DoCollisionCheck(id, mgr);
|
||||
if (res.IsValid()) {
|
||||
if (TCastToPtr<CActor> act = mgr.ObjectById(id))
|
||||
if (const TCastToPtr<CActor> act = mgr.ObjectById(id)) {
|
||||
ResolveCollisionWithActor(res, *act, mgr);
|
||||
else
|
||||
} else {
|
||||
ResolveCollisionWithWorld(res, mgr);
|
||||
}
|
||||
}
|
||||
|
||||
x170_projectile.UpdateParticleFX();
|
||||
if (x2e4_24_active && x3d0_26_)
|
||||
if (x2e4_24_active && x3d0_26_) {
|
||||
Explode(GetTranslation(), zeus::skUp, EWeaponCollisionResponseTypes::Default, mgr,
|
||||
CDamageVulnerability::NormalVulnerabilty(), kInvalidUniqueId);
|
||||
}
|
||||
|
||||
if (x2c8_projectileLight != kInvalidUniqueId) {
|
||||
if (TCastToPtr<CGameLight> light = mgr.ObjectById(x2c8_projectileLight)) {
|
||||
if (const TCastToPtr<CGameLight> light = mgr.ObjectById(x2c8_projectileLight)) {
|
||||
light->SetTransform(GetTransform());
|
||||
light->SetTranslation(GetTranslation());
|
||||
if (CElementGen* ps1 = x170_projectile.GetAttachedPS1())
|
||||
if (ps1->SystemHasLight())
|
||||
if (CElementGen* ps1 = x170_projectile.GetAttachedPS1()) {
|
||||
if (ps1->SystemHasLight()) {
|
||||
light->SetLight(ps1->GetLight());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (x2e8_sfx) {
|
||||
CSfxManager::UpdateEmitter(x2e8_sfx, x170_projectile.GetTranslation(), x170_projectile.GetVelocity(), 1.f);
|
||||
|
@ -185,22 +209,24 @@ void CEnergyProjectile::Think(float dt, CStateManager& mgr) {
|
|||
}
|
||||
|
||||
x3d4_curTime += dt;
|
||||
if (x3d4_curTime > 45.f || x170_projectile.IsSystemDeletable() || x3d0_24_dead)
|
||||
if (x3d4_curTime > 45.f || x170_projectile.IsSystemDeletable() || x3d0_24_dead) {
|
||||
mgr.FreeScriptObject(GetUniqueId());
|
||||
}
|
||||
}
|
||||
|
||||
void CEnergyProjectile::Render(CStateManager& mgr) {
|
||||
SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(FMT_STRING("CEnergyProjectile::Render WPSC_{}"), x2cc_wpscId).c_str(), zeus::skOrange);
|
||||
|
||||
CPlayerState::EPlayerVisor visor = mgr.GetPlayerState()->GetActiveVisor(mgr);
|
||||
const auto visor = mgr.GetPlayerState()->GetActiveVisor(mgr);
|
||||
if (visor == CPlayerState::EPlayerVisor::Combat) {
|
||||
if ((xe8_projectileAttribs & EProjectileAttrib::Charged) == EProjectileAttrib::Charged ||
|
||||
(xe8_projectileAttribs & EProjectileAttrib::ComboShot) == EProjectileAttrib::ComboShot) {
|
||||
float warpTime = 1.f - float(x170_projectile.GameTime());
|
||||
if (warpTime > 0.f)
|
||||
const float warpTime = 1.f - float(x170_projectile.GameTime());
|
||||
if (warpTime > 0.f) {
|
||||
mgr.DrawSpaceWarp(GetTranslation(), warpTime * 0.75f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (visor == CPlayerState::EPlayerVisor::XRay) {
|
||||
CElementGen::SetSubtractBlend((xe8_projectileAttribs & EProjectileAttrib::Ice) != EProjectileAttrib::Ice);
|
||||
|
@ -222,11 +248,12 @@ void CEnergyProjectile::Render(CStateManager& mgr) {
|
|||
}
|
||||
|
||||
void CEnergyProjectile::AddToRenderer(const zeus::CFrustum& frustum, CStateManager& mgr) {
|
||||
auto bounds = x170_projectile.GetBounds();
|
||||
if (bounds && !frustum.aabbFrustumTest(*bounds))
|
||||
const auto bounds = x170_projectile.GetBounds();
|
||||
if (bounds && !frustum.aabbFrustumTest(*bounds)) {
|
||||
return;
|
||||
}
|
||||
|
||||
CPlayerState::EPlayerVisor visor = mgr.GetPlayerState()->GetActiveVisor(mgr);
|
||||
const auto visor = mgr.GetPlayerState()->GetActiveVisor(mgr);
|
||||
if (visor != CPlayerState::EPlayerVisor::XRay &&
|
||||
((xe8_projectileAttribs & EProjectileAttrib::Ice) != EProjectileAttrib::Ice ||
|
||||
mgr.GetThermalDrawFlag() != EThermalDrawFlag::Hot)) {
|
||||
|
@ -247,7 +274,8 @@ bool CEnergyProjectile::Explode(const zeus::CVector3f& pos, const zeus::CVector3
|
|||
bool retargetPlayer = false;
|
||||
bool deflect = false;
|
||||
zeus::CVector3f targetPos;
|
||||
EVulnerability vulnType = dVuln.GetVulnerability(x12c_curDamageInfo.GetWeaponMode(), false);
|
||||
const EVulnerability vulnType = dVuln.GetVulnerability(x12c_curDamageInfo.GetWeaponMode(), false);
|
||||
|
||||
if (vulnType == EVulnerability::Deflect) {
|
||||
deflect = true;
|
||||
EDeflectType deflectType = dVuln.GetDeflectionType(x12c_curDamageInfo.GetWeaponMode());
|
||||
|
@ -259,17 +287,19 @@ bool CEnergyProjectile::Explode(const zeus::CVector3f& pos, const zeus::CVector3
|
|||
case EDeflectType::Three:
|
||||
if (deflectType != EDeflectType::Two ||
|
||||
(xf0_weaponType != EWeaponType::Missile &&
|
||||
(xe8_projectileAttribs & EProjectileAttrib::ComboShot) != EProjectileAttrib::ComboShot))
|
||||
if (xf8_filter.GetExcludeList().HasMaterial(EMaterialTypes::Player))
|
||||
(xe8_projectileAttribs & EProjectileAttrib::ComboShot) != EProjectileAttrib::ComboShot)) {
|
||||
if (xf8_filter.GetExcludeList().HasMaterial(EMaterialTypes::Player)) {
|
||||
retargetPlayer = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (retargetPlayer) {
|
||||
float ang = mgr.GetActiveRandom()->Range(0.f, 2.f * M_PIF);
|
||||
float y = std::sin(ang);
|
||||
float x = std::cos(ang);
|
||||
const float ang = mgr.GetActiveRandom()->Range(0.f, 2.f * M_PIF);
|
||||
const float y = std::sin(ang);
|
||||
const float x = std::cos(ang);
|
||||
targetPos = mgr.GetPlayer().GetAimPosition(mgr, 0.f) + zeus::CVector3f(x, 0.f, y);
|
||||
ChangeProjectileOwner(hitActor, mgr);
|
||||
}
|
||||
|
@ -278,7 +308,8 @@ bool CEnergyProjectile::Explode(const zeus::CVector3f& pos, const zeus::CVector3
|
|||
if (vulnType != EVulnerability::Immune && !deflect) {
|
||||
deflect =
|
||||
(type == EWeaponCollisionResponseTypes::Unknown15 || type == EWeaponCollisionResponseTypes::EnemyShielded ||
|
||||
(type >= EWeaponCollisionResponseTypes::Unknown69 && type <= EWeaponCollisionResponseTypes::AtomicAlphaReflect));
|
||||
(type >= EWeaponCollisionResponseTypes::Unknown69 &&
|
||||
type <= EWeaponCollisionResponseTypes::AtomicAlphaReflect));
|
||||
}
|
||||
|
||||
SetTranslation(offsetPos);
|
||||
|
@ -309,29 +340,30 @@ bool CEnergyProjectile::Explode(const zeus::CVector3f& pos, const zeus::CVector3
|
|||
zeus::CVector3f scale = zeus::skOne3f;
|
||||
bool camClose = false;
|
||||
if (mgr.GetPlayer().GetCameraState() == CPlayer::EPlayerCameraState::FirstPerson) {
|
||||
float mag = (offsetPos - mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTranslation()).magnitude();
|
||||
const float mag = (offsetPos - mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTranslation()).magnitude();
|
||||
if (mag < 4.f) {
|
||||
scale = zeus::CVector3f(0.75f * (mag * 0.25f) + 0.25f);
|
||||
camClose = true;
|
||||
}
|
||||
}
|
||||
u32 explodeFlags = 0x8;
|
||||
if ((xe8_projectileAttribs & EProjectileAttrib::Ice) == EProjectileAttrib::Ice)
|
||||
if ((xe8_projectileAttribs & EProjectileAttrib::Ice) == EProjectileAttrib::Ice) {
|
||||
explodeFlags |= 0x4;
|
||||
if (camClose)
|
||||
}
|
||||
if (camClose) {
|
||||
explodeFlags |= 0x2;
|
||||
CEntityInfo explosionInfo(GetAreaIdAlways(), CEntity::NullConnectionList);
|
||||
CExplosion* explosion =
|
||||
new CExplosion(*particle, mgr.AllocateUniqueId(), true, explosionInfo, "Projectile collision response",
|
||||
particleXf, explodeFlags, scale, zeus::skWhite);
|
||||
}
|
||||
const CEntityInfo explosionInfo(GetAreaIdAlways(), CEntity::NullConnectionList);
|
||||
auto* explosion = new CExplosion(*particle, mgr.AllocateUniqueId(), true, explosionInfo,
|
||||
"Projectile collision response", particleXf, explodeFlags, scale, zeus::skWhite);
|
||||
mgr.AddObject(explosion);
|
||||
if (TCastToPtr<CActor> hActor = mgr.ObjectById(hitActor)) {
|
||||
if (const TCastToPtr<CActor> hActor = mgr.ObjectById(hitActor)) {
|
||||
bool validPlat = false;
|
||||
CScriptPlatform* plat = TCastToPtr<CScriptPlatform>(hActor.GetPtr()).GetPtr();
|
||||
validPlat = plat != nullptr;
|
||||
if (!validPlat && hActor->GetMaterialList().HasMaterial(EMaterialTypes::Bomb)) {
|
||||
for (CEntity* ent : mgr.GetPlatformAndDoorObjectList()) {
|
||||
if (TCastToPtr<CScriptPlatform> otherPlat = ent) {
|
||||
if (const TCastToPtr<CScriptPlatform> otherPlat = ent) {
|
||||
if (otherPlat->IsSlave(hitActor)) {
|
||||
plat = otherPlat.GetPtr();
|
||||
validPlat = true;
|
||||
|
@ -340,22 +372,24 @@ bool CEnergyProjectile::Explode(const zeus::CVector3f& pos, const zeus::CVector3
|
|||
}
|
||||
}
|
||||
}
|
||||
if (validPlat)
|
||||
if (validPlat) {
|
||||
plat->AddSlave(explosion->GetUniqueId(), mgr);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
x3d0_24_dead = true;
|
||||
}
|
||||
|
||||
if ((xe8_projectileAttribs & (EProjectileAttrib::ComboShot | EProjectileAttrib::Ice)) ==
|
||||
(EProjectileAttrib::ComboShot | EProjectileAttrib::Ice)) {
|
||||
/* Ice Spreader */
|
||||
TLockedToken<CGenDescription> iceSpreadParticle = g_SimplePool->GetObj("IceSpread1");
|
||||
// Ice Spreader
|
||||
const TLockedToken<CGenDescription> iceSpreadParticle = g_SimplePool->GetObj("IceSpread1");
|
||||
|
||||
u32 flags = (xe6_27_thermalVisorFlags & 0x2) == 0 ? 1 : 0;
|
||||
flags |= 0x2;
|
||||
CIceImpact* iceImpact =
|
||||
new CIceImpact(iceSpreadParticle, mgr.AllocateUniqueId(), GetAreaIdAlways(), true, "Ice spread explosion",
|
||||
particleXf, flags, zeus::skOne3f, zeus::skWhite);
|
||||
|
||||
auto* iceImpact = new CIceImpact(iceSpreadParticle, mgr.AllocateUniqueId(), GetAreaIdAlways(), true,
|
||||
"Ice spread explosion", particleXf, flags, zeus::skOne3f, zeus::skWhite);
|
||||
mgr.AddObject(iceImpact);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,8 +83,7 @@ void CFluidPlane::AddRipple(const CRipple& ripple, const CScriptWater& water, CS
|
|||
mgr.GetFluidPlaneManager()->RippleManager().AddRipple(ripple);
|
||||
}
|
||||
|
||||
void CFluidPlane::RenderStripWithRipples(float curY, const CFluidPlaneRender::SHFieldSample (&heights)[46][46],
|
||||
const u8 (&flags)[9][9], int startYDiv,
|
||||
void CFluidPlane::RenderStripWithRipples(float curY, const Heights& heights, const Flags& flags, int startYDiv,
|
||||
const CFluidPlaneRender::SPatchInfo& info,
|
||||
std::vector<CFluidPlaneShader::Vertex>& vOut,
|
||||
std::vector<CFluidPlaneShader::PatchVertex>& pvOut) {
|
||||
|
@ -310,8 +309,7 @@ void CFluidPlane::RenderStripWithRipples(float curY, const CFluidPlaneRender::SH
|
|||
}
|
||||
}
|
||||
|
||||
void CFluidPlane::RenderPatch(const CFluidPlaneRender::SPatchInfo& info,
|
||||
const CFluidPlaneRender::SHFieldSample (&heights)[46][46], const u8 (&flags)[9][9],
|
||||
void CFluidPlane::RenderPatch(const CFluidPlaneRender::SPatchInfo& info, const Heights& heights, const Flags& flags,
|
||||
bool noRipples, bool flagIs1, std::vector<CFluidPlaneShader::Vertex>& vOut,
|
||||
std::vector<CFluidPlaneShader::PatchVertex>& pvOut) {
|
||||
if (noRipples) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
@ -84,10 +85,10 @@ public:
|
|||
|
||||
struct SRippleInfo {
|
||||
const CRipple& x0_ripple;
|
||||
int x4_fromX;
|
||||
int x8_toX;
|
||||
int xc_fromY;
|
||||
int x10_toY;
|
||||
int x4_fromX = 0;
|
||||
int x8_toX = 0;
|
||||
int xc_fromY = 0;
|
||||
int x10_toY = 0;
|
||||
int x14_gfromX;
|
||||
int x18_gtoX;
|
||||
int x1c_gfromY;
|
||||
|
@ -116,6 +117,10 @@ public:
|
|||
};
|
||||
|
||||
class CFluidPlane {
|
||||
public:
|
||||
using Flags = std::array<std::array<u8, 9>, 9>;
|
||||
using Heights = std::array<std::array<CFluidPlaneRender::SHFieldSample, 46>, 46>;
|
||||
|
||||
protected:
|
||||
CAssetId x4_texPattern1Id;
|
||||
CAssetId x8_texPattern2Id;
|
||||
|
@ -135,12 +140,12 @@ protected:
|
|||
float ProjectRippleVelocity(float baseI, float velDot) const;
|
||||
float CalculateRippleIntensity(float baseI) const;
|
||||
|
||||
virtual void RenderStripWithRipples(float curY, const CFluidPlaneRender::SHFieldSample (&heights)[46][46],
|
||||
const u8 (&flags)[9][9], int startYDiv, const CFluidPlaneRender::SPatchInfo& info,
|
||||
virtual void RenderStripWithRipples(float curY, const Heights& heights, const Flags& flags, int startYDiv,
|
||||
const CFluidPlaneRender::SPatchInfo& info,
|
||||
std::vector<CFluidPlaneShader::Vertex>& vOut,
|
||||
std::vector<CFluidPlaneShader::PatchVertex>& pvOut);
|
||||
void RenderPatch(const CFluidPlaneRender::SPatchInfo& info, const CFluidPlaneRender::SHFieldSample (&heights)[46][46],
|
||||
const u8 (&flags)[9][9], bool noRipples, bool flagIs1, std::vector<CFluidPlaneShader::Vertex>& vOut,
|
||||
void RenderPatch(const CFluidPlaneRender::SPatchInfo& info, const Heights& heights, const Flags& flags,
|
||||
bool noRipples, bool flagIs1, std::vector<CFluidPlaneShader::Vertex>& vOut,
|
||||
std::vector<CFluidPlaneShader::PatchVertex>& pvOut);
|
||||
|
||||
public:
|
||||
|
|
|
@ -110,14 +110,15 @@ void CFluidPlaneCPU::CalculateLightmapMatrix(const zeus::CTransform& areaXf, con
|
|||
}
|
||||
|
||||
static bool sSineWaveInitialized = false;
|
||||
static float sGlobalSineWave[256] = {};
|
||||
static const float* InitializeSineWave() {
|
||||
if (sSineWaveInitialized)
|
||||
return sGlobalSineWave;
|
||||
for (int i = 0; i < 256; ++i)
|
||||
sGlobalSineWave[i] = std::sin(2.f * M_PIF * (i / 256.f));
|
||||
static CFluidPlaneCPU::SineTable sGlobalSineWave{};
|
||||
static void InitializeSineWave() {
|
||||
if (sSineWaveInitialized) {
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < sGlobalSineWave.size(); ++i) {
|
||||
sGlobalSineWave[i] = std::sin(2.f * M_PIF * (float(i) / 256.f));
|
||||
}
|
||||
sSineWaveInitialized = true;
|
||||
return sGlobalSineWave;
|
||||
}
|
||||
|
||||
#define kEnableWaterBumpMaps true
|
||||
|
@ -303,8 +304,7 @@ bool CFluidPlaneCPU::PrepareRipple(const CRipple& ripple, const CFluidPlaneRende
|
|||
return !(rippleOut.x14_gfromX > rippleOut.x18_gtoX || rippleOut.x1c_gfromY > rippleOut.x20_gtoY);
|
||||
}
|
||||
|
||||
void CFluidPlaneCPU::ApplyTurbulence(float t, CFluidPlaneRender::SHFieldSample (&heights)[46][46],
|
||||
const u8 (&flags)[9][9], const float sineWave[256],
|
||||
void CFluidPlaneCPU::ApplyTurbulence(float t, Heights& heights, const Flags& flags, const SineTable& sineWave,
|
||||
const CFluidPlaneRender::SPatchInfo& info,
|
||||
const zeus::CVector3f& areaCenter) const {
|
||||
if (!HasTurbulence()) {
|
||||
|
@ -334,9 +334,8 @@ void CFluidPlaneCPU::ApplyTurbulence(float t, CFluidPlaneRender::SHFieldSample (
|
|||
}
|
||||
}
|
||||
|
||||
void CFluidPlaneCPU::ApplyRipple(const CFluidPlaneRender::SRippleInfo& rippleInfo,
|
||||
CFluidPlaneRender::SHFieldSample (&heights)[46][46], u8 (&flags)[9][9],
|
||||
const float sineWave[256], const CFluidPlaneRender::SPatchInfo& info) const {
|
||||
void CFluidPlaneCPU::ApplyRipple(const CFluidPlaneRender::SRippleInfo& rippleInfo, Heights& heights, Flags& flags,
|
||||
const SineTable& sineWave, const CFluidPlaneRender::SPatchInfo& info) const {
|
||||
float lookupT = 256.f *
|
||||
(1.f - rippleInfo.x0_ripple.GetTime() * rippleInfo.x0_ripple.GetOOTimeFalloff() *
|
||||
rippleInfo.x0_ripple.GetOOTimeFalloff()) *
|
||||
|
@ -409,8 +408,9 @@ void CFluidPlaneCPU::ApplyRipple(const CFluidPlaneRender::SRippleInfo& rippleInf
|
|||
|
||||
float divDist = (divDistSq != 0.f) ? std::sqrt(divDistSq) : 0.f;
|
||||
if (u8 rippleV = CFluidPlaneManager::RippleValues[lifeIdx][int(divDist * distFalloff)]) {
|
||||
heights[k][l].height += rippleV * rippleInfo.x0_ripple.GetLookupAmplitude() *
|
||||
sineWave[int(divDist * rippleInfo.x0_ripple.GetLookupPhase() + lookupT) & 0xff];
|
||||
heights[k][l].height +=
|
||||
rippleV * rippleInfo.x0_ripple.GetLookupAmplitude() *
|
||||
sineWave[size_t(divDist * rippleInfo.x0_ripple.GetLookupPhase() + lookupT) & 0xff];
|
||||
} else {
|
||||
heights[k][l].height += 0.f;
|
||||
}
|
||||
|
@ -460,8 +460,9 @@ void CFluidPlaneCPU::ApplyRipple(const CFluidPlaneRender::SRippleInfo& rippleInf
|
|||
|
||||
float divDist = (divDistSq != 0.f) ? std::sqrt(divDistSq) : 0.f;
|
||||
if (u8 rippleV = CFluidPlaneManager::RippleValues[lifeIdx][int(divDist * distFalloff)]) {
|
||||
heights[k][l].height += rippleV * rippleInfo.x0_ripple.GetLookupAmplitude() *
|
||||
sineWave[int(divDist * rippleInfo.x0_ripple.GetLookupPhase() + lookupT) & 0xff];
|
||||
heights[k][l].height +=
|
||||
rippleV * rippleInfo.x0_ripple.GetLookupAmplitude() *
|
||||
sineWave[size_t(divDist * rippleInfo.x0_ripple.GetLookupPhase() + lookupT) & 0xff];
|
||||
} else {
|
||||
heights[k][l].height += 0.f;
|
||||
}
|
||||
|
@ -485,8 +486,8 @@ void CFluidPlaneCPU::ApplyRipple(const CFluidPlaneRender::SRippleInfo& rippleInf
|
|||
}
|
||||
|
||||
void CFluidPlaneCPU::ApplyRipples(const rstl::reserved_vector<CFluidPlaneRender::SRippleInfo, 32>& rippleInfos,
|
||||
CFluidPlaneRender::SHFieldSample (&heights)[46][46], u8 (&flags)[9][9],
|
||||
const float sineWave[256], const CFluidPlaneRender::SPatchInfo& info) const {
|
||||
Heights& heights, Flags& flags, const SineTable& sineWave,
|
||||
const CFluidPlaneRender::SPatchInfo& info) const {
|
||||
for (const CFluidPlaneRender::SRippleInfo& rippleInfo : rippleInfos)
|
||||
ApplyRipple(rippleInfo, heights, flags, sineWave, info);
|
||||
for (int i = 0; i < CFluidPlaneRender::numTilesInHField; ++i)
|
||||
|
@ -499,7 +500,7 @@ void CFluidPlaneCPU::ApplyRipples(const rstl::reserved_vector<CFluidPlaneRender:
|
|||
flags[CFluidPlaneRender::numTilesInHField + 1][i + 1] |= 2;
|
||||
}
|
||||
|
||||
void CFluidPlaneCPU::UpdatePatchNoNormals(CFluidPlaneRender::SHFieldSample (&heights)[46][46], const u8 (&flags)[9][9],
|
||||
void CFluidPlaneCPU::UpdatePatchNoNormals(Heights& heights, const Flags& flags,
|
||||
const CFluidPlaneRender::SPatchInfo& info) {
|
||||
for (int i = 1; i <= (info.x1_ySubdivs + CFluidPlaneRender::numSubdivisionsInTile - 2) /
|
||||
CFluidPlaneRender::numSubdivisionsInTile;
|
||||
|
@ -558,8 +559,8 @@ void CFluidPlaneCPU::UpdatePatchNoNormals(CFluidPlaneRender::SHFieldSample (&hei
|
|||
}
|
||||
}
|
||||
|
||||
void CFluidPlaneCPU::UpdatePatchWithNormals(CFluidPlaneRender::SHFieldSample (&heights)[46][46],
|
||||
const u8 (&flags)[9][9], const CFluidPlaneRender::SPatchInfo& info) {
|
||||
void CFluidPlaneCPU::UpdatePatchWithNormals(Heights& heights, const Flags& flags,
|
||||
const CFluidPlaneRender::SPatchInfo& info) {
|
||||
float normalScale = -(2.f * info.x18_rippleResolution);
|
||||
float nz = 0.25f * 2.f * info.x18_rippleResolution;
|
||||
int curGridY = info.x2e_tileY * info.x2a_gridDimX - 1 + info.x28_tileX;
|
||||
|
@ -696,11 +697,9 @@ void CFluidPlaneCPU::UpdatePatchWithNormals(CFluidPlaneRender::SHFieldSample (&h
|
|||
}
|
||||
}
|
||||
|
||||
bool CFluidPlaneCPU::UpdatePatch(float time, const CFluidPlaneRender::SPatchInfo& info,
|
||||
CFluidPlaneRender::SHFieldSample (&heights)[46][46], u8 (&flags)[9][9],
|
||||
const zeus::CVector3f& areaCenter,
|
||||
const std::optional<CRippleManager>& rippleManager, int fromX, int toX,
|
||||
int fromY, int toY) const {
|
||||
bool CFluidPlaneCPU::UpdatePatch(float time, const CFluidPlaneRender::SPatchInfo& info, Heights& heights, Flags& flags,
|
||||
const zeus::CVector3f& areaCenter, const std::optional<CRippleManager>& rippleManager,
|
||||
int fromX, int toX, int fromY, int toY) const {
|
||||
rstl::reserved_vector<CFluidPlaneRender::SRippleInfo, 32> rippleInfos;
|
||||
if (rippleManager) {
|
||||
for (const CRipple& ripple : rippleManager->GetRipples()) {
|
||||
|
@ -730,10 +729,10 @@ bool CFluidPlaneCPU::UpdatePatch(float time, const CFluidPlaneRender::SPatchInfo
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Used to be part of locked cache
|
||||
* These are too big for stack allocation */
|
||||
static CFluidPlaneRender::SHFieldSample lc_heights[46][46] = {};
|
||||
static u8 lc_flags[9][9] = {};
|
||||
// Used to be part of locked cache
|
||||
// These are too big for stack allocation
|
||||
static CFluidPlane::Heights lc_heights{};
|
||||
static CFluidPlane::Flags lc_flags{};
|
||||
|
||||
void CFluidPlaneCPU::Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf,
|
||||
const zeus::CTransform& areaXf, bool noNormals, const zeus::CFrustum& frustum,
|
||||
|
|
|
@ -12,6 +12,9 @@ namespace urde {
|
|||
class CFluidUVMotion;
|
||||
|
||||
class CFluidPlaneCPU : public CFluidPlane {
|
||||
public:
|
||||
using SineTable = std::array<float, 256>;
|
||||
|
||||
protected:
|
||||
class CTurbulence {
|
||||
float x0_speed;
|
||||
|
@ -60,28 +63,22 @@ protected:
|
|||
u32 m_maxVertCount;
|
||||
bool m_tessellation = false;
|
||||
|
||||
bool m_cachedDoubleLightmapBlend;
|
||||
bool m_cachedAdditive;
|
||||
bool m_cachedDoubleLightmapBlend = false;
|
||||
bool m_cachedAdditive = false;
|
||||
|
||||
static bool PrepareRipple(const CRipple& ripple, const CFluidPlaneRender::SPatchInfo& info,
|
||||
CFluidPlaneRender::SRippleInfo& rippleOut);
|
||||
void ApplyTurbulence(float t, CFluidPlaneRender::SHFieldSample (&heights)[46][46], const u8 (&flags)[9][9],
|
||||
const float sineWave[256], const CFluidPlaneRender::SPatchInfo& info,
|
||||
const zeus::CVector3f& areaCenter) const;
|
||||
void ApplyRipple(const CFluidPlaneRender::SRippleInfo& rippleInfo,
|
||||
CFluidPlaneRender::SHFieldSample (&heights)[46][46], u8 (&flags)[9][9], const float sineWave[256],
|
||||
const CFluidPlaneRender::SPatchInfo& info) const;
|
||||
void ApplyRipples(const rstl::reserved_vector<CFluidPlaneRender::SRippleInfo, 32>& rippleInfos,
|
||||
CFluidPlaneRender::SHFieldSample (&heights)[46][46], u8 (&flags)[9][9], const float sineWave[256],
|
||||
const CFluidPlaneRender::SPatchInfo& info) const;
|
||||
static void UpdatePatchNoNormals(CFluidPlaneRender::SHFieldSample (&heights)[46][46], const u8 (&flags)[9][9],
|
||||
const CFluidPlaneRender::SPatchInfo& info);
|
||||
static void UpdatePatchWithNormals(CFluidPlaneRender::SHFieldSample (&heights)[46][46], const u8 (&flags)[9][9],
|
||||
const CFluidPlaneRender::SPatchInfo& info);
|
||||
bool UpdatePatch(float time, const CFluidPlaneRender::SPatchInfo& info,
|
||||
CFluidPlaneRender::SHFieldSample (&heights)[46][46], u8 (&flags)[9][9],
|
||||
const zeus::CVector3f& areaCenter, const std::optional<CRippleManager>& rippleManager,
|
||||
int fromX, int toX, int fromY, int toY) const;
|
||||
void ApplyTurbulence(float t, Heights& heights, const Flags& flags, const SineTable& sineWave,
|
||||
const CFluidPlaneRender::SPatchInfo& info, const zeus::CVector3f& areaCenter) const;
|
||||
void ApplyRipple(const CFluidPlaneRender::SRippleInfo& rippleInfo, Heights& heights, Flags& flags,
|
||||
const SineTable& sineWave, const CFluidPlaneRender::SPatchInfo& info) const;
|
||||
void ApplyRipples(const rstl::reserved_vector<CFluidPlaneRender::SRippleInfo, 32>& rippleInfos, Heights& heights,
|
||||
Flags& flags, const SineTable& sineWave, const CFluidPlaneRender::SPatchInfo& info) const;
|
||||
static void UpdatePatchNoNormals(Heights& heights, const Flags& flags, const CFluidPlaneRender::SPatchInfo& info);
|
||||
static void UpdatePatchWithNormals(Heights& heights, const Flags& flags, const CFluidPlaneRender::SPatchInfo& info);
|
||||
bool UpdatePatch(float time, const CFluidPlaneRender::SPatchInfo& info, Heights& heights, Flags& flags,
|
||||
const zeus::CVector3f& areaCenter, const std::optional<CRippleManager>& rippleManager, int fromX,
|
||||
int toX, int fromY, int toY) const;
|
||||
|
||||
public:
|
||||
CFluidPlaneCPU(CAssetId texPattern1, CAssetId texPattern2, CAssetId texColor, CAssetId bumpMap, CAssetId envMap,
|
||||
|
|
|
@ -51,10 +51,10 @@ CFluidPlaneShader::RenderSetupInfo CFluidPlaneDoor::RenderSetup(const CStateMana
|
|||
return out;
|
||||
}
|
||||
|
||||
/* Used to be part of locked cache
|
||||
* These are too big for stack allocation */
|
||||
static CFluidPlaneRender::SHFieldSample lc_heights[46][46] = {};
|
||||
static u8 lc_flags[9][9] = {};
|
||||
// Used to be part of locked cache
|
||||
// These are too big for stack allocation
|
||||
static CFluidPlane::Heights lc_heights{};
|
||||
static CFluidPlane::Flags lc_flags{};
|
||||
|
||||
void CFluidPlaneDoor::Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb,
|
||||
const zeus::CTransform& xf, const zeus::CTransform& areaXf, bool noNormals,
|
||||
|
|
|
@ -17,8 +17,7 @@ CFluidPlaneGPU::CFluidPlaneGPU(CAssetId texPattern1, CAssetId texPattern2, CAsse
|
|||
m_tessellation = true;
|
||||
}
|
||||
|
||||
void CFluidPlaneGPU::RenderStripWithRipples(float curY, const CFluidPlaneRender::SHFieldSample (&heights)[46][46],
|
||||
const u8 (&flags)[9][9], int startYDiv,
|
||||
void CFluidPlaneGPU::RenderStripWithRipples(float curY, const Heights& heights, const Flags& flags, int startYDiv,
|
||||
const CFluidPlaneRender::SPatchInfo& info,
|
||||
std::vector<CFluidPlaneShader::Vertex>& vOut,
|
||||
std::vector<CFluidPlaneShader::PatchVertex>& pvOut) {
|
||||
|
|
|
@ -17,9 +17,8 @@ public:
|
|||
float turbAmplitudeMin, float specularMin, float specularMax, float reflectionBlend,
|
||||
float reflectionSize, float rippleIntensity, u32 maxVertCount);
|
||||
|
||||
void RenderStripWithRipples(float curY, const CFluidPlaneRender::SHFieldSample (&heights)[46][46],
|
||||
const u8 (&flags)[9][9], int startYDiv, const CFluidPlaneRender::SPatchInfo& info,
|
||||
std::vector<CFluidPlaneShader::Vertex>& vOut,
|
||||
void RenderStripWithRipples(float curY, const Heights& heights, const Flags& flags, int startYDiv,
|
||||
const CFluidPlaneRender::SPatchInfo& info, std::vector<CFluidPlaneShader::Vertex>& vOut,
|
||||
std::vector<CFluidPlaneShader::PatchVertex>& pvOut) override;
|
||||
};
|
||||
|
||||
|
|
|
@ -283,8 +283,9 @@ CMorphBall::CMorphBall(CPlayer& player, float radius)
|
|||
|
||||
kSpiderBallCollisionRadius = GetBallRadius() + 0.2f;
|
||||
|
||||
for (int i = 0; i < 32; ++i)
|
||||
for (size_t i = 0; i < x19e4_spiderElectricGens.capacity(); ++i) {
|
||||
x19e4_spiderElectricGens.emplace_back(std::make_unique<CParticleSwoosh>(x19a0_spiderElectric, 0), false);
|
||||
}
|
||||
|
||||
LoadAnimationTokens("SamusBallANCS");
|
||||
InitializeWakeEffects();
|
||||
|
@ -303,10 +304,9 @@ void CMorphBall::LoadAnimationTokens(std::string_view ancsName) {
|
|||
}
|
||||
|
||||
void CMorphBall::InitializeWakeEffects() {
|
||||
TToken<CGenDescription> nullParticle =
|
||||
const TToken<CGenDescription> nullParticle =
|
||||
CToken(TObjOwnerDerivedFromIObj<CGenDescription>::GetNewDerivedObject(std::make_unique<CGenDescription>()));
|
||||
for (int i = 0; i < 8; ++i)
|
||||
x1b84_wakeEffects.push_back(nullParticle);
|
||||
x1b84_wakeEffects.resize(x1b84_wakeEffects.capacity(), nullParticle);
|
||||
|
||||
x1b84_wakeEffects[2] = g_SimplePool->GetObj("DirtWake");
|
||||
x1b84_wakeEffects[0] = g_SimplePool->GetObj("PhazonWake");
|
||||
|
@ -317,7 +317,7 @@ void CMorphBall::InitializeWakeEffects() {
|
|||
x1b84_wakeEffects[6] = g_SimplePool->GetObj("SandWake");
|
||||
x1b84_wakeEffects[7] = g_SimplePool->GetObj("RainWake");
|
||||
|
||||
x1bc8_wakeEffectGens.resize(8);
|
||||
x1bc8_wakeEffectGens.resize(x1b84_wakeEffects.capacity());
|
||||
x1bc8_wakeEffectGens[2] = std::make_unique<CElementGen>(x1b84_wakeEffects[2]);
|
||||
x1bc8_wakeEffectGens[0] = std::make_unique<CElementGen>(x1b84_wakeEffects[0]);
|
||||
x1bc8_wakeEffectGens[1] = std::make_unique<CElementGen>(x1b84_wakeEffects[1]);
|
||||
|
|
|
@ -27,7 +27,7 @@ private:
|
|||
CPFArea* x0_area;
|
||||
rstl::reserved_vector<zeus::CVector3f, 16> x4_waypoints;
|
||||
u32 xc8_curWaypoint = 0;
|
||||
EResult xcc_result;
|
||||
EResult xcc_result{};
|
||||
float xd0_chHeight;
|
||||
float xd4_chRadius;
|
||||
float xd8_padding = 10.f;
|
||||
|
|
|
@ -15,7 +15,7 @@ class CScriptPickup : public CPhysicsActor {
|
|||
float x268_fadeInTime;
|
||||
float x26c_lifeTime;
|
||||
float x270_curTime = 0.f;
|
||||
float x274_tractorTime;
|
||||
float x274_tractorTime = 0.f;
|
||||
float x278_delayTimer;
|
||||
TLockedToken<CGenDescription> x27c_pickupParticleDesc;
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ class CScriptSpindleCamera : public CGameCamera {
|
|||
float x328_maxAzimuthInterpTimer = 0.f;
|
||||
bool x32c_outsideClampedAzimuth = false;
|
||||
zeus::CVector3f x330_lookDir;
|
||||
bool x33c_24_inResetThink;
|
||||
bool x33c_24_inResetThink = false;
|
||||
|
||||
float GetInVar(const SSpindleProperty& seg) const { return x18c_inVars[int(seg.x4_input)]; }
|
||||
|
||||
|
|
|
@ -78,10 +78,10 @@ void CStateMachineState::Update(CStateManager& mgr, CAi& ai, float delta) {
|
|||
if (andPassed && state) {
|
||||
x4_state->CallFunc(mgr, ai, EStateMsg::Deactivate, 0.f);
|
||||
x4_state = state;
|
||||
#ifndef NDEBUG
|
||||
fmt::print(FMT_STRING("{} {} {} - {} {}\n"), ai.GetUniqueId(), ai.GetEditorId(), ai.GetName(),
|
||||
state->xc_name, int(state - x0_machine->GetStateVector().data()));
|
||||
#endif
|
||||
//#ifndef NDEBUG
|
||||
// fmt::print(FMT_STRING("{} {} {} - {} {}\n"), ai.GetUniqueId(), ai.GetEditorId(), ai.GetName(),
|
||||
// state->xc_name, int(state - x0_machine->GetStateVector().data()));
|
||||
//#endif
|
||||
x8_time = 0.f;
|
||||
x18_24_codeTrigger = false;
|
||||
xc_random = mgr.GetActiveRandom()->Float();
|
||||
|
|
|
@ -50,8 +50,8 @@ class CAiState {
|
|||
friend class CStateMachineState;
|
||||
CAiStateFunc x0_func;
|
||||
char xc_name[32] = {};
|
||||
u32 x2c_numTriggers;
|
||||
CAiTrigger* x30_firstTrigger;
|
||||
u32 x2c_numTriggers = 0;
|
||||
CAiTrigger* x30_firstTrigger = nullptr;
|
||||
|
||||
public:
|
||||
CAiState(CAiStateFunc func, const char* name) {
|
||||
|
@ -88,7 +88,7 @@ class CStateMachineState {
|
|||
float x8_time = 0.f;
|
||||
float xc_random = 0.f;
|
||||
float x10_delay = 0.f;
|
||||
float x14_;
|
||||
float x14_ = 0.f;
|
||||
bool x18_24_codeTrigger : 1;
|
||||
|
||||
public:
|
||||
|
|
|
@ -69,9 +69,9 @@ void CVisorFlare::Update(float dt, const zeus::CVector3f& pos, const CActor* act
|
|||
mgr.SetThermalColdScale2(mgr.GetThermalColdScale2() + x24_);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
printf("%08X %f %f\n", act->GetEditorId().id, x24_, x28_);
|
||||
#endif
|
||||
//#ifndef NDEBUG
|
||||
// printf("%08X %f %f\n", act->GetEditorId().id, x24_, x28_);
|
||||
//#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ public:
|
|||
CCollisionSurface x50_surface =
|
||||
CCollisionSurface(zeus::CVector3f(0.f, 0.f, 1.f), zeus::CVector3f(0.f, 1.f, 0.f),
|
||||
zeus::CVector3f(1.f, 0.f, 0.f), 0xffffffff);
|
||||
float x78_health;
|
||||
float x78_health = 0.f;
|
||||
int x7c_framesNotOnSurface : 8;
|
||||
int x7c_idx : 10;
|
||||
int x7c_remainingLaunchNotOnSurfaceFrames : 8;
|
||||
|
@ -53,6 +53,7 @@ public:
|
|||
: x0_xf(xf)
|
||||
, x7c_framesNotOnSurface(0)
|
||||
, x7c_idx(idx)
|
||||
, x7c_remainingLaunchNotOnSurfaceFrames(0)
|
||||
, x80_24_active(false)
|
||||
, x80_25_inFrustum(false)
|
||||
, x80_26_launched(false)
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
#include "Runtime/World/CWorld.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
#include "Runtime/CGameState.hpp"
|
||||
#include "Runtime/CInGameTweakManagerBase.hpp"
|
||||
#include "Runtime/CSimplePool.hpp"
|
||||
|
@ -44,17 +47,19 @@ const IGameArea* CDummyWorld::IGetAreaAlways(TAreaId id) const { return &x18_are
|
|||
TAreaId CDummyWorld::IGetCurrentAreaId() const { return x3c_curAreaId; }
|
||||
|
||||
TAreaId CDummyWorld::IGetAreaId(CAssetId id) const {
|
||||
int ret = 0;
|
||||
if (!id.IsValid())
|
||||
if (!id.IsValid()) {
|
||||
return kInvalidAreaId;
|
||||
for (const CDummyGameArea& area : x18_areas) {
|
||||
if (area.xc_mrea == id)
|
||||
return ret;
|
||||
++ret;
|
||||
}
|
||||
|
||||
const auto iter =
|
||||
std::find_if(x18_areas.cbegin(), x18_areas.cend(), [id](const auto& area) { return area.xc_mrea == id; });
|
||||
if (iter == x18_areas.cend()) {
|
||||
return kInvalidAreaId;
|
||||
}
|
||||
|
||||
return TAreaId(std::distance(x18_areas.cbegin(), iter));
|
||||
}
|
||||
|
||||
CWorld::CRelay::CRelay(CInputStream& in) {
|
||||
x0_relay = in.readUint32Big();
|
||||
x4_target = in.readUint32Big();
|
||||
|
@ -226,17 +231,19 @@ const IGameArea* CWorld::IGetAreaAlways(TAreaId id) const { return GetAreaAlways
|
|||
TAreaId CWorld::IGetCurrentAreaId() const { return x68_curAreaId; }
|
||||
|
||||
TAreaId CWorld::IGetAreaId(CAssetId id) const {
|
||||
int ret = 0;
|
||||
if (!id.IsValid())
|
||||
if (!id.IsValid()) {
|
||||
return kInvalidAreaId;
|
||||
for (const std::unique_ptr<CGameArea>& area : x18_areas) {
|
||||
if (area->x84_mrea == id)
|
||||
return ret;
|
||||
++ret;
|
||||
}
|
||||
|
||||
const auto iter =
|
||||
std::find_if(x18_areas.cbegin(), x18_areas.cend(), [id](const auto& area) { return area->x84_mrea == id; });
|
||||
if (iter == x18_areas.cend()) {
|
||||
return kInvalidAreaId;
|
||||
}
|
||||
|
||||
return TAreaId(std::distance(x18_areas.cbegin(), iter));
|
||||
}
|
||||
|
||||
void CWorld::MoveToChain(CGameArea* area, EChain chain) {
|
||||
if (area->x138_curChain == chain) {
|
||||
return;
|
||||
|
@ -705,19 +712,20 @@ bool CWorld::AreSkyNeedsMet() const {
|
|||
}
|
||||
|
||||
TAreaId CWorld::GetAreaIdForSaveId(s32 saveId) const {
|
||||
if (saveId == -1)
|
||||
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;
|
||||
}
|
||||
|
||||
if (x18_areas.empty()) {
|
||||
return kInvalidAreaId;
|
||||
}
|
||||
|
||||
const auto iter = std::find_if(x18_areas.cbegin(), x18_areas.cend(),
|
||||
[saveId](const auto& area) { return area->x88_areaId == saveId; });
|
||||
if (iter == x18_areas.cend()) {
|
||||
return kInvalidAreaId;
|
||||
}
|
||||
|
||||
return TAreaId(std::distance(x18_areas.cbegin(), iter));
|
||||
}
|
||||
} // namespace urde
|
||||
|
|
|
@ -171,7 +171,7 @@ public:
|
|||
void CycleLoadPauseState();
|
||||
|
||||
CWorld(IObjectStore& objStore, IFactory& resFactory, CAssetId mlvlId);
|
||||
~CWorld();
|
||||
~CWorld() override;
|
||||
bool DoesAreaExist(TAreaId area) const;
|
||||
const std::vector<std::unique_ptr<CGameArea>>& GetGameAreas() const { return x18_areas; }
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 2.0 MiB |
2
hecl
2
hecl
|
@ -1 +1 @@
|
|||
Subproject commit f64ed44fe8164b06ed5bef6344d9f743e2c5d638
|
||||
Subproject commit d208592b2825188940064e462038e2ce90164101
|
Loading…
Reference in New Issue