Nearly finish CScriptWater

This commit is contained in:
Jack Andersen 2017-08-12 21:56:35 -10:00
parent e0efcc0e5c
commit e25d2a423d
29 changed files with 1059 additions and 372 deletions

View File

@ -16,134 +16,151 @@ struct Water : IScriptObject
Value<atVec3f> location; Value<atVec3f> location;
Value<atVec3f> volume; Value<atVec3f> volume;
DamageInfo damageInfo; DamageInfo damageInfo;
Value<atVec3f> unknown1; Value<atVec3f> orientedForce;
Value<atUint32> unknown2; Value<atUint32> triggerFlags;
Value<bool> unknown3; Value<bool> thermalCold;
Value<bool> unknown4; Value<bool> displaySurface;
UniqueID32 texture1; UniqueID32 patternMap1;
UniqueID32 texture2; UniqueID32 patternMap2;
UniqueID32 texture3; UniqueID32 colorMap;
UniqueID32 texture4; UniqueID32 bumpMap;
UniqueID32 texture5; UniqueID32 envMap;
UniqueID32 texture6; UniqueID32 envBumpMap;
Value<atVec3f> unknown5; Value<atVec3f> bumpLightDir;
Value<float> unknown6; Value<float> bumpScale;
Value<float> unknown7; Value<float> morphInTime;
Value<float> unknown8; Value<float> morphOutTime;
Value<bool> unknown9; Value<bool> active;
Value<atUint32> unknown10; Value<atUint32> fluidType;
Value<bool> unknown11; Value<bool> unknownBool;
Value<float> unknown12; Value<float> alpha;
struct FluidUVMotion : BigYAML struct FluidUVMotion : BigYAML
{ {
DECL_YAML DECL_YAML
struct FluidLayerMotion : BigYAML struct FluidLayerMotion : BigYAML
{ {
DECL_YAML DECL_YAML
Value<atUint32> unknown1; Value<atUint32> motionType;
Value<float> unknown2; Value<float> timeToWrap;
Value<float> unknown3; Value<float> orientation;
Value<float> unknown4; Value<float> magnitude;
Value<float> unknown5; Value<float> uvMul;
}; };
/* BIG FAT WARNING: Do NOT re-order these, even if they seem incorrect */ FluidLayerMotion pattern1Layer;
FluidLayerMotion layer2; FluidLayerMotion pattern2Layer;
FluidLayerMotion layer3; FluidLayerMotion colorLayer;
FluidLayerMotion layer1; Value<float> timeToWrap;
Value<float> unknown1; Value<float> orientation;
Value<float> unknown2;
} fluidUVMotion; } fluidUVMotion;
Value<float> unknown13; Value<float> turbulenceSpeed;
Value<float> unknown14; Value<float> turbulenceDistance;
Value<float> unknown15; Value<float> turbulenceFrequencyMax;
Value<float> unknown16; Value<float> turbulenceFrequencyMin;
Value<float> unknown17; Value<float> turbulencePhaseMax;
Value<float> unknown18; Value<float> turbulencePhaseMin;
Value<float> unknown19; Value<float> turbulenceAmplitudeMax;
Value<float> unknown20; Value<float> turbulenceAmplitudeMin;
Value<atVec4f> unknown21; Value<atVec4f> splashColor;
Value<atVec4f> unknown22; Value<atVec4f> unkColor;
UniqueID32 particle1; UniqueID32 splashParticle1;
UniqueID32 particle2; UniqueID32 splashParticle2;
UniqueID32 particle3; UniqueID32 splashParticle3;
UniqueID32 particle4; UniqueID32 particle4;
UniqueID32 particle5; UniqueID32 particle5;
Value<atUint32> soundID1; // needs verification Value<atUint32> unkSfx;
Value<atUint32> soundID2; // needs verification Value<atUint32> visorRunoffSfx;
Value<atUint32> soundID3; // needs verification Value<atUint32> splashSfx1;
Value<atUint32> soundID4; // needs verification Value<atUint32> splashSfx2;
Value<atUint32> soundID5; // needs verification Value<atUint32> splashSfx3;
Value<float> unknown23; Value<float> tileSize;
Value<atUint32> unknown24; Value<atUint32> tileSubdivisions;
Value<float> unknown25; Value<float> specularMin;
Value<float> unknown26; Value<float> specularMax;
Value<float> unknown27; Value<float> reflectionSize;
Value<float> unknown28; Value<float> rippleIntensity;
Value<float> unknown29; Value<float> reflectionBlend;
Value<float> unknown30; Value<float> fogBias;
Value<float> unknown31; Value<float> fogMagnitude;
Value<float> unknown32; Value<float> fogSpeed;
Value<atVec4f> unknown33; // CColor Value<atVec4f> fogColor; // CColor
UniqueID32 texture34; UniqueID32 lightmap;
Value<float> unknown35; Value<float> unitsPerLightmapTexel;
Value<float> unknown36; Value<float> alphaInTime;
Value<float> unknown37; Value<float> alphaOutTime;
Value<atUint32> unknown38; Value<atUint32> unusedInt1;
Value<atUint32> unknown39; Value<atUint32> unusedInt2;
Value<bool> unknown40;
struct UnusedBitset : BigYAML
{
Delete _d;
void read(athena::io::IStreamReader& in)
{
if (in.readBool())
{
atUint32 bitVal0 = in.readUint16Big();
atUint32 bitVal1 = in.readUint16Big();
atUint32 len = ((bitVal0 * bitVal1) + 31) / 31;
in.seek(len * 4);
}
}
void write(athena::io::IStreamWriter& out) const { out.writeBool(false); }
void read(athena::io::YAMLDocReader& reader) {}
void write(athena::io::YAMLDocWriter& writer) const {}
size_t binarySize(size_t __isz) const { return __isz + 1; }
} unusedBitset;
void nameIDs(PAKRouter<PAKBridge>& pakRouter) const void nameIDs(PAKRouter<PAKBridge>& pakRouter) const
{ {
if (texture1) if (patternMap1)
{ {
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture1); PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(patternMap1);
ent->name = name + "_tex1"; ent->name = name + "_tex1";
} }
if (texture2) if (patternMap2)
{ {
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture2); PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(patternMap2);
ent->name = name + "_tex2"; ent->name = name + "_tex2";
} }
if (texture3) if (colorMap)
{ {
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture3); PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(colorMap);
ent->name = name + "_tex3"; ent->name = name + "_tex3";
} }
if (texture4) if (bumpMap)
{ {
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture4); PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(bumpMap);
ent->name = name + "_tex4"; ent->name = name + "_tex4";
} }
if (texture5) if (envMap)
{ {
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture5); PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(envMap);
ent->name = name + "_tex5"; ent->name = name + "_tex5";
} }
if (texture6) if (envBumpMap)
{ {
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture6); PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(envBumpMap);
ent->name = name + "_tex6"; ent->name = name + "_tex6";
} }
if (texture34) if (lightmap)
{ {
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture34); PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(lightmap);
ent->name = name + "_tex34"; ent->name = name + "_tex34";
} }
if (particle1) if (splashParticle1)
{ {
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(splashParticle1);
ent->name = name + "_part1"; ent->name = name + "_part1";
} }
if (particle2) if (splashParticle2)
{ {
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(splashParticle2);
ent->name = name + "_part2"; ent->name = name + "_part2";
} }
if (particle3) if (splashParticle3)
{ {
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle3); PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(splashParticle3);
ent->name = name + "_part3"; ent->name = name + "_part3";
} }
if (particle4) if (particle4)
@ -160,16 +177,16 @@ struct Water : IScriptObject
void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) const void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) const
{ {
g_curSpec->flattenDependencies(texture1, pathsOut); g_curSpec->flattenDependencies(patternMap1, pathsOut);
g_curSpec->flattenDependencies(texture2, pathsOut); g_curSpec->flattenDependencies(patternMap2, pathsOut);
g_curSpec->flattenDependencies(texture3, pathsOut); g_curSpec->flattenDependencies(colorMap, pathsOut);
g_curSpec->flattenDependencies(texture4, pathsOut); g_curSpec->flattenDependencies(bumpMap, pathsOut);
g_curSpec->flattenDependencies(texture5, pathsOut); g_curSpec->flattenDependencies(envMap, pathsOut);
g_curSpec->flattenDependencies(texture6, pathsOut); g_curSpec->flattenDependencies(envBumpMap, pathsOut);
g_curSpec->flattenDependencies(texture34, pathsOut); g_curSpec->flattenDependencies(lightmap, pathsOut);
g_curSpec->flattenDependencies(particle1, pathsOut); g_curSpec->flattenDependencies(splashParticle1, pathsOut);
g_curSpec->flattenDependencies(particle2, pathsOut); g_curSpec->flattenDependencies(splashParticle2, pathsOut);
g_curSpec->flattenDependencies(particle3, pathsOut); g_curSpec->flattenDependencies(splashParticle3, pathsOut);
g_curSpec->flattenDependencies(particle4, pathsOut); g_curSpec->flattenDependencies(particle4, pathsOut);
g_curSpec->flattenDependencies(particle5, pathsOut); g_curSpec->flattenDependencies(particle5, pathsOut);
} }

View File

@ -709,7 +709,7 @@ void CStateManager::DrawWorld() const
for (TUniqueId id : x86c_stateManagerContainer->xf370_) for (TUniqueId id : x86c_stateManagerContainer->xf370_)
if (const CActor* ent = static_cast<const CActor*>(GetObjectById(id))) if (const CActor* ent = static_cast<const CActor*>(GetObjectById(id)))
if (!thermal || ent->xe6_27_ & 0x2) if (!thermal || ent->xe6_27_renderVisorFlags & 0x2)
ent->Render(*this); ent->Render(*this);
bool morphingPlayerVisible = false; bool morphingPlayerVisible = false;
@ -747,9 +747,9 @@ void CStateManager::DrawWorld() const
continue; continue;
} }
} }
if (!thermal || actor->xe6_27_ & 0x2) if (!thermal || actor->xe6_27_renderVisorFlags & 0x2)
actor->AddToRenderer(frustum, *this); actor->AddToRenderer(frustum, *this);
if (thermal && actor->xe6_27_ & 0x4) if (thermal && actor->xe6_27_renderVisorFlags & 0x4)
thermalActorArr[thermalActorCount++] = actor.GetPtr(); thermalActorArr[thermalActorCount++] = actor.GetPtr();
} }
} }
@ -785,7 +785,7 @@ void CStateManager::DrawWorld() const
CGraphics::SetDepthRange(0.015625f, 0.03125f); CGraphics::SetDepthRange(0.015625f, 0.03125f);
for (TUniqueId id : x86c_stateManagerContainer->xf39c_renderLast) for (TUniqueId id : x86c_stateManagerContainer->xf39c_renderLast)
if (const CActor* actor = static_cast<const CActor*>(GetObjectById(id))) if (const CActor* actor = static_cast<const CActor*>(GetObjectById(id)))
if (actor->xe6_27_ & 0x2) if (actor->xe6_27_renderVisorFlags & 0x2)
actor->Render(*this); actor->Render(*this);
CGraphics::SetDepthRange(0.125f, 1.f); CGraphics::SetDepthRange(0.125f, 1.f);
} }
@ -793,7 +793,7 @@ void CStateManager::DrawWorld() const
for (TUniqueId id : x86c_stateManagerContainer->xf370_) for (TUniqueId id : x86c_stateManagerContainer->xf370_)
if (const CActor* actor = static_cast<const CActor*>(GetObjectById(id))) if (const CActor* actor = static_cast<const CActor*>(GetObjectById(id)))
if (actor->xe6_27_ & 0x4) if (actor->xe6_27_renderVisorFlags & 0x4)
actor->Render(*this); actor->Render(*this);
for (int i=areaCount-1 ; i>=0 ; --i) for (int i=areaCount-1 ; i>=0 ; --i)
@ -856,7 +856,7 @@ void CStateManager::DrawWorld() const
CGraphics::SetDepthRange(0.015625f, 0.03125f); CGraphics::SetDepthRange(0.015625f, 0.03125f);
for (TUniqueId id : x86c_stateManagerContainer->xf39c_renderLast) for (TUniqueId id : x86c_stateManagerContainer->xf39c_renderLast)
if (const CActor* actor = static_cast<const CActor*>(GetObjectById(id))) if (const CActor* actor = static_cast<const CActor*>(GetObjectById(id)))
if (actor->xe6_27_ & 0x4) if (actor->xe6_27_renderVisorFlags & 0x4)
actor->Render(*this); actor->Render(*this);
CGraphics::SetDepthRange(0.125f, 1.f); CGraphics::SetDepthRange(0.125f, 1.f);
} }
@ -2560,6 +2560,13 @@ void CStateManager::SetBossParams(TUniqueId bossId, float maxEnergy, u32 stringI
xf20_bossStringIdx = stringIdx; xf20_bossStringIdx = stringIdx;
} }
float CStateManager::IntegrateVisorFog(float f) const
{
if (x8b8_playerState->GetActiveVisor(*this) == CPlayerState::EPlayerVisor::Scan)
return (1.f - x8b8_playerState->GetVisorTransitionFactor()) * f;
return f;
}
float CStateManager::g_EscapeShakeCountdown; float CStateManager::g_EscapeShakeCountdown;
bool CStateManager::g_EscapeShakeCountdownInit = false; bool CStateManager::g_EscapeShakeCountdownInit = false;
} }

View File

@ -461,6 +461,7 @@ public:
void SetViewportScale(const zeus::CVector2f& scale) { xf2c_viewportScale = scale; } void SetViewportScale(const zeus::CVector2f& scale) { xf2c_viewportScale = scale; }
float GetThermalColdScale2() const { return xf28_thermColdScale2; } float GetThermalColdScale2() const { return xf28_thermColdScale2; }
void SetThermalColdScale2(float s) { xf28_thermColdScale2 = s; } void SetThermalColdScale2(float s) { xf28_thermColdScale2 = s; }
float IntegrateVisorFog(float f) const;
static float g_EscapeShakeCountdown; static float g_EscapeShakeCountdown;
static bool g_EscapeShakeCountdownInit; static bool g_EscapeShakeCountdownInit;

View File

@ -77,7 +77,7 @@ void CFirstPersonCamera::UpdateTransform(CStateManager& mgr, float dt)
x34_transform = zeus::CTransform::Identity(); x34_transform = zeus::CTransform::Identity();
xe4_27_ = true; xe4_27_ = true;
xe4_28_ = true; xe4_28_ = true;
xe4_29_ = true; xe4_29_actorLightsDirty = true;
return; return;
} }
@ -262,7 +262,7 @@ void CFirstPersonCamera::UpdateTransform(CStateManager& mgr, float dt)
xe4_27_ = true; xe4_27_ = true;
xe4_28_ = true; xe4_28_ = true;
xe4_28_ = true; xe4_28_ = true;
xe4_29_ = true; xe4_29_actorLightsDirty = true;
CActor::SetTranslation(x190_gunFollowXf.origin + player->GetTransform().rotate(bobXf.origin)); CActor::SetTranslation(x190_gunFollowXf.origin + player->GetTransform().rotate(bobXf.origin));
x190_gunFollowXf.orthonormalize(); x190_gunFollowXf.orthonormalize();

View File

@ -84,8 +84,10 @@ public:
const zeus::CColor& GetAmbientColor() const { return x288_ambientColor; } const zeus::CColor& GetAmbientColor() const { return x288_ambientColor; }
const CLight& GetLight(u32 idx) const; const CLight& GetLight(u32 idx) const;
u32 GetActiveLightCount() const; u32 GetActiveLightCount() const;
int GetMaxAreaLights() const { return x2b8_maxAreaLights; }
const std::vector<CLight>& GetAreaLights() const { return x0_areaLights; } const std::vector<CLight>& GetAreaLights() const { return x0_areaLights; }
const std::vector<CLight>& GetDynamicLights() const { return x144_dynamicLights; } const std::vector<CLight>& GetDynamicLights() const { return x144_dynamicLights; }
bool GetIsDirty() const { return x298_24_dirty; }
}; };
} }

View File

@ -1146,8 +1146,11 @@ void CBooRenderer::SetWorldFog(ERglFogMode mode, float startz, float endz, const
CGraphics::SetFog(mode, startz, endz, color); CGraphics::SetFog(mode, startz, endz, color);
} }
void CBooRenderer::RenderFogVolume(const zeus::CColor&, const zeus::CAABox&, const TLockedToken<CModel>*, const CSkinnedModel*) void CBooRenderer::RenderFogVolume(const zeus::CColor& color, const zeus::CAABox& aabb,
const TLockedToken<CModel>* model, const CSkinnedModel* sModel)
{ {
if (!x318_28_disableFog)
x2ac_fogVolumes.emplace_back(CGraphics::g_GXModelMatrix, color, aabb, model, sModel);
} }
void CBooRenderer::SetThermal(bool thermal, float level, const zeus::CColor& color) void CBooRenderer::SetThermal(bool thermal, float level, const zeus::CColor& color)

View File

@ -124,7 +124,7 @@ CFluidPlaneShader::CFluidPlaneShader(CFluidPlane::EFluidType type,
const std::experimental::optional<TLockedToken<CTexture>>& envMap, const std::experimental::optional<TLockedToken<CTexture>>& envMap,
const std::experimental::optional<TLockedToken<CTexture>>& envBumpMap, const std::experimental::optional<TLockedToken<CTexture>>& envBumpMap,
const std::experimental::optional<TLockedToken<CTexture>>& lightmap, const std::experimental::optional<TLockedToken<CTexture>>& lightmap,
bool doubleLightmapBlend, bool additive) bool doubleLightmapBlend, bool additive, u32 maxVertCount)
: m_patternTex1(patternTex1), : m_patternTex1(patternTex1),
m_patternTex2(patternTex2), m_patternTex2(patternTex2),
m_colorTex(colorTex), m_colorTex(colorTex),
@ -147,7 +147,7 @@ CFluidPlaneShader::CFluidPlaneShader(CFluidPlane::EFluidType type,
m_gfxTok = CGraphics::CommitResources( m_gfxTok = CGraphics::CommitResources(
[&](boo::IGraphicsDataFactory::Context& ctx) [&](boo::IGraphicsDataFactory::Context& ctx)
{ {
m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(Vertex), 999); // TODO: Figure out how many m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(Vertex), maxVertCount);
m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, 1024, 1); m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, 1024, 1);
switch (ctx.platform()) switch (ctx.platform())

View File

@ -114,7 +114,7 @@ public:
const std::experimental::optional<TLockedToken<CTexture>>& envMap, const std::experimental::optional<TLockedToken<CTexture>>& envMap,
const std::experimental::optional<TLockedToken<CTexture>>& envBumpMap, const std::experimental::optional<TLockedToken<CTexture>>& envBumpMap,
const std::experimental::optional<TLockedToken<CTexture>>& lightmap, const std::experimental::optional<TLockedToken<CTexture>>& lightmap,
bool doubleLightmapBlend, bool additive); bool doubleLightmapBlend, bool additive, u32 maxVertCount);
void prepareDraw(const zeus::CMatrix4f* texMtxs, const zeus::CMatrix4f& normMtx, float indScale, void prepareDraw(const zeus::CMatrix4f* texMtxs, const zeus::CMatrix4f& normMtx, float indScale,
const std::vector<CLight>& lights, const zeus::CColor* kColors); const std::vector<CLight>& lights, const zeus::CColor* kColors);
void loadVerts(const std::vector<Vertex>& verts); void loadVerts(const std::vector<Vertex>& verts);

View File

@ -14,7 +14,7 @@ CEnergyProjectile::CEnergyProjectile(bool active, const TToken<CWeaponDescriptio
x2ec_dir(xf.basis[1]), x2f8_mag(x2ec_dir.magnitude()), x2ec_dir(xf.basis[1]), x2f8_mag(x2ec_dir.magnitude()),
x2fc_camShake(CCameraShakeData::BuildProjectileCameraShake(0.5f, 0.75f)) x2fc_camShake(CCameraShakeData::BuildProjectileCameraShake(0.5f, 0.75f))
{ {
xe6_27_ = 2; xe6_27_renderVisorFlags = 2;
} }
} }

View File

@ -288,7 +288,7 @@ void CActor::SetRotation(const zeus::CQuaternion &q)
x34_transform = q.toTransform(x34_transform.origin); x34_transform = q.toTransform(x34_transform.origin);
xe4_27_ = true; xe4_27_ = true;
xe4_28_ = true; xe4_28_ = true;
xe4_29_ = true; xe4_29_actorLightsDirty = true;
} }
void CActor::SetTranslation(const zeus::CVector3f& tr) void CActor::SetTranslation(const zeus::CVector3f& tr)
@ -296,7 +296,7 @@ void CActor::SetTranslation(const zeus::CVector3f& tr)
x34_transform.origin = tr; x34_transform.origin = tr;
xe4_27_ = true; xe4_27_ = true;
xe4_28_ = true; xe4_28_ = true;
xe4_29_ = true; xe4_29_actorLightsDirty = true;
} }
void CActor::SetTransform(const zeus::CTransform& tr) void CActor::SetTransform(const zeus::CTransform& tr)
@ -304,7 +304,7 @@ void CActor::SetTransform(const zeus::CTransform& tr)
x34_transform = tr; x34_transform = tr;
xe4_27_ = true; xe4_27_ = true;
xe4_28_ = true; xe4_28_ = true;
xe4_29_ = true; xe4_29_actorLightsDirty = true;
} }
void CActor::SetAddedToken(u32 tok) { xcc_addedToken = tok; } void CActor::SetAddedToken(u32 tok) { xcc_addedToken = tok; }

View File

@ -55,8 +55,8 @@ protected:
u8 xe4_24_nextNonLoopingSfxHandle : 3; u8 xe4_24_nextNonLoopingSfxHandle : 3;
bool xe4_27_ : 1; bool xe4_27_ : 1;
bool xe4_28_ : 1; bool xe4_28_ : 1;
bool xe4_29_ : 1; bool xe4_29_actorLightsDirty : 1;
bool xe4_30_ : 1; bool xe4_30_outOfFrustum : 1;
bool xe4_31_lightsDirty : 1; bool xe4_31_lightsDirty : 1;
bool xe5_24_ : 1; bool xe5_24_ : 1;
bool xe5_25_ : 1; bool xe5_25_ : 1;
@ -64,7 +64,7 @@ protected:
bool xe5_27_useInSortedLists : 1; bool xe5_27_useInSortedLists : 1;
bool xe5_28_callTouch : 1; bool xe5_28_callTouch : 1;
u8 xe6_24_fluidCounter : 3; u8 xe6_24_fluidCounter : 3;
u8 xe6_27_ : 3; u8 xe6_27_renderVisorFlags : 3; // 2: thermal cold, 4: thermal hot
bool xe6_30_enablePitchBend : 1; bool xe6_30_enablePitchBend : 1;
u8 xe6_31_targetableVisorFlags : 4; u8 xe6_31_targetableVisorFlags : 4;
bool xe7_29_ : 1; bool xe7_29_ : 1;
@ -99,7 +99,7 @@ public:
{ {
xe4_27_ = true; xe4_27_ = true;
xe4_28_ = true; xe4_28_ = true;
xe4_29_ = true; xe4_29_actorLightsDirty = true;
xe7_29_ = true; xe7_29_ = true;
CEntity::SetActive(active); CEntity::SetActive(active);
} }

View File

@ -15,7 +15,7 @@ CExplosion::CExplosion(const TLockedToken<CGenDescription>& particle, TUniqueId
xf4_24_ = flags & 0x4; xf4_24_ = flags & 0x4;
xf4_25_ = true; xf4_25_ = true;
xf4_26_ = flags & 0x8; xf4_26_ = flags & 0x8;
xe6_27_ = flags & 0x1 ? 1 : 2; xe6_27_renderVisorFlags = flags & 0x1 ? 1 : 2;
xe8_particleGen->SetGlobalTranslation(xf.origin); xe8_particleGen->SetGlobalTranslation(xf.origin);
xe8_particleGen->SetOrientation(xf.getRotation()); xe8_particleGen->SetOrientation(xf.getRotation());
xe8_particleGen->SetGlobalScale(scale); xe8_particleGen->SetGlobalScale(scale);

View File

@ -6,9 +6,9 @@ namespace urde
{ {
CFluidPlane::CFluidPlane(ResId texPattern1, ResId texPattern2, ResId texColor, float alpha, EFluidType fluidType, CFluidPlane::CFluidPlane(ResId texPattern1, ResId texPattern2, ResId texColor, float alpha, EFluidType fluidType,
float f2, const CFluidUVMotion& motion) float rippleIntensity, const CFluidUVMotion& motion)
: x4_texPattern1Id(texPattern1), x8_texPattern2Id(texPattern2), xc_texColorId(texColor), x40_alpha(alpha), : x4_texPattern1Id(texPattern1), x8_texPattern2Id(texPattern2), xc_texColorId(texColor), x40_alpha(alpha),
x44_fluidType(fluidType), x48_f2(f2), x4c_uvMotion(motion) x44_fluidType(fluidType), x48_rippleIntensity(rippleIntensity), x4c_uvMotion(motion)
{ {
if (g_ResFactory->GetResourceTypeById(texPattern1) == FOURCC('TXTR')) if (g_ResFactory->GetResourceTypeById(texPattern1) == FOURCC('TXTR'))
x10_texPattern1.emplace(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), texPattern1})); x10_texPattern1.emplace(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), texPattern1}));

View File

@ -36,11 +36,11 @@ protected:
std::experimental::optional<TLockedToken<CTexture>> x30_texColor; std::experimental::optional<TLockedToken<CTexture>> x30_texColor;
float x40_alpha; float x40_alpha;
EFluidType x44_fluidType; EFluidType x44_fluidType;
float x48_f2; float x48_rippleIntensity;
CFluidUVMotion x4c_uvMotion; CFluidUVMotion x4c_uvMotion;
public: public:
CFluidPlane(ResId texPattern1, ResId texPattern2, ResId texColor, float alpha, EFluidType fluidType, CFluidPlane(ResId texPattern1, ResId texPattern2, ResId texColor, float alpha, EFluidType fluidType,
float f2, const CFluidUVMotion& motion); float rippleIntensity, const CFluidUVMotion& motion);
virtual void Ripple(float mag, TUniqueId rippler, const zeus::CVector3f& pos, virtual void Ripple(float mag, TUniqueId rippler, const zeus::CVector3f& pos,
CScriptWater& water, CStateManager& mgr); CScriptWater& water, CStateManager& mgr);

View File

@ -50,8 +50,8 @@ CFluidPlaneCPU::CFluidPlaneCPU(ResId texPattern1, ResId texPattern2, ResId texCo
float turbSpeed, float turbDistance, float turbFreqMax, float turbFreqMin, float turbSpeed, float turbDistance, float turbFreqMax, float turbFreqMin,
float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax, float turbAmplitudeMin, float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax, float turbAmplitudeMin,
float specularMin, float specularMax, float reflectionBlend, float reflectionSize, float specularMin, float specularMax, float reflectionBlend, float reflectionSize,
float fluidPlaneF2) float rippleIntensity, u32 maxVertCount)
: CFluidPlane(texPattern1, texPattern2, texColor, alpha, fluidType, fluidPlaneF2, mot), : CFluidPlane(texPattern1, texPattern2, texColor, alpha, fluidType, rippleIntensity, mot),
xa0_texIdBumpMap(bumpMap), xa4_texIdEnvMap(envMap), xa8_texIdEnvBumpMap(envBumpMap), xac_texId4(lightMap), xa0_texIdBumpMap(bumpMap), xa4_texIdEnvMap(envMap), xa8_texIdEnvBumpMap(envBumpMap), xac_texId4(lightMap),
xf0_bumpLightDir(bumpLightDir), xfc_bumpScale(bumpScale), x100_tileSize(tileSize), xf0_bumpLightDir(bumpLightDir), xfc_bumpScale(bumpScale), x100_tileSize(tileSize),
x104_tileSubdivisions(tileSubdivisions & ~0x1), x104_tileSubdivisions(tileSubdivisions & ~0x1),
@ -59,7 +59,8 @@ CFluidPlaneCPU::CFluidPlaneCPU(ResId texPattern1, ResId texPattern2, ResId texCo
x10c_specularMin(specularMin), x110_specularMax(specularMax), x114_reflectionBlend(reflectionBlend), x10c_specularMin(specularMin), x110_specularMax(specularMax), x114_reflectionBlend(reflectionBlend),
x118_reflectionSize(reflectionSize), x11c_unitsPerLightmapTexel(unitsPerLightmapTexel), x118_reflectionSize(reflectionSize), x11c_unitsPerLightmapTexel(unitsPerLightmapTexel),
x120_turbulence(turbSpeed, turbDistance, turbFreqMax, turbFreqMin, turbPhaseMax, x120_turbulence(turbSpeed, turbDistance, turbFreqMax, turbFreqMin, turbPhaseMax,
turbPhaseMin, turbAmplitudeMax, turbAmplitudeMin) turbPhaseMin, turbAmplitudeMax, turbAmplitudeMin),
m_maxVertCount(maxVertCount)
{ {
if (g_ResFactory->GetResourceTypeById(xa0_texIdBumpMap) == FOURCC('TXTR')) if (g_ResFactory->GetResourceTypeById(xa0_texIdBumpMap) == FOURCC('TXTR'))
xb0_bumpMap.emplace(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), xa0_texIdBumpMap})); xb0_bumpMap.emplace(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), xa0_texIdBumpMap}));
@ -223,7 +224,7 @@ CFluidPlaneCPU::RenderSetup(const CStateManager& mgr, float alpha, const zeus::C
const CGameArea* area = mgr.GetWorld()->GetAreaAlways(mgr.GetNextAreaId()); const CGameArea* area = mgr.GetWorld()->GetAreaAlways(mgr.GetNextAreaId());
float lightLevel = area->GetPostConstructed()->x1128_worldLightingLevel; float lightLevel = area->GetPostConstructed()->x1128_worldLightingLevel;
const CScriptWater* nextWater = water->GetNextConnectedWater(mgr); const CScriptWater* nextWater = water->GetNextConnectedWater(mgr);
if (std::fabs(water->GetLightmapDoubleBlendFactor()) < 0.00001f || !nextWater || if (std::fabs(water->GetMorphFactor()) < 0.00001f || !nextWater ||
!nextWater->GetFluidPlane().HasLightMap()) !nextWater->GetFluidPlane().HasLightMap())
{ {
lightmapId = curTex; lightmapId = curTex;
@ -233,7 +234,7 @@ CFluidPlaneCPU::RenderSetup(const CStateManager& mgr, float alpha, const zeus::C
} }
else if (nextWater && nextWater->GetFluidPlane().HasLightMap()) else if (nextWater && nextWater->GetFluidPlane().HasLightMap())
{ {
if (std::fabs(water->GetLightmapDoubleBlendFactor() - 1.f) < 0.00001f) if (std::fabs(water->GetMorphFactor() - 1.f) < 0.00001f)
{ {
lightmapId = curTex; lightmapId = curTex;
// Load lightmap // Load lightmap
@ -250,9 +251,9 @@ CFluidPlaneCPU::RenderSetup(const CStateManager& mgr, float alpha, const zeus::C
CalculateLightmapMatrix(areaXf, xf, aabb, out.texMtxs[nextTexMtx++]); CalculateLightmapMatrix(areaXf, xf, aabb, out.texMtxs[nextTexMtx++]);
// Next: GX_TG_MTX2x4 GX_TG_POS, mtxNext, false, GX_PTIDENTITY // Next: GX_TG_MTX2x4 GX_TG_POS, mtxNext, false, GX_PTIDENTITY
float lum = lightLevel * water->GetLightmapDoubleBlendFactor(); float lum = lightLevel * water->GetMorphFactor();
out.kColors[3] = zeus::CColor(lum, 1.f); out.kColors[3] = zeus::CColor(lum, 1.f);
lowLightBlend = (1.f - water->GetLightmapDoubleBlendFactor()) / (1.f - lum); lowLightBlend = (1.f - water->GetMorphFactor()) / (1.f - lum);
doubleLightmapBlend = true; doubleLightmapBlend = true;
} }
} }
@ -269,11 +270,15 @@ CFluidPlaneCPU::RenderSetup(const CStateManager& mgr, float alpha, const zeus::C
zeus::CColor((1.f - waterPlaneOrthoDot) * (x110_specularMax - x10c_specularMin) + x10c_specularMin, alpha); zeus::CColor((1.f - waterPlaneOrthoDot) * (x110_specularMax - x10c_specularMin) + x10c_specularMin, alpha);
out.kColors[1] = zeus::CColor(x114_reflectionBlend, 1.f); out.kColors[1] = zeus::CColor(x114_reflectionBlend, 1.f);
// TODO: Detect parameter changes and rebuild if needed if (!m_shader || m_cachedDoubleLightmapBlend != doubleLightmapBlend ||
if (!m_shader) m_cachedAdditive != (mgr.GetParticleFlags() == 0))
{
m_cachedDoubleLightmapBlend = doubleLightmapBlend;
m_cachedAdditive = mgr.GetParticleFlags() == 0;
m_shader.emplace(x44_fluidType, m_shader.emplace(x44_fluidType,
x10_texPattern1, x20_texPattern2, x30_texColor, xb0_bumpMap, xc0_envMap, xd0_envBumpMap, x10_texPattern1, x20_texPattern2, x30_texColor, xb0_bumpMap, xc0_envMap, xd0_envBumpMap,
xe0_lightmap, doubleLightmapBlend, mgr.GetParticleFlags() == 0); xe0_lightmap, m_cachedDoubleLightmapBlend, m_cachedAdditive, m_maxVertCount);
}
return out; return out;
} }
@ -369,6 +374,16 @@ public:
s8 ny; s8 ny;
s8 nz; s8 nz;
u8 wavecapIntensity; u8 wavecapIntensity;
zeus::CVector3f MakeNormal() const { return {nx / 63.f, ny / 63.f, nz / 63.f}; }
zeus::CVector3f MakeBinormal() const { return {nx / 63.f, nz / 63.f, -ny / 63.f}; }
zeus::CVector3f MakeTangent() const { return {nz / 63.f, ny / 63.f, -nx / 63.f}; }
zeus::CColor MakeColor(const CFluidPlaneCPURender::SPatchInfo& info) const
{
return {(wavecapIntensity >> info.x34_redShift) / 255.f,
(wavecapIntensity >> info.x35_greenShift) / 255.f,
(wavecapIntensity >> info.x36_blueShift) / 255.f};
}
}; };
}; };
@ -427,7 +442,8 @@ static void ApplyTurbulence(float t, CFluidPlaneCPURender::SHFieldSample (&heigh
float distFac = curX * curX + curYSq; float distFac = curX * curX + curYSq;
if (distFac != 0.f) if (distFac != 0.f)
distFac = std::sqrt(distFac); distFac = std::sqrt(distFac);
heights[i][j].height = fluidPane.GetTurbulenceHeight(fluidPane.GetOOTurbulenceDistance() * distFac + scaledT); heights[i][j].height =
fluidPane.GetTurbulenceHeight(fluidPane.GetOOTurbulenceDistance() * distFac + scaledT);
curX += info.x18_rippleResolution; curX += info.x18_rippleResolution;
} }
curY += info.x18_rippleResolution; curY += info.x18_rippleResolution;
@ -561,7 +577,8 @@ static void ApplyRipple(const CFluidPlaneCPURender::SRippleInfo& rippleInfo,
if (u8 val = CFluidPlaneManager::RippleValues[lifeIdx][int(divDist * f11)]) if (u8 val = CFluidPlaneManager::RippleValues[lifeIdx][int(divDist * f11)])
{ {
heights[k][l].height += val * rippleInfo.x0_ripple.GetAmplitude() * heights[k][l].height += val * rippleInfo.x0_ripple.GetAmplitude() *
sineWave[int(divDist * rippleInfo.x0_ripple.GetLookupPhase() + lookupT)]; sineWave[int(divDist * rippleInfo.x0_ripple.GetLookupPhase() +
lookupT)];
} }
else else
{ {
@ -581,7 +598,6 @@ static void ApplyRipple(const CFluidPlaneCPURender::SRippleInfo& rippleInfo,
curYDiv = nextYDiv; curYDiv = nextYDiv;
curGridY += info.x2a_gridDimX; curGridY += info.x2a_gridDimX;
} }
} }
static void ApplyRipples(const rstl::reserved_vector<CFluidPlaneCPURender::SRippleInfo, 32>& rippleInfos, static void ApplyRipples(const rstl::reserved_vector<CFluidPlaneCPURender::SRippleInfo, 32>& rippleInfos,
@ -600,7 +616,7 @@ static void ApplyRipples(const rstl::reserved_vector<CFluidPlaneCPURender::SRipp
flags[CFluidPlaneCPURender::numTilesInHField+1][i+1] |= 2; flags[CFluidPlaneCPURender::numTilesInHField+1][i+1] |= 2;
} }
static void UpdatePatchNoNormals(CFluidPlaneCPURender::SHFieldSample (& heights)[45][45], const u8 (& flags)[9][9], static void UpdatePatchNoNormals(CFluidPlaneCPURender::SHFieldSample (&heights)[45][45], const u8 (&flags)[9][9],
const CFluidPlaneCPURender::SPatchInfo& info) const CFluidPlaneCPURender::SPatchInfo& info)
{ {
for (int i=1 ; i <= (info.x1_ySubdivs + CFluidPlaneCPURender::numSubdivisionsInTile - 2) / for (int i=1 ; i <= (info.x1_ySubdivs + CFluidPlaneCPURender::numSubdivisionsInTile - 2) /
@ -868,7 +884,265 @@ static void RenderStripWithRipples(float curY, const CFluidPlaneCPURender::SHFie
const CFluidPlaneCPURender::SPatchInfo& info, const CFluidPlaneCPURender::SPatchInfo& info,
std::vector<CFluidPlaneShader::Vertex>& vOut) std::vector<CFluidPlaneShader::Vertex>& vOut)
{ {
int yTile = (startYDiv + CFluidPlaneCPURender::numSubdivisionsInTile - 1) /
CFluidPlaneCPURender::numSubdivisionsInTile;
int endXTile = (info.x0_xSubdivs + CFluidPlaneCPURender::numSubdivisionsInTile - 4) /
CFluidPlaneCPURender::numSubdivisionsInTile;
int midDiv = CFluidPlaneCPURender::numSubdivisionsInTile / 2;
float tileMid = info.x18_rippleResolution * midDiv;
float yMin = curY;
float yMid = curY + tileMid;
float xMin = info.x4_localMin.x;
float curX = info.x4_localMin.x;
int gridCell = info.x28_tileX + info.x2a_gridDimX * (info.x2e_tileY + yTile - 1);
int xTile = 1;
int tileSpan;
for (int i = 1 ; i < info.x0_xSubdivs - 2 ;
i += CFluidPlaneCPURender::numSubdivisionsInTile * tileSpan, gridCell += tileSpan,
xTile += tileSpan, curX += info.x14_tileSize * tileSpan)
{
tileSpan = 1;
if (info.x30_gridFlags && !info.x30_gridFlags[gridCell])
continue;
if ((flags[yTile][xTile] & 0x1f) == 0x1f)
{
for (; xTile+tileSpan<=endXTile ; ++tileSpan)
{
if ((flags[yTile][xTile+tileSpan] & 0x1f) != 0x1f)
break;
if (info.x30_gridFlags && !info.x30_gridFlags[gridCell+tileSpan])
break;
}
int stripDivCount = tileSpan * CFluidPlaneCPURender::numSubdivisionsInTile + 1;
int remSubdivs = CFluidPlaneCPURender::numSubdivisionsInTile;
std::function<void(float x, float y, const CFluidPlaneCPURender::SHFieldSample& samp)> func;
switch (info.x37_normalMode)
{
case CFluidPlaneCPURender::NormalMode::None:
func = [&](float x, float y, const CFluidPlaneCPURender::SHFieldSample& samp)
{
vOut.emplace_back(zeus::CVector3f(x, y, samp.height));
};
break;
case CFluidPlaneCPURender::NormalMode::NoNormals:
func = [&](float x, float y, const CFluidPlaneCPURender::SHFieldSample& samp)
{
vOut.emplace_back(zeus::CVector3f(x, y, samp.height), samp.MakeColor(info));
};
break;
case CFluidPlaneCPURender::NormalMode::Normals:
func = [&](float x, float y, const CFluidPlaneCPURender::SHFieldSample& samp)
{
vOut.emplace_back(zeus::CVector3f(x, y, samp.height), samp.MakeNormal(),
samp.MakeColor(info));
};
break;
case CFluidPlaneCPURender::NormalMode::NBT:
func = [&](float x, float y, const CFluidPlaneCPURender::SHFieldSample& samp)
{
vOut.emplace_back(zeus::CVector3f(x, y, samp.height), samp.MakeNormal(),
samp.MakeBinormal(), samp.MakeTangent(), samp.MakeColor(info));
};
break;
}
float curTileY = yMin;
int curYDiv = startYDiv;
for (; remSubdivs>0 ; --remSubdivs, ++curYDiv, curTileY+=info.x18_rippleResolution)
{
size_t start = vOut.size();
float curTileX = xMin;
for (int v=0 ; v<stripDivCount ; ++v)
{
func(curTileX, curTileY, heights[curYDiv][i+v]);
func(curTileX, curTileY + info.x18_rippleResolution, heights[curYDiv+1][i+v]);
curTileX += info.x18_rippleResolution;
}
CGraphics::DrawArray(start, 4);
}
}
else
{
bool r19 = (flags[yTile+1][xTile] & 0x2) != 0;
bool r16 = (flags[yTile][xTile-1] & 0x8) != 0;
bool r18 = (flags[yTile][xTile+1] & 0x4) != 0;
bool r17 = (flags[yTile-1][xTile] & 0x1) != 0;
int r6 = (r19 ? CFluidPlaneCPURender::numSubdivisionsInTile : 1) + 2;
r6 += r18 ? CFluidPlaneCPURender::numSubdivisionsInTile : 1;
r6 += r17 ? CFluidPlaneCPURender::numSubdivisionsInTile : 1;
r6 += r16 ? CFluidPlaneCPURender::numSubdivisionsInTile : 1;
if (r6 == 6 && (info.x37_normalMode == CFluidPlaneCPURender::NormalMode::Normals ||
info.x37_normalMode == CFluidPlaneCPURender::NormalMode::NBT))
{
for (; xTile+tileSpan<=endXTile ; ++tileSpan)
{
if ((flags[yTile][xTile+tileSpan] & 0x1f) == 0x1f)
break;
if (info.x30_gridFlags && !info.x30_gridFlags[gridCell+tileSpan])
break;
if ((flags[yTile+1][xTile+tileSpan] & 0x2) != 0x0)
break;
if ((flags[yTile][xTile+tileSpan+1] & 0x4) != 0x0)
break;
if ((flags[yTile-1][xTile+tileSpan] & 0x1) != 0x0)
break;
}
int stripDivCount = tileSpan + 1;
size_t start = vOut.size();
switch (info.x37_normalMode)
{
case CFluidPlaneCPURender::NormalMode::Normals:
{
int curYDiv0 = startYDiv;
int curYDiv1 = startYDiv + CFluidPlaneCPURender::numSubdivisionsInTile;
float curTileX = xMin;
for (int v=0 ; v<stripDivCount ; ++v)
{
int curXDiv = v * CFluidPlaneCPURender::numSubdivisionsInTile + i;
const CFluidPlaneCPURender::SHFieldSample& samp0 = heights[curYDiv0][curXDiv];
const CFluidPlaneCPURender::SHFieldSample& samp1 = heights[curYDiv1][curXDiv];
vOut.emplace_back(zeus::CVector3f(curTileX, yMin, samp0.height),
samp0.MakeNormal(), samp0.MakeColor(info));
vOut.emplace_back(zeus::CVector3f(curTileX, yMin + info.x14_tileSize, samp1.height),
samp1.MakeNormal(), samp1.MakeColor(info));
curTileX += info.x18_rippleResolution;
}
break;
}
case CFluidPlaneCPURender::NormalMode::NBT:
{
int curYDiv0 = startYDiv;
int curYDiv1 = startYDiv + CFluidPlaneCPURender::numSubdivisionsInTile;
float curTileX = xMin;
for (int v=0 ; v<stripDivCount ; ++v)
{
int curXDiv = v * CFluidPlaneCPURender::numSubdivisionsInTile + i;
const CFluidPlaneCPURender::SHFieldSample& samp0 = heights[curYDiv0][curXDiv];
const CFluidPlaneCPURender::SHFieldSample& samp1 = heights[curYDiv1][curXDiv];
vOut.emplace_back(zeus::CVector3f(curTileX, yMin, samp0.height),
samp0.MakeNormal(), samp0.MakeBinormal(), samp0.MakeTangent(),
samp0.MakeColor(info));
vOut.emplace_back(zeus::CVector3f(curTileX, yMin + info.x14_tileSize, samp1.height),
samp1.MakeNormal(), samp1.MakeBinormal(), samp1.MakeTangent(),
samp1.MakeColor(info));
curTileX += info.x18_rippleResolution;
}
break;
}
default:
break;
}
CGraphics::DrawArray(start, 4);
}
else
{
TriFanToStrip<CFluidPlaneShader::Vertex> toStrip(vOut);
std::function<void(float x, float y, const CFluidPlaneCPURender::SHFieldSample& samp)> func;
switch (info.x37_normalMode)
{
case CFluidPlaneCPURender::NormalMode::None:
func = [&](float x, float y, const CFluidPlaneCPURender::SHFieldSample& samp)
{
toStrip.EmplaceVert(zeus::CVector3f(x, y, samp.height));
};
break;
case CFluidPlaneCPURender::NormalMode::NoNormals:
func = [&](float x, float y, const CFluidPlaneCPURender::SHFieldSample& samp)
{
toStrip.EmplaceVert(zeus::CVector3f(x, y, samp.height), samp.MakeColor(info));
};
break;
case CFluidPlaneCPURender::NormalMode::Normals:
func = [&](float x, float y, const CFluidPlaneCPURender::SHFieldSample& samp)
{
toStrip.EmplaceVert(zeus::CVector3f(x, y, samp.height), samp.MakeNormal(),
samp.MakeColor(info));
};
break;
case CFluidPlaneCPURender::NormalMode::NBT:
func = [&](float x, float y, const CFluidPlaneCPURender::SHFieldSample& samp)
{
toStrip.EmplaceVert(zeus::CVector3f(x, y, samp.height), samp.MakeNormal(),
samp.MakeBinormal(), samp.MakeTangent(), samp.MakeColor(info));
};
break;
}
func(tileMid + xMin, yMid, heights[startYDiv+midDiv][i+midDiv]);
int curXDiv = i;
int curYDiv = startYDiv + CFluidPlaneCPURender::numSubdivisionsInTile;
float curTileX = xMin;
float curTileY = yMin + info.x14_tileSize;
for (int v=0 ; v<(r19 ? CFluidPlaneCPURender::numSubdivisionsInTile : 1) ; ++v)
{
const CFluidPlaneCPURender::SHFieldSample& samp = heights[curYDiv][curXDiv+v];
func(curTileX, curTileY, samp);
curTileX += info.x18_rippleResolution;
}
curXDiv = i + CFluidPlaneCPURender::numSubdivisionsInTile;
curYDiv = startYDiv + CFluidPlaneCPURender::numSubdivisionsInTile;
curTileX = xMin + info.x14_tileSize;
curTileY = yMin + info.x14_tileSize;
for (int v=0 ; v<(r18 ? CFluidPlaneCPURender::numSubdivisionsInTile : 1) ; ++v)
{
const CFluidPlaneCPURender::SHFieldSample& samp = heights[curYDiv-v][curXDiv];
func(curTileX, curTileY, samp);
curTileY -= info.x18_rippleResolution;
}
curXDiv = i + CFluidPlaneCPURender::numSubdivisionsInTile;
curYDiv = startYDiv;
curTileX = xMin + info.x14_tileSize;
curTileY = yMin;
for (int v=0 ; v<(r17 ? CFluidPlaneCPURender::numSubdivisionsInTile : 1) ; ++v)
{
const CFluidPlaneCPURender::SHFieldSample& samp = heights[curYDiv][curXDiv-v];
func(curTileX, curTileY, samp);
curTileX -= info.x18_rippleResolution;
}
curXDiv = i;
curYDiv = startYDiv;
curTileX = xMin;
curTileY = yMin;
if (r16)
{
for (int v=0 ; v<CFluidPlaneCPURender::numSubdivisionsInTile ; ++v)
{
const CFluidPlaneCPURender::SHFieldSample& samp = heights[curYDiv+v][curXDiv];
func(curTileX, curTileY, samp);
curTileY += info.x18_rippleResolution;
}
}
else
{
{
const CFluidPlaneCPURender::SHFieldSample& samp = heights[curYDiv][curXDiv];
func(curTileX, curTileY, samp);
}
curTileY += info.x14_tileSize;
{
const CFluidPlaneCPURender::SHFieldSample& samp =
heights[curYDiv+CFluidPlaneCPURender::numSubdivisionsInTile][curXDiv];
func(curTileX, curTileY, samp);
}
}
toStrip.Draw();
}
}
}
} }
static void RenderPatch(const CFluidPlaneCPURender::SPatchInfo& info, static void RenderPatch(const CFluidPlaneCPURender::SPatchInfo& info,

View File

@ -46,7 +46,7 @@ class CFluidPlaneCPU : public CFluidPlane
zeus::CVector3f xf0_bumpLightDir; zeus::CVector3f xf0_bumpLightDir;
float xfc_bumpScale; float xfc_bumpScale;
float x100_tileSize; float x100_tileSize;
u32 x104_tileSubdivisions; int x104_tileSubdivisions;
float x108_rippleResolution; float x108_rippleResolution;
float x10c_specularMin; float x10c_specularMin;
float x110_specularMax; float x110_specularMax;
@ -55,8 +55,12 @@ class CFluidPlaneCPU : public CFluidPlane
float x11c_unitsPerLightmapTexel; float x11c_unitsPerLightmapTexel;
CTurbulence x120_turbulence; CTurbulence x120_turbulence;
u32 m_maxVertCount;
mutable std::vector<CFluidPlaneShader::Vertex> m_verts; mutable std::vector<CFluidPlaneShader::Vertex> m_verts;
mutable std::experimental::optional<CFluidPlaneShader> m_shader; mutable std::experimental::optional<CFluidPlaneShader> m_shader;
mutable bool m_cachedDoubleLightmapBlend;
mutable bool m_cachedAdditive;
struct RenderSetupInfo struct RenderSetupInfo
{ {
@ -73,7 +77,7 @@ public:
const CFluidUVMotion& mot, float turbSpeed, float turbDistance, float turbFreqMax, const CFluidUVMotion& mot, float turbSpeed, float turbDistance, float turbFreqMax,
float turbFreqMin, float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax, float turbFreqMin, float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax,
float turbAmplitudeMin, float specularMin, float specularMax, float reflectionBlend, float turbAmplitudeMin, float specularMin, float specularMax, float reflectionBlend,
float reflectionSize, float fluidPlaneF2); float reflectionSize, float rippleIntensity, u32 maxVertCount);
void CreateRipple(const CRipple& ripple, CStateManager& mgr); void CreateRipple(const CRipple& ripple, CStateManager& mgr);
void CalculateLightmapMatrix(const zeus::CTransform& areaXf, const zeus::CTransform& xf, void CalculateLightmapMatrix(const zeus::CTransform& areaXf, const zeus::CTransform& xf,
const zeus::CAABox& aabb, zeus::CMatrix4f& mtxOut) const; const zeus::CAABox& aabb, zeus::CMatrix4f& mtxOut) const;
@ -100,7 +104,7 @@ public:
const CTexture& GetLightMap() const { return **xe0_lightmap; } const CTexture& GetLightMap() const { return **xe0_lightmap; }
const zeus::CVector3f& GetBumpLightDir() const { return xf0_bumpLightDir; } const zeus::CVector3f& GetBumpLightDir() const { return xf0_bumpLightDir; }
float GetTileSize() const { return x100_tileSize; } float GetTileSize() const { return x100_tileSize; }
u32 GetTileSubdivisions() const { return x104_tileSubdivisions; } int GetTileSubdivisions() const { return x104_tileSubdivisions; }
float GetRippleResolution() const { return x108_rippleResolution; } float GetRippleResolution() const { return x108_rippleResolution; }
float GetTurbulenceHeight(float sel) const { return x120_turbulence.GetHeight(sel); } float GetTurbulenceHeight(float sel) const { return x120_turbulence.GetHeight(sel); }
float GetOOTurbulenceDistance() const { return x120_turbulence.GetOODistance(); } float GetOOTurbulenceDistance() const { return x120_turbulence.GetOODistance(); }

View File

@ -48,6 +48,7 @@ public:
void CreateSplash(TUniqueId splasher, CStateManager& mgr, const CScriptWater& water, void CreateSplash(TUniqueId splasher, CStateManager& mgr, const CScriptWater& water,
const zeus::CVector3f& pos, float factor, bool); const zeus::CVector3f& pos, float factor, bool);
rstl::reserved_vector<CSplashRecord, 32>& SplashRecords() { return x18_splashes; } rstl::reserved_vector<CSplashRecord, 32>& SplashRecords() { return x18_splashes; }
const CRippleManager& GetRippleManager() const { return x0_rippleManager; }
}; };
} }

View File

@ -4,58 +4,69 @@
namespace urde namespace urde
{ {
CFluidUVMotion::CFluidUVMotion(float a, float b, const CFluidUVMotion::SFluidLayerMotion& c, CFluidUVMotion::CFluidUVMotion(float timeToWrap, float orientation,
const CFluidUVMotion::SFluidLayerMotion& d, const CFluidUVMotion::SFluidLayerMotion& e) const CFluidUVMotion::SFluidLayerMotion& colorLayer,
: x4c_(1.f/a) const CFluidUVMotion::SFluidLayerMotion& pattern1Layer,
, x50_(b) const CFluidUVMotion::SFluidLayerMotion& pattern2Layer)
: x4c_ooTimeToWrap(1.f / timeToWrap)
, x50_orientation(orientation)
{ {
x0_fluidLayers.resize(3); x0_fluidLayers.resize(3);
x0_fluidLayers[0] = c; x0_fluidLayers[0] = colorLayer;
x0_fluidLayers[1] = d; x0_fluidLayers[1] = pattern1Layer;
x0_fluidLayers[2] = e; x0_fluidLayers[2] = pattern2Layer;
} }
CFluidUVMotion::CFluidUVMotion(float, float) CFluidUVMotion::CFluidUVMotion(float timeToWrap, float orientation)
{} : x4c_ooTimeToWrap(1.f / timeToWrap), x50_orientation(orientation)
void CFluidUVMotion::CalculateFluidTextureOffset(float f31, float offsets[3][2]) const
{ {
float f28 = (f31 * x4c_) * zeus::fastCosF(x50_); x0_fluidLayers.resize(3);
float f29 = (f31 * x4c_) / zeus::fastSinF(x50_); x0_fluidLayers[0].x4_ooTimeToWrap = 0.001f;
x0_fluidLayers[1].x4_ooTimeToWrap = 0.33333334f;
x0_fluidLayers[2].x4_ooTimeToWrap = 0.2f;
x0_fluidLayers[2].x8_orientation = 0.78539819f;
}
void CFluidUVMotion::CalculateFluidTextureOffset(float t, float offsets[3][2]) const
{
float totalYOffset = (t * x4c_ooTimeToWrap) * zeus::fastCosF(x50_orientation);
float totalXOffset = (t * x4c_ooTimeToWrap) * zeus::fastSinF(x50_orientation);
for (u32 i = 0 ; i<x0_fluidLayers.size() ; ++i) for (u32 i = 0 ; i<x0_fluidLayers.size() ; ++i)
{ {
const SFluidLayerMotion& layer = x0_fluidLayers[i]; const SFluidLayerMotion& layer = x0_fluidLayers[i];
float f30 = f31 * layer.x4_a; float speedT = t * layer.x4_ooTimeToWrap;
float f1 = f30 - std::floor(f30); float cycleT = speedT - std::floor(speedT);
float f27; float localY;
float f26; float localX;
switch(layer.x0_motion) switch(layer.x0_motion)
{ {
case EFluidUVMotion::One: case EFluidUVMotion::One:
{ {
f30 = (M_PIF * 2) * f1; float angle = (M_PIF * 2) * cycleT;
f27 = layer.xc_c * zeus::fastSinF(f30); localY = layer.xc_magnitude * zeus::fastSinF(angle);
f26 = layer.xc_c * zeus::fastCosF(f30); localX = layer.xc_magnitude * zeus::fastCosF(angle);
} }
break; break;
case EFluidUVMotion::Two: case EFluidUVMotion::Two:
{ {
f27 = 0.f; localY = 0.f;
f26 = layer.xc_c * zeus::fastCosF((M_PIF * 2) * f1); localX = layer.xc_magnitude * zeus::fastCosF((M_PIF * 2) * cycleT);
} }
break; break;
default: default:
f27 = f26 = 0.f; localY = localX = 0.f;
break; break;
} }
float x = f26 * zeus::fastSinF(layer.x8_b) + (f27 * zeus::fastCosF(layer.x8_b) + f29); float x = localX * zeus::fastSinF(layer.x8_orientation) +
float y = f27 * zeus::fastSinF(layer.x8_b) + (f26 * zeus::fastCosF(layer.x8_b) + f28); localY * zeus::fastCosF(layer.x8_orientation) + totalXOffset;
float y = localY * zeus::fastSinF(layer.x8_orientation) +
localX * zeus::fastCosF(layer.x8_orientation) + totalYOffset;
offsets[i][0] = float(x - floor(x)); offsets[i][0] = x - std::floor(x);
offsets[i][1] = float(y - floor(y)); offsets[i][1] = y - std::floor(y);
} }
} }
} }

View File

@ -19,15 +19,16 @@ public:
struct SFluidLayerMotion struct SFluidLayerMotion
{ {
EFluidUVMotion x0_motion = EFluidUVMotion::Zero; EFluidUVMotion x0_motion = EFluidUVMotion::Zero;
float x4_a = 0.16666667f; float x4_ooTimeToWrap = 0.16666667f;
float x8_b = 0.f; float x8_orientation = 0.f;
float xc_c = 1.f; float xc_magnitude = 1.f;
float x10_uvMul = 5.f; float x10_uvMul = 5.f;
float x14_uvScale = 0.2f; float x14_uvScale = 0.2f;
SFluidLayerMotion() = default; SFluidLayerMotion() = default;
SFluidLayerMotion(EFluidUVMotion motion, float a, float b, float c, float uvMul) SFluidLayerMotion(EFluidUVMotion motion, float timeToWrap, float orientation, float magnitude, float uvMul)
: x0_motion(motion), x4_a(1.f / a), x8_b(b), xc_c(c), x10_uvMul(uvMul), x14_uvScale(1.f / uvMul) : x0_motion(motion), x4_ooTimeToWrap(1.f / timeToWrap), x8_orientation(orientation),
xc_magnitude(magnitude), x10_uvMul(uvMul), x14_uvScale(1.f / uvMul)
{ {
} }
@ -36,15 +37,16 @@ public:
private: private:
rstl::reserved_vector<SFluidLayerMotion, 3> x0_fluidLayers; rstl::reserved_vector<SFluidLayerMotion, 3> x0_fluidLayers;
float x4c_; float x4c_ooTimeToWrap;
float x50_; float x50_orientation;
public: public:
CFluidUVMotion(float a, float b, const SFluidLayerMotion& c, const SFluidLayerMotion& d, const SFluidLayerMotion& e); CFluidUVMotion(float timeToWrap, float orientation, const SFluidLayerMotion& colorLayer,
CFluidUVMotion(float, float); const SFluidLayerMotion& pattern1Layer, const SFluidLayerMotion& pattern2Layer);
CFluidUVMotion(float timeToWrap, float orientation);
const rstl::reserved_vector<SFluidLayerMotion, 3>& GetFluidLayers() const { return x0_fluidLayers; } const rstl::reserved_vector<SFluidLayerMotion, 3>& GetFluidLayers() const { return x0_fluidLayers; }
void GetOrientation() const; float GetOrientation() const { return x50_orientation; }
void GetOOTimeToWrapTexPage() const; float GetOOTimeToWrapTexPage() const { return x4c_ooTimeToWrap; }
void CalculateFluidTextureOffset(float, float[3][2]) const; void CalculateFluidTextureOffset(float, float[3][2]) const;
}; };
} }

View File

@ -103,7 +103,7 @@ void CPhysicsActor::AddMotionState(const CMotionState& mst)
xe4_27_ = true; xe4_27_ = true;
xe4_28_ = true; xe4_28_ = true;
xe4_29_ = true; xe4_29_actorLightsDirty = true;
SetTranslation(x34_transform.origin + mst.x0_translation); SetTranslation(x34_transform.origin + mst.x0_translation);
@ -123,7 +123,7 @@ void CPhysicsActor::SetMotionState(const CMotionState& mst)
xe4_27_ = true; xe4_27_ = true;
xe4_28_ = true; xe4_28_ = true;
xe4_29_ = true; xe4_29_actorLightsDirty = true;
SetTranslation(mst.x0_translation); SetTranslation(mst.x0_translation);
xfc_constantForce = mst.x1c_velocity; xfc_constantForce = mst.x1c_velocity;
@ -268,7 +268,7 @@ void CPhysicsActor::SetPhysicsState(const CPhysicsState& state)
x34_transform = zeus::CTransform(state.GetOrientation(), x34_transform.origin); x34_transform = zeus::CTransform(state.GetOrientation(), x34_transform.origin);
xe4_27_ = true; xe4_27_ = true;
xe4_28_ = true; xe4_28_ = true;
xe4_29_ = true; xe4_29_actorLightsDirty = true;
xfc_constantForce = state.GetConstantForceWR(); xfc_constantForce = state.GetConstantForceWR();
x108_angularMomentum = state.GetAngularMomentumWR(); x108_angularMomentum = state.GetAngularMomentumWR();

View File

@ -2554,7 +2554,7 @@ void CPlayer::ApplyGrappleForces(const CFinalInput& input, CStateManager& mgr, f
zeus::CTransform(x3c0_grappleSwingAxis, swingForward, zeus::CVector3f::skUp, GetTranslation()); zeus::CTransform(x3c0_grappleSwingAxis, swingForward, zeus::CVector3f::skUp, GetTranslation());
xe4_27_ = true; xe4_27_ = true;
xe4_28_ = true; xe4_28_ = true;
xe4_29_ = true; xe4_29_actorLightsDirty = true;
SetVelocityWR(pullVec); SetVelocityWR(pullVec);
if (!ValidateFPPosition(GetTranslation(), mgr)) if (!ValidateFPPosition(GetTranslation(), mgr))
@ -2563,7 +2563,7 @@ void CPlayer::ApplyGrappleForces(const CFinalInput& input, CStateManager& mgr, f
x34_transform = backupXf; x34_transform = backupXf;
xe4_27_ = true; xe4_27_ = true;
xe4_28_ = true; xe4_28_ = true;
xe4_29_ = true; xe4_29_actorLightsDirty = true;
SetVelocityWR(backupVel); SetVelocityWR(backupVel);
} }
} }

View File

@ -127,10 +127,10 @@ void CScriptActor::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum)
{ {
CActor::PreRender(mgr, frustum); CActor::PreRender(mgr, frustum);
if (xe4_30_ && TCastToPtr<CCinematicCamera>(mgr.GetCameraManager()->GetCurrentCamera(mgr))) if (xe4_30_outOfFrustum && TCastToPtr<CCinematicCamera>(mgr.GetCameraManager()->GetCurrentCamera(mgr)))
xe4_30_ = false; xe4_30_outOfFrustum = false;
if (xe4_30_ && !x2e2_29_ && !x2e2_27_) if (xe4_30_outOfFrustum && !x2e2_29_ && !x2e2_27_)
{ {
zeus::CColor col(1.f, 1.f, x2dc_xrayAlpha); zeus::CColor col(1.f, 1.f, x2dc_xrayAlpha);
if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay) if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay)
@ -154,7 +154,7 @@ void CScriptActor::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum)
} }
} }
if (!x2e2_24_ && xe6_27_ == 2 && if (!x2e2_24_ && xe6_27_renderVisorFlags == 2 &&
mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay) mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay)
{ {
xb4_drawFlags.x2_flags &= ~3; xb4_drawFlags.x2_flags &= ~3;

View File

@ -79,7 +79,7 @@ void CScriptDoor::Think(float dt, CStateManager& mgr)
void CScriptDoor::AddToRenderer(const zeus::CFrustum& /*frustum*/, CStateManager &mgr) void CScriptDoor::AddToRenderer(const zeus::CFrustum& /*frustum*/, CStateManager &mgr)
{ {
if (!xe4_30_) if (!xe4_30_outOfFrustum)
CPhysicsActor::Render(mgr); CPhysicsActor::Render(mgr);
} }

View File

@ -44,7 +44,7 @@ void CScriptTrigger::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CS
if (msg == EScriptObjectMessage::Deactivate) if (msg == EScriptObjectMessage::Deactivate)
{ {
xe8_inhabitants.clear(); xe8_inhabitants.clear();
x148_25_ = false; x148_25_camSubmerged = false;
} }
if (x148_28_) if (x148_28_)

View File

@ -58,7 +58,7 @@ protected:
struct struct
{ {
bool x148_24_playerInside : 1; bool x148_24_playerInside : 1;
bool x148_25_ : 1; bool x148_25_camSubmerged : 1;
bool x148_26_deactivateOnEntered : 1; bool x148_26_deactivateOnEntered : 1;
bool x148_27_deactivateOnExited : 1; bool x148_27_deactivateOnExited : 1;
bool x148_28_ : 1; bool x148_28_ : 1;
@ -84,6 +84,7 @@ public:
std::list<CObjectTracker>& GetInhabitants(); std::list<CObjectTracker>& GetInhabitants();
rstl::optional_object<zeus::CAABox> GetTouchBounds() const; rstl::optional_object<zeus::CAABox> GetTouchBounds() const;
void Touch(CActor &, CStateManager &); void Touch(CActor &, CStateManager &);
const zeus::CAABox& GetTriggerBoundsOR() const { return x130_bounds; }
zeus::CAABox GetTriggerBoundsWR() const; zeus::CAABox GetTriggerBoundsWR() const;
const CDamageInfo& GetDamageInfo() const { return x100_damageInfo; } const CDamageInfo& GetDamageInfo() const { return x100_damageInfo; }
ETriggerFlags GetTriggerFlags() const { return x12c_flags; } ETriggerFlags GetTriggerFlags() const { return x12c_flags; }

View File

@ -16,7 +16,7 @@ CScriptVisorFlare::CScriptVisorFlare(TUniqueId uid, const std::string& name, con
CMaterialList(EMaterialTypes::Unknown), CActorParameters::None(), kInvalidUniqueId), CMaterialList(EMaterialTypes::Unknown), CActorParameters::None(), kInvalidUniqueId),
xe8_flare(blendMode, b1, f1, f2, f3, w1, w2, flares) xe8_flare(blendMode, b1, f1, f2, f3, w1, w2, flares)
{ {
xe6_27_ = 2; xe6_27_renderVisorFlags = 2;
} }
void CScriptVisorFlare::Accept(IVisitor& visitor) void CScriptVisorFlare::Accept(IVisitor& visitor)

View File

@ -3,6 +3,9 @@
#include "TCastTo.hpp" #include "TCastTo.hpp"
#include "GameGlobalObjects.hpp" #include "GameGlobalObjects.hpp"
#include "CSimplePool.hpp" #include "CSimplePool.hpp"
#include "World/CWorld.hpp"
#include "Graphics/CBooRenderer.hpp"
#include "Camera/CGameCamera.hpp"
namespace urde namespace urde
{ {
@ -15,42 +18,49 @@ const float CScriptWater::kSplashScales[6] =
CScriptWater::CScriptWater(CStateManager& mgr, TUniqueId uid, const std::string& name, const CEntityInfo& info, CScriptWater::CScriptWater(CStateManager& mgr, TUniqueId uid, const std::string& name, const CEntityInfo& info,
const zeus::CVector3f& pos, const zeus::CAABox& box, const urde::CDamageInfo& dInfo, const zeus::CVector3f& pos, const zeus::CAABox& box, const urde::CDamageInfo& dInfo,
zeus::CVector3f& orientedForce, ETriggerFlags triggerFlags, bool b1, bool b2, zeus::CVector3f& orientedForce, ETriggerFlags triggerFlags, bool thermalCold,
ResId patternMap1, ResId patternMap2, ResId colorMap, ResId bumpMap, ResId envMap, bool allowRender, ResId patternMap1, ResId patternMap2, ResId colorMap, ResId bumpMap,
ResId envBumpMap, ResId unusedMap, const zeus::CVector3f& bumpLightDir, float bumpScale, ResId envMap, ResId envBumpMap, ResId unusedMap, const zeus::CVector3f& bumpLightDir,
float f2, float f3, bool active, CFluidPlane::EFluidType fluidType, bool b4, float alpha, float bumpScale, float morphInTime, float morphOutTime, bool active,
const CFluidUVMotion& uvMot, float turbSpeed, float turbDistance, float turbFreqMax, CFluidPlane::EFluidType fluidType, bool b4, float alpha, const CFluidUVMotion& uvMot,
float turbFreqMin, float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax, float turbSpeed, float turbDistance, float turbFreqMax, float turbFreqMin,
float turbAmplitudeMin, const zeus::CColor& c1, const zeus::CColor& c2, ResId splashParticle1, float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax, float turbAmplitudeMin,
ResId splashParticle2, ResId splashParticle3, ResId particle4, ResId particle5, s32 i1, const zeus::CColor& splashColor, const zeus::CColor& unkColor, ResId splashParticle1,
ResId splashParticle2, ResId splashParticle3, ResId particle4, ResId particle5, s32 unkSfx,
s32 visorRunoffSfx, s32 splashSfx1, s32 splashSfx2, s32 splashSfx3, float tileSize, s32 visorRunoffSfx, s32 splashSfx1, s32 splashSfx2, s32 splashSfx3, float tileSize,
u32 tileSubdivisions, float specularMin, float specularMax, float reflectionSize, u32 tileSubdivisions, float specularMin, float specularMax, float reflectionSize,
float fluidPlaneF2, float reflectionBlend, float slF6, float slF7, float slF8, float rippleIntensity, float reflectionBlend, float fogBias, float fogMagnitude,
const zeus::CColor& c3, ResId lightmapId, float unitsPerLightmapTexel, float lF2, float lF3, float fogSpeed, const zeus::CColor& fogColor, ResId lightmapId, float unitsPerLightmapTexel,
u32, u32, bool, s32, s32, std::unique_ptr<u32[]>&& u32Arr) float alphaInTime, float alphaOutTime, u32, u32, bool, s32, s32,
std::unique_ptr<u32[]>&& u32Arr)
: CScriptTrigger(uid, name, info, pos, box, dInfo, orientedForce, triggerFlags, active, false, false), : CScriptTrigger(uid, name, info, pos, box, dInfo, orientedForce, triggerFlags, active, false, false),
x1b8_position(pos), x1c4_extent(box.max - box.min), x1d0_f2(f2), x1d4_position2(pos), x1e0_extent2(box.max - box.min), x1b8_positionMorphed(pos), x1c4_extentMorphed(box.max - box.min), x1d0_morphInTime(morphInTime), x1d4_positionOrig(pos),
x1ec_damage(dInfo.GetDamage()), x1f0_damage2(dInfo.GetDamage()), x1f4_(f3), x214_(slF6), x218_(slF7), x21c_(slF6), x1e0_extentOrig(box.max - box.min), x1ec_damageOrig(dInfo.GetDamage()), x1f0_damageMorphed(dInfo.GetDamage()),
x220_(slF7), x224_(slF8), x228_(c3), x22c_splashParticle1Id(splashParticle1), x230_splashParticle2Id(splashParticle2), x1f4_morphOutTime(morphOutTime), x214_fogBias(fogBias), x218_fogMagnitude(fogMagnitude), x21c_origFogBias(fogBias),
x220_origFogMagnitude(fogMagnitude), x224_fogSpeed(fogSpeed), x228_fogColor(fogColor),
x22c_splashParticle1Id(splashParticle1), x230_splashParticle2Id(splashParticle2),
x234_splashParticle3Id(splashParticle3), x238_particle4Id(particle4), x24c_particle5Id(particle5), x234_splashParticle3Id(splashParticle3), x238_particle4Id(particle4), x24c_particle5Id(particle5),
x260_(CSfxManager::TranslateSFXID(i1)), x262_visorRunoffSfx(CSfxManager::TranslateSFXID(visorRunoffSfx)), x260_unkSfx(CSfxManager::TranslateSFXID(unkSfx)), x262_visorRunoffSfx(CSfxManager::TranslateSFXID(visorRunoffSfx)),
x2a4_c1(c1), x2a8_c2(c2), x2ac_lf2(lF2), x2b0_lf3(lF3), x2b4_((lF2 != 0.f) ? 1.f / lF2 : 0.f), x2a4_splashColor(splashColor), x2a8_unkColor(unkColor), x2ac_alphaInTime(alphaInTime), x2b0_alphaOutTime(alphaOutTime),
x2b8_((lF3 != 0.f) ? 1.f / lF3 : 0.f), x2bc_alpha(alpha), x2c0_tileSize(tileSize) x2b4_alphaInRecip((alphaInTime != 0.f) ? 1.f / alphaInTime : 0.f),
x2b8_alphaOutRecip((alphaOutTime != 0.f) ? 1.f / alphaOutTime : 0.f), x2bc_alpha(alpha), x2c0_tileSize(tileSize)
{ {
zeus::CAABox triggerAABB = GetTriggerBoundsWR(); zeus::CAABox triggerAABB = GetTriggerBoundsWR();
x2c4_gridDimX = u32((x2c0_tileSize + triggerAABB.max.x - triggerAABB.min.x - 0.01f) / x2c0_tileSize); x2c4_gridDimX = u32((x2c0_tileSize + triggerAABB.max.x - triggerAABB.min.x - 0.01f) / x2c0_tileSize);
x2c8_gridDimY = u32((x2c0_tileSize + triggerAABB.max.y - triggerAABB.min.y - 0.01f) / x2c0_tileSize); x2c8_gridDimY = u32((x2c0_tileSize + triggerAABB.max.y - triggerAABB.min.y - 0.01f) / x2c0_tileSize);
x2cc_gridCellCount = (x2c4_gridDimX + 1) * (x2c8_gridDimY + 1); x2cc_gridCellCount = (x2c4_gridDimX + 1) * (x2c8_gridDimY + 1);
x2e8_24_b4 = b4; x2e8_24_b4 = b4;
x2e8_27_b2 = b2; x2e8_27_allowRender = allowRender;
x2e8_28 = true; x2e8_28_recomputeClipping = true;
x1b4_fluidPlane = std::make_unique<CFluidPlaneCPU>(patternMap1, patternMap2, colorMap, bumpMap, envMap, envBumpMap, x1b4_fluidPlane = std::make_unique<CFluidPlaneCPU>(patternMap1, patternMap2, colorMap, bumpMap, envMap, envBumpMap,
lightmapId, unitsPerLightmapTexel, tileSize, tileSubdivisions, lightmapId, unitsPerLightmapTexel, tileSize, tileSubdivisions,
fluidType, x2bc_alpha, bumpLightDir, bumpScale, uvMot, fluidType, x2bc_alpha, bumpLightDir, bumpScale, uvMot,
turbSpeed, turbDistance, turbFreqMax, turbFreqMin, turbPhaseMax, turbSpeed, turbDistance, turbFreqMax, turbFreqMin, turbPhaseMax,
turbPhaseMin, turbAmplitudeMax, turbAmplitudeMin, specularMin, turbPhaseMin, turbAmplitudeMax, turbAmplitudeMin, specularMin,
specularMax, reflectionBlend, reflectionSize, fluidPlaneF2); specularMax, reflectionBlend, reflectionSize, rippleIntensity,
x2cc_gridCellCount *
((std::max(u32(2), tileSubdivisions) * 4 + 2) * 4));
u32Arr.reset(); u32Arr.reset();
x264_splashEffects.resize(3); x264_splashEffects.resize(3);
if (x22c_splashParticle1Id != kInvalidResId) if (x22c_splashParticle1Id != kInvalidResId)
@ -75,61 +85,410 @@ CScriptWater::CScriptWater(CStateManager& mgr, TUniqueId uid, const std::string&
x90_actorLights->SetFindNearestDynamicLights(true); x90_actorLights->SetFindNearestDynamicLights(true);
x148_24_playerInside = true; x148_24_playerInside = true;
CalculateRenderBounds(); CalculateRenderBounds();
xe6_27_ = u8(b1 ? 2 : 1); xe6_27_renderVisorFlags = u8(thermalCold ? 2 : 1);
if (!x30_24_active) if (!x30_24_active)
{ {
x2bc_alpha = 0.f; x2bc_alpha = 0.f;
x214_ = 0.f; x214_fogBias = 0.f;
x218_ = 0.f; x218_fogMagnitude = 0.f;
} }
SetupGrid(true); SetupGrid(true);
} }
void CScriptWater::SetupGrid(bool b) void CScriptWater::SetupGrid(bool recomputeClipping)
{ {
zeus::CAABox triggerAABB = GetTriggerBoundsWR(); zeus::CAABox triggerAABB = GetTriggerBoundsWR();
auto dimX = u32((triggerAABB.max.x - triggerAABB.min.x + x2c0_tileSize) / x2c0_tileSize); auto dimX = u32((triggerAABB.max.x - triggerAABB.min.x + x2c0_tileSize) / x2c0_tileSize);
auto dimY = u32((triggerAABB.max.y - triggerAABB.min.y + x2c0_tileSize) / x2c0_tileSize); auto dimY = u32((triggerAABB.max.y - triggerAABB.min.y + x2c0_tileSize) / x2c0_tileSize);
x2e4_gridCellCount2 = x2cc_gridCellCount = (dimX + 1) * (dimY + 1); x2e4_gridCellCount2 = x2cc_gridCellCount = (dimX + 1) * (dimY + 1);
x2dc_.reset(); x2dc_vertIntersects.reset();
if (!x2d8_gridFlags || dimX != x2c4_gridDimX || dimY != x2c8_gridDimY) if (!x2d8_tileIntersects || dimX != x2c4_gridDimX || dimY != x2c8_gridDimY)
x2d8_gridFlags.reset(new bool[dimX * dimY]); x2d8_tileIntersects.reset(new bool[dimX * dimY]);
x2c4_gridDimX = dimX; x2c4_gridDimX = dimX;
x2c8_gridDimY = dimY; x2c8_gridDimY = dimY;
for (int i=0 ; i<x2c8_gridDimY ; ++i) for (int i=0 ; i<x2c8_gridDimY ; ++i)
for (int j=0 ; j<x2c4_gridDimX ; ++j) for (int j=0 ; j<x2c4_gridDimX ; ++j)
x2d8_gridFlags[i * x2c4_gridDimX + j] = true; x2d8_tileIntersects[i * x2c4_gridDimX + j] = true;
if (!x2e0_patchFlags || x2d0_patchDimX != 0 || x2d4_patchDimY != 0) if (!x2e0_patchIntersects || x2d0_patchDimX != 0 || x2d4_patchDimY != 0)
x2e0_patchFlags.reset(new u8[32]); x2e0_patchIntersects.reset(new u8[32]);
for (int i=0 ; i<32 ; ++i) for (int i=0 ; i<32 ; ++i)
x2e0_patchFlags[i] = 1; x2e0_patchIntersects[i] = 1;
x2d4_patchDimY = 0; x2d4_patchDimY = 0;
x2d0_patchDimX = 0; x2d0_patchDimX = 0;
x2e8_28 = b; x2e8_28_recomputeClipping = recomputeClipping;
} }
void CScriptWater::Think(float dt, CStateManager& mgr) { CScriptTrigger::Think(dt, mgr); } static const CMaterialFilter SolidFilter = CMaterialFilter::MakeInclude({EMaterialTypes::Solid});
void CScriptWater::SetupGridClipping(CStateManager& mgr, int computeVerts)
{
if (x2e8_28_recomputeClipping)
{
x2e4_gridCellCount2 = 0;
x2dc_vertIntersects.reset();
x2e8_28_recomputeClipping = false;
}
if (x2e4_gridCellCount2 >= x2cc_gridCellCount)
return;
if (!x2dc_vertIntersects)
x2dc_vertIntersects.reset(new bool[(x2c4_gridDimX + 1) * (x2c8_gridDimY + 1)]);
zeus::CAABox triggerBounds = GetTriggerBoundsWR();
zeus::CVector3f basePos = triggerBounds.min;
basePos.z = triggerBounds.max.z + 0.8f;
auto gridDiv = std::div(int(x2e4_gridCellCount2), int(x2c4_gridDimX + 1));
float yOffset = x2c0_tileSize * gridDiv.quot;
float xOffset = x2c0_tileSize * gridDiv.rem;
float mag = std::min(120.f, 2.f * (x130_bounds.max.z - x130_bounds.min.z) + 0.8f);
for (int i = x2e4_gridCellCount2; i < std::min(x2e4_gridCellCount2 + computeVerts, x2cc_gridCellCount); ++i)
{
zeus::CVector3f pos = basePos;
pos.x += xOffset;
pos.y += yOffset;
x2dc_vertIntersects[i] = mgr.RayStaticIntersection(pos, zeus::CVector3f::skDown, mag, SolidFilter).IsValid();
gridDiv.rem += 1;
xOffset += x2c0_tileSize;
if (gridDiv.rem > x2c4_gridDimX)
{
yOffset += x2c0_tileSize;
xOffset = 0.f;
gridDiv.rem = 0;
}
}
x2e4_gridCellCount2 += computeVerts;
if (x2e4_gridCellCount2 < x2cc_gridCellCount)
return;
x2e4_gridCellCount2 = x2cc_gridCellCount;
x2d8_tileIntersects.reset(new bool[x2c4_gridDimX * x2c8_gridDimY]);
for (int i = 0; i < x2c8_gridDimY; ++i)
{
int rowBase = x2c4_gridDimX * i;
int nextRowBase = (x2c4_gridDimX + 1) * i;
for (int j = 0; j < x2c4_gridDimX; ++j)
{
x2d8_tileIntersects[rowBase + j] =
x2dc_vertIntersects[nextRowBase + j] ||
x2dc_vertIntersects[nextRowBase + j + 1] ||
x2dc_vertIntersects[nextRowBase + j + x2c4_gridDimX + 1] ||
x2dc_vertIntersects[nextRowBase + j + x2c4_gridDimX + 2];
}
}
int tilesPerPatch = std::min(42 / x1b4_fluidPlane->GetTileSubdivisions(), 7);
x2d0_patchDimX = (tilesPerPatch + x2c4_gridDimX - 1) / tilesPerPatch;
x2d4_patchDimY = (tilesPerPatch + x2c8_gridDimY - 1) / tilesPerPatch;
x2e0_patchIntersects.reset(new u8[x2d0_patchDimX * x2d4_patchDimY]);
int curTileY = 0;
int nextTileY;
for (int i=0 ; i<x2d4_patchDimY ; ++i, curTileY = nextTileY)
{
nextTileY = curTileY + tilesPerPatch;
int curTileX = 0;
int rowBase = x2d0_patchDimX * i;
for (int j=0 ; j<x2d0_patchDimX ; ++j)
{
int nextTileX = curTileX + tilesPerPatch;
bool allClear = true;
bool allIntersections = true;
for (int k=curTileY ; k<std::min(nextTileY, x2c8_gridDimY) ; ++k)
{
if (!allClear && !allIntersections)
break;
for (int l=curTileX ; l<std::min(nextTileX, x2c4_gridDimX) ; ++l)
{
if (x2d8_tileIntersects[k * x2c4_gridDimX + l])
{
allClear = false;
if (!allIntersections)
break;
}
else
{
allIntersections = false;
if (!allClear)
break;
}
}
}
u8 flag;
if (allIntersections)
flag = 1;
else if (allClear)
flag = 0;
else
flag = 2;
x2e0_patchIntersects[rowBase + j] = flag;
curTileX += tilesPerPatch;
}
}
x2dc_vertIntersects.reset();
}
void CScriptWater::UpdateSplashInhabitants(CStateManager& mgr)
{
// TODO: Do
}
void CScriptWater::Think(float dt, CStateManager& mgr)
{
if (!x30_24_active)
return;
bool oldCamSubmerged = x148_25_camSubmerged;
CScriptTrigger::Think(dt, mgr);
CGameCamera* curCam = mgr.GetCameraManager()->GetCurrentCamera(mgr);
if (x148_25_camSubmerged && !oldCamSubmerged)
mgr.SendScriptMsg(curCam, x8_uid, EScriptObjectMessage::AddSplashInhabitant);
else if (!x148_25_camSubmerged && oldCamSubmerged)
mgr.SendScriptMsg(curCam, x8_uid, EScriptObjectMessage::RemoveSplashInhabitant);
UpdateSplashInhabitants(mgr);
if (x2e8_30_alphaOut)
{
x2bc_alpha -= x2b8_alphaOutRecip * dt * x1b4_fluidPlane->GetAlpha();
x214_fogBias -= x2b8_alphaOutRecip * dt * x21c_origFogBias;
x218_fogMagnitude -= x2b8_alphaOutRecip * dt * x220_origFogMagnitude;
if (x2bc_alpha <= 0.f)
{
x218_fogMagnitude = 0.f;
x214_fogBias = 0.f;
x2bc_alpha = 0.f;
x2e8_30_alphaOut = false;
}
}
else if (x2e8_29_alphaIn)
{
x2bc_alpha += x2b4_alphaInRecip * dt * x1b4_fluidPlane->GetAlpha();
x214_fogBias -= x2b4_alphaInRecip * dt * x21c_origFogBias;
x218_fogMagnitude -= x2b4_alphaInRecip * dt * x220_origFogMagnitude;
if (x2bc_alpha > x1b4_fluidPlane->GetAlpha())
{
x2bc_alpha = x1b4_fluidPlane->GetAlpha();
x214_fogBias = x21c_origFogBias;
x218_fogMagnitude = x220_origFogMagnitude;
x2e8_29_alphaIn = false;
}
}
if (x2e8_26_morphing)
{
bool stillMorphing = true;
if (x2e8_25_morphIn)
{
x1f8_morphFactor += dt / x1d0_morphInTime;
if (x1f8_morphFactor > 1.f)
{
x1f8_morphFactor = 1.f;
stillMorphing = false;
}
}
else
{
x1f8_morphFactor -= dt / x1f4_morphOutTime;
if (x1f8_morphFactor < 0.f)
{
x1f8_morphFactor = 0.f;
stillMorphing = false;
}
}
SetTranslation(zeus::CVector3f::lerp(x1d4_positionOrig, x1b8_positionMorphed, x1f8_morphFactor));
zeus::CVector3f lerpExtent = zeus::CVector3f::lerp(x1e0_extentOrig, x1c4_extentMorphed, x1f8_morphFactor);
x130_bounds = zeus::CAABox(lerpExtent * -0.5f, lerpExtent * 0.5f);
CalculateRenderBounds();
if (!stillMorphing)
SetMorphing(false);
else
SetupGrid(false);
}
SetupGridClipping(mgr, 4);
}
void CScriptWater::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId other, CStateManager& mgr) void CScriptWater::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId other, CStateManager& mgr)
{ {
switch (msg)
{
case EScriptObjectMessage::Next:
if (!x30_24_active)
break;
x2e8_25_morphIn = !x2e8_25_morphIn;
if (x2e8_25_morphIn)
{
for (const SConnection& conn : x20_conns)
{
if (conn.x0_state != EScriptObjectState::Play ||
conn.x4_msg != EScriptObjectMessage::Activate)
continue;
auto list = mgr.GetIdListForScript(conn.x8_objId);
if (list.first == mgr.GetIdListEnd())
continue;
if (TCastToConstPtr<CScriptTrigger> trig = mgr.GetObjectById(list.first->second))
{
x1b8_positionMorphed = trig->GetTranslation();
x1c4_extentMorphed = trig->GetTriggerBoundsOR().max - trig->GetTriggerBoundsOR().min;
x1f0_damageMorphed = trig->GetDamageInfo().GetDamage();
x1d4_positionOrig = GetTranslation();
x1e0_extentOrig = x130_bounds.max - x130_bounds.min;
x1ec_damageOrig = x100_damageInfo.GetDamage();
break;
}
}
}
SetMorphing(true);
break;
case EScriptObjectMessage::Activate:
x2e8_30_alphaOut = false;
if (std::fabs(x2ac_alphaInTime) < 0.00001f)
{
x2bc_alpha = x1b4_fluidPlane->GetAlpha();
x214_fogBias = x21c_origFogBias;
x218_fogMagnitude = x220_origFogMagnitude;
}
else
{
x2e8_29_alphaIn = true;
}
break;
case EScriptObjectMessage::Action:
x2e8_29_alphaIn = false;
if (std::fabs(x2b0_alphaOutTime) < 0.00001f)
{
x2bc_alpha = 0.f;
x214_fogBias = 0.f;
x218_fogMagnitude = 0.f;
}
else
{
x2e8_30_alphaOut = true;
}
break;
default:
break;
}
CScriptTrigger::AcceptScriptMsg(msg, other, mgr); CScriptTrigger::AcceptScriptMsg(msg, other, mgr);
} }
void CScriptWater::PreRender(CStateManager &, const zeus::CFrustum &) {} void CScriptWater::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum)
{
if (x2e8_27_allowRender)
{
zeus::CAABox aabb = GetSortingBounds(mgr);
xe4_30_outOfFrustum = !frustum.aabbFrustumTest(aabb);
if (!xe4_30_outOfFrustum)
{
if (x4_areaId != kInvalidAreaId)
{
if (x90_actorLights->GetMaxAreaLights() &&
(xe4_29_actorLightsDirty || x90_actorLights->GetIsDirty()))
{
const CGameArea* area = mgr.GetWorld()->GetAreaAlways(x4_areaId);
if (area->IsPostConstructed())
{
x90_actorLights->BuildAreaLightList(mgr, *area, GetTriggerBoundsWR());
xe4_29_actorLightsDirty = false;
}
}
x90_actorLights->BuildDynamicLightList(mgr, GetTriggerBoundsWR());
}
x150_frustum = frustum;
}
}
else
{
xe4_30_outOfFrustum = true;
}
}
void CScriptWater::AddToRenderer(const zeus::CFrustum& /*frustum*/, const CStateManager& mgr) const void CScriptWater::AddToRenderer(const zeus::CFrustum& /*frustum*/, const CStateManager& mgr) const
{ {
zeus::CPlane plane; if (!xe4_30_outOfFrustum)
plane.vec = x34_transform.origin.normalized(); {
plane.d = x34_transform.origin.z + x130_bounds.max.z; zeus::CPlane plane;
zeus::CAABox renderBounds = GetSortingBounds(mgr); plane.vec = x34_transform.origin.normalized();
mgr.AddDrawableActorPlane(*this, plane, renderBounds); plane.d = x34_transform.origin.z + x130_bounds.max.z;
zeus::CAABox renderBounds = GetSortingBounds(mgr);
mgr.AddDrawableActorPlane(*this, plane, renderBounds);
}
} }
void CScriptWater::Render(const CStateManager&) const {} void CScriptWater::Render(const CStateManager& mgr) const
void CScriptWater::Touch(CActor&, CStateManager&)
{ {
if (x30_24_active && !xe4_30_outOfFrustum)
{
float zOffset = 0.5f * (x9c_renderBounds.max.z + x9c_renderBounds.min.z) - x34_transform.origin.z;
zeus::CAABox aabb = x9c_renderBounds.getTransformedAABox(
zeus::CTransform::Translate(-x34_transform.origin.x, -x34_transform.origin.y,
-x34_transform.origin.z - zOffset));
zeus::CTransform xf = x34_transform;
xf.origin.z += zOffset;
zeus::CVector3f areaCenter = mgr.GetWorld()->GetAreaAlways(mgr.GetNextAreaId())->GetAABB().center();
std::experimental::optional<CRippleManager> rippleMan(mgr.GetFluidPlaneManager()->GetRippleManager());
x1b4_fluidPlane->Render(mgr, x2bc_alpha, aabb, xf,
mgr.GetWorld()->GetAreaAlways(x4_areaId)->GetTransform(), false,
x150_frustum, rippleMan, x8_uid, x2d8_tileIntersects.get(),
x2c4_gridDimX, x2c8_gridDimY, areaCenter);
if (x214_fogBias != 0.f)
{
if (mgr.GetPlayerState()->CanVisorSeeFog(mgr))
{
float fogLevel = mgr.IntegrateVisorFog(x218_fogMagnitude *
std::sin(x224_fogSpeed * CGraphics::GetSecondsMod900()) +
x214_fogBias);
if (fogLevel > 0.f)
{
zeus::CAABox fogBox = GetTriggerBoundsWR();
fogBox.min.z = fogBox.max.z;
fogBox.max.z += fogLevel;
zeus::CTransform modelXf = zeus::CTransform::Translate(fogBox.center()) *
zeus::CTransform::Scale((fogBox.max - fogBox.min) * 0.5f);
zeus::CAABox renderAABB(zeus::CVector3f::skNegOne, zeus::CVector3f::skOne);
CGraphics::SetModelMatrix(modelXf);
g_Renderer->SetAmbientColor(zeus::CColor::skWhite);
g_Renderer->RenderFogVolume(x228_fogColor, renderAABB, nullptr, nullptr);
}
}
}
CGraphics::DisableAllLights();
}
CActor::Render(mgr);
}
void CScriptWater::Touch(CActor& otherAct, CStateManager& mgr)
{
if (!x30_24_active)
return;
CScriptTrigger::Touch(otherAct, mgr);
if (otherAct.GetMaterialList().HasMaterial(EMaterialTypes::Trigger))
return;
for (auto& inhab : x1fc_waterInhabitants)
if (inhab.first == otherAct.GetUniqueId())
{
inhab.second = true;
return;
}
auto touchBounds = otherAct.GetTouchBounds();
if (!touchBounds)
return;
x1fc_waterInhabitants.emplace_back(otherAct.GetUniqueId(), true);
float triggerMaxZ = GetTriggerBoundsWR().max.z;
if (touchBounds->min.z <= triggerMaxZ && touchBounds->max.z >= triggerMaxZ)
otherAct.FluidFXThink(EFluidState::Zero, *this, mgr);
mgr.SendScriptMsg(&otherAct, x8_uid, EScriptObjectMessage::AddSplashInhabitant);
} }
void CScriptWater::CalculateRenderBounds() void CScriptWater::CalculateRenderBounds()
@ -143,12 +502,15 @@ void CScriptWater::CalculateRenderBounds()
x9c_renderBounds = zeus::CAABox(transAABBMin, transAABBMax); x9c_renderBounds = zeus::CAABox(transAABBMin, transAABBMax);
} }
zeus::CAABox CScriptWater::GetSortingBounds(const CStateManager&) const zeus::CAABox CScriptWater::GetSortingBounds(const CStateManager& mgr) const
{ {
return {}; zeus::CVector3f max = x9c_renderBounds.max;
max.z = std::max(max.z, x9c_renderBounds.max.z - 1.f + x214_fogBias + x218_fogMagnitude);
return {x9c_renderBounds.min, max};
} }
EWeaponCollisionResponseTypes CScriptWater::GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, CWeaponMode&, int) EWeaponCollisionResponseTypes CScriptWater::GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&,
CWeaponMode&, int)
{ {
return EWeaponCollisionResponseTypes::Water; return EWeaponCollisionResponseTypes::Water;
} }
@ -175,10 +537,18 @@ float CScriptWater::GetSplashEffectScale(float dt) const
u32 CScriptWater::GetSplashIndex(float dt) const u32 CScriptWater::GetSplashIndex(float dt) const
{ {
u32 idx = dt * 3.f; auto idx = u32(dt * 3.f);
return (idx < 3 ? idx : idx - 1); return (idx < 3 ? idx : idx - 1);
} }
void CScriptWater::SetMorphing(bool m)
{
if (m == x2e8_26_morphing)
return;
x2e8_26_morphing = m;
SetupGrid(!m);
}
const CScriptWater* CScriptWater::GetNextConnectedWater(const CStateManager& mgr) const const CScriptWater* CScriptWater::GetNextConnectedWater(const CStateManager& mgr) const
{ {
for (const SConnection& conn : x20_conns) for (const SConnection& conn : x20_conns)

View File

@ -15,23 +15,22 @@ private:
static const float kSplashScales[6]; static const float kSplashScales[6];
zeus::CFrustum x150_frustum; zeus::CFrustum x150_frustum;
std::unique_ptr<CFluidPlaneCPU> x1b4_fluidPlane; std::unique_ptr<CFluidPlaneCPU> x1b4_fluidPlane;
zeus::CVector3f x1b8_position; zeus::CVector3f x1b8_positionMorphed;
zeus::CVector3f x1c4_extent; zeus::CVector3f x1c4_extentMorphed;
float x1d0_f2; float x1d0_morphInTime;
zeus::CVector3f x1d4_position2; zeus::CVector3f x1d4_positionOrig;
zeus::CVector3f x1e0_extent2; zeus::CVector3f x1e0_extentOrig;
float x1ec_damage; float x1ec_damageOrig;
float x1f0_damage2; float x1f0_damageMorphed;
float x1f4_; float x1f4_morphOutTime;
float x1f8_lightmapDoubleBlendFactor = 0.f; float x1f8_morphFactor = 0.f;
std::list<std::pair<TUniqueId, bool>> x1fc_waterInhabitants; std::list<std::pair<TUniqueId, bool>> x1fc_waterInhabitants;
u32 x210_; float x214_fogBias;
float x214_; float x218_fogMagnitude;
float x218_; float x21c_origFogBias;
float x21c_; float x220_origFogMagnitude;
float x220_; float x224_fogSpeed;
float x224_; zeus::CColor x228_fogColor;
zeus::CColor x228_;
ResId x22c_splashParticle1Id; ResId x22c_splashParticle1Id;
ResId x230_splashParticle2Id; ResId x230_splashParticle2Id;
ResId x234_splashParticle3Id; ResId x234_splashParticle3Id;
@ -39,58 +38,60 @@ private:
std::experimental::optional<TLockedToken<CGenDescription>> x23c_; std::experimental::optional<TLockedToken<CGenDescription>> x23c_;
ResId x24c_particle5Id; ResId x24c_particle5Id;
std::experimental::optional<TLockedToken<CGenDescription>> x250_visorRunoffEffect; std::experimental::optional<TLockedToken<CGenDescription>> x250_visorRunoffEffect;
u16 x260_; u16 x260_unkSfx;
u16 x262_visorRunoffSfx; u16 x262_visorRunoffSfx;
rstl::reserved_vector<std::experimental::optional<TLockedToken<CGenDescription>>, 3> x264_splashEffects; rstl::reserved_vector<std::experimental::optional<TLockedToken<CGenDescription>>, 3> x264_splashEffects;
rstl::reserved_vector<u16, 3> x298_splashSounds; rstl::reserved_vector<u16, 3> x298_splashSounds;
zeus::CColor x2a4_c1; zeus::CColor x2a4_splashColor;
zeus::CColor x2a8_c2; zeus::CColor x2a8_unkColor;
float x2ac_lf2; float x2ac_alphaInTime;
float x2b0_lf3; float x2b0_alphaOutTime;
float x2b4_; float x2b4_alphaInRecip;
float x2b8_; float x2b8_alphaOutRecip;
float x2bc_alpha; float x2bc_alpha;
float x2c0_tileSize; float x2c0_tileSize;
u32 x2c4_gridDimX = 0; int x2c4_gridDimX = 0;
u32 x2c8_gridDimY = 0; int x2c8_gridDimY = 0;
u32 x2cc_gridCellCount = 0; int x2cc_gridCellCount = 0;
u32 x2d0_patchDimX = 0; int x2d0_patchDimX = 0;
u32 x2d4_patchDimY = 0; int x2d4_patchDimY = 0;
std::unique_ptr<bool[]> x2d8_gridFlags; std::unique_ptr<bool[]> x2d8_tileIntersects;
std::unique_ptr<bool[]> x2dc_; std::unique_ptr<bool[]> x2dc_vertIntersects;
std::unique_ptr<u8[]> x2e0_patchFlags; std::unique_ptr<u8[]> x2e0_patchIntersects; // 0: all clear, 1: all intersect, 2: partial intersect
u32 x2e4_gridCellCount2 = 0; int x2e4_gridCellCount2 = 0;
union union
{ {
struct struct
{ {
bool x2e8_24_b4 : 1; bool x2e8_24_b4 : 1;
bool x2e8_25 : 1; bool x2e8_25_morphIn : 1;
bool x2e8_26 : 1; bool x2e8_26_morphing : 1;
bool x2e8_27_b2 : 1; bool x2e8_27_allowRender : 1;
bool x2e8_28 : 1; bool x2e8_28_recomputeClipping : 1;
bool x2e8_29 : 1; bool x2e8_29_alphaIn : 1;
bool x2e8_30 : 1; bool x2e8_30_alphaOut : 1;
}; };
u32 _dummy = 0; u32 _dummy = 0;
}; };
void SetupGrid(bool b); void SetupGrid(bool recomputeClipping);
void SetupGridClipping(CStateManager& mgr, int computeVerts);
void UpdateSplashInhabitants(CStateManager& mgr);
public: public:
CScriptWater(CStateManager& mgr, TUniqueId uid, const std::string& name, const CEntityInfo& info, CScriptWater(CStateManager& mgr, TUniqueId uid, const std::string& name, const CEntityInfo& info,
const zeus::CVector3f& pos, const zeus::CAABox& box, const urde::CDamageInfo& dInfo, const zeus::CVector3f& pos, const zeus::CAABox& box, const urde::CDamageInfo& dInfo,
zeus::CVector3f& orientedForce, ETriggerFlags triggerFlags, bool b1, bool b2, zeus::CVector3f& orientedForce, ETriggerFlags triggerFlags, bool thermalCold, bool allowRender,
ResId patternMap1, ResId patternMap2, ResId colorMap, ResId bumpMap, ResId envMap, ResId patternMap1, ResId patternMap2, ResId colorMap, ResId bumpMap, ResId envMap,
ResId envBumpMap, ResId unusedMap, const zeus::CVector3f& bumpLightDir, float bumpScale, ResId envBumpMap, ResId unusedMap, const zeus::CVector3f& bumpLightDir, float bumpScale,
float f2, float f3, bool active, CFluidPlane::EFluidType fluidType, bool b4, float alpha, float morphInTime, float morphOutTime, bool active, CFluidPlane::EFluidType fluidType, bool b4,
const CFluidUVMotion& uvMot, float turbSpeed, float turbDistance, float turbFreqMax, float alpha, const CFluidUVMotion& uvMot, float turbSpeed, float turbDistance, float turbFreqMax,
float turbFreqMin, float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax, float turbFreqMin, float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax,
float turbAmplitudeMin, const zeus::CColor& c1, const zeus::CColor& c2, ResId splashParticle1, float turbAmplitudeMin, const zeus::CColor& splashColor, const zeus::CColor& unkColor,
ResId splashParticle2, ResId splashParticle3, ResId particle4, ResId particle5, s32 i1, ResId splashParticle1, ResId splashParticle2, ResId splashParticle3, ResId particle4, ResId particle5,
s32 visorRunoffSfx, s32 splashSfx1, s32 splashSfx2, s32 splashSfx3, float tileSize, s32 unkSfx, s32 visorRunoffSfx, s32 splashSfx1, s32 splashSfx2, s32 splashSfx3, float tileSize,
u32 tileSubdivisions, float specularMin, float specularMax, float reflectionSize, u32 tileSubdivisions, float specularMin, float specularMax, float reflectionSize,
float fluidPlaneF2, float reflectionBlend, float slF6, float slF7, float slF8, float rippleIntensity, float reflectionBlend, float fogBias, float fogMagnitude, float fogSpeed,
const zeus::CColor& c3, ResId lightmapId, float unitsPerLightmapTexel, float lF2, float lF3, const zeus::CColor& fogColor, ResId lightmapId, float unitsPerLightmapTexel, float alphaInTime,
u32, u32, bool, s32, s32, std::unique_ptr<u32[]>&& u32Arr); float alphaOutTime, u32, u32, bool, s32, s32, std::unique_ptr<u32[]>&& u32Arr);
void Think(float, CStateManager&); void Think(float, CStateManager&);
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&);
@ -100,32 +101,30 @@ public:
void Touch(CActor &, CStateManager &); void Touch(CActor &, CStateManager &);
void CalculateRenderBounds(); void CalculateRenderBounds();
zeus::CAABox GetSortingBounds(const CStateManager&) const; zeus::CAABox GetSortingBounds(const CStateManager&) const;
void RenderSurface();
EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, CWeaponMode&, EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, CWeaponMode&,
int); int);
void UpdateSplashInhabitants(CStateManager&);
s16 GetSplashSound(float) const; s16 GetSplashSound(float) const;
const std::experimental::optional<TLockedToken<CGenDescription>>& GetSplashEffect(float) const; const std::experimental::optional<TLockedToken<CGenDescription>>& GetSplashEffect(float) const;
float GetSplashEffectScale(float) const; float GetSplashEffectScale(float) const;
u32 GetSplashIndex(float) const; u32 GetSplashIndex(float) const;
void FluidPlane(); CFluidPlaneCPU& FluidPlane() { return *x1b4_fluidPlane; }
zeus::CPlane GetWRSurfacePlane() const; zeus::CPlane GetWRSurfacePlane() const;
float GetSurfaceZ() const; float GetSurfaceZ() const;
bool IsMorphing() const; bool IsMorphing() const { return x2e8_26_morphing; }
void SetMorphing(bool); void SetMorphing(bool);
zeus::CColor GetSplashColor() const; float GetMorphFactor() const { return x1f8_morphFactor; }
void SetFrustumPlanes(const zeus::CFrustum& frustum); zeus::CColor GetSplashColor() const { return x2a4_splashColor; }
const zeus::CFrustum& GetFrustumPlanes() const; void SetFrustumPlanes(const zeus::CFrustum& frustum) { x150_frustum = frustum; }
const zeus::CFrustum& GetFrustumPlanes() const { return x150_frustum; }
CFluidPlaneCPU& GetFluidPlane() const { return *x1b4_fluidPlane; } CFluidPlaneCPU& GetFluidPlane() const { return *x1b4_fluidPlane; }
const std::experimental::optional<TLockedToken<CGenDescription>>& GetVisorRunoffEffect() const const std::experimental::optional<TLockedToken<CGenDescription>>& GetVisorRunoffEffect() const
{ return x250_visorRunoffEffect; } { return x250_visorRunoffEffect; }
u16 GetVisorRunoffSfx() const { return x262_visorRunoffSfx; } u16 GetVisorRunoffSfx() const { return x262_visorRunoffSfx; }
const CScriptWater* GetNextConnectedWater(const CStateManager& mgr) const; const CScriptWater* GetNextConnectedWater(const CStateManager& mgr) const;
float GetLightmapDoubleBlendFactor() const { return x1f8_lightmapDoubleBlendFactor; } u8 GetPatchRenderFlags(int x, int y) const { return x2e0_patchIntersects[y * x2d0_patchDimX + x]; }
u8 GetPatchRenderFlags(int x, int y) const { return x2e0_patchFlags[y * x2d0_patchDimX + x]; } int GetPatchDimensionX() const { return x2d0_patchDimX; }
u32 GetPatchDimensionX() const { return x2d0_patchDimX; } int GetPatchDimensionY() const { return x2d4_patchDimY; }
u32 GetPatchDimensionY() const { return x2d4_patchDimY; }
}; };
} }

View File

@ -327,20 +327,13 @@ CAnimationParameters ScriptLoader::LoadAnimationParameters(CInputStream& in)
CFluidUVMotion ScriptLoader::LoadFluidUVMotion(CInputStream& in) CFluidUVMotion ScriptLoader::LoadFluidUVMotion(CInputStream& in)
{ {
/* NOTE: DO NOT RE-ORDER THIS FUNCTION auto motion = CFluidUVMotion::EFluidUVMotion(in.readUint32Big());
* For some inexplicable reason Retro stores the layers in this order.
* Changing it will change the behavior of CFluidUVMotion,
* which is something we don't want.
* - Phil
* P.S: If you do change it, I'll hunt you down and put pink lipstick on your dog.
*/
CFluidUVMotion::EFluidUVMotion motion = CFluidUVMotion::EFluidUVMotion(in.readUint32Big());
float a = in.readFloatBig(); float a = in.readFloatBig();
float b = in.readFloatBig(); float b = in.readFloatBig();
b = zeus::degToRad(b) - M_PIF; b = zeus::degToRad(b) - M_PIF;
float c = in.readFloatBig(); float c = in.readFloatBig();
float d = in.readFloatBig(); float d = in.readFloatBig();
CFluidUVMotion::SFluidLayerMotion layerMotion2(motion, a, b, c, d); CFluidUVMotion::SFluidLayerMotion pattern1Layer(motion, a, b, c, d);
motion = CFluidUVMotion::EFluidUVMotion(in.readUint32Big()); motion = CFluidUVMotion::EFluidUVMotion(in.readUint32Big());
a = in.readFloatBig(); a = in.readFloatBig();
@ -348,7 +341,7 @@ CFluidUVMotion ScriptLoader::LoadFluidUVMotion(CInputStream& in)
b = zeus::degToRad(b) - M_PIF; b = zeus::degToRad(b) - M_PIF;
c = in.readFloatBig(); c = in.readFloatBig();
d = in.readFloatBig(); d = in.readFloatBig();
CFluidUVMotion::SFluidLayerMotion layerMotion3(motion, a, b, c, d); CFluidUVMotion::SFluidLayerMotion pattern2Layer(motion, a, b, c, d);
motion = CFluidUVMotion::EFluidUVMotion(in.readUint32Big()); motion = CFluidUVMotion::EFluidUVMotion(in.readUint32Big());
a = in.readFloatBig(); a = in.readFloatBig();
@ -356,14 +349,14 @@ CFluidUVMotion ScriptLoader::LoadFluidUVMotion(CInputStream& in)
b = zeus::degToRad(b) - M_PIF; b = zeus::degToRad(b) - M_PIF;
c = in.readFloatBig(); c = in.readFloatBig();
d = in.readFloatBig(); d = in.readFloatBig();
CFluidUVMotion::SFluidLayerMotion layerMotion1(motion, a, b, c, d); CFluidUVMotion::SFluidLayerMotion colorLayer(motion, a, b, c, d);
a = in.readFloatBig(); a = in.readFloatBig();
b = in.readFloatBig(); b = in.readFloatBig();
b = zeus::degToRad(b) - M_PIF; b = zeus::degToRad(b) - M_PIF;
return CFluidUVMotion(a, b, layerMotion1, layerMotion2, layerMotion3); return CFluidUVMotion(a, b, colorLayer, pattern1Layer, pattern2Layer);
} }
zeus::CTransform ScriptLoader::ConvertEditorEulerToTransform4f(const zeus::CVector3f& orientation, zeus::CTransform ScriptLoader::ConvertEditorEulerToTransform4f(const zeus::CVector3f& orientation,
@ -1206,68 +1199,68 @@ CEntity* ScriptLoader::LoadWater(CStateManager& mgr, CInputStream& in, int propC
ETriggerFlags::DetectProjectiles4 | ETriggerFlags::DetectBombs | ETriggerFlags::DetectProjectiles4 | ETriggerFlags::DetectBombs |
ETriggerFlags::DetectPowerBombs | ETriggerFlags::DetectProjectiles5 | ETriggerFlags::DetectPowerBombs | ETriggerFlags::DetectProjectiles5 |
ETriggerFlags::DetectProjectiles6 | ETriggerFlags::DetectProjectiles7; ETriggerFlags::DetectProjectiles6 | ETriggerFlags::DetectProjectiles7;
bool b1 = in.readBool(); bool thermalCold = in.readBool();
bool displaySurface = in.readBool(); bool displaySurface = in.readBool();
ResId textureId1 = in.readUint32Big(); ResId patternMap1 = in.readUint32Big();
ResId textureId2 = in.readUint32Big(); ResId patternMap2 = in.readUint32Big();
ResId textureId3 = in.readUint32Big(); ResId colorMap = in.readUint32Big();
ResId textureId4 = in.readUint32Big(); ResId bumpMap = in.readUint32Big();
ResId textureId5 = in.readUint32Big(); ResId _envMap = in.readUint32Big();
ResId textureId6 = in.readUint32Big(); ResId _envBumpMap = in.readUint32Big();
zeus::CVector3f v2; zeus::CVector3f _bumpLightDir;
v2.readBig(in); _bumpLightDir.readBig(in);
zeus::CVector3f otherV2 = v2; zeus::CVector3f bumpLightDir = _bumpLightDir;
if (otherV2.canBeNormalized()) if (!bumpLightDir.canBeNormalized())
otherV2.assign(0.f, 0.f, -1.f); bumpLightDir.assign(0.f, 0.f, -1.f);
float f1 = 1.f / in.readFloatBig(); float bumpScale = 1.f / in.readFloatBig();
float f2 = in.readFloatBig(); float morphInTime = in.readFloatBig();
float f3 = in.readFloatBig(); float morphOutTime = in.readFloatBig();
bool active = in.readBool(); bool active = in.readBool();
CFluidPlane::EFluidType fluidType = CFluidPlane::EFluidType(in.readUint32Big()); auto fluidType = CFluidPlane::EFluidType(in.readUint32Big());
bool b4 = in.readBool(); bool b4 = in.readBool();
float f4 = in.readFloatBig(); float alpha = in.readFloatBig();
CFluidUVMotion fluidMotion = LoadFluidUVMotion(in); CFluidUVMotion uvMotion = LoadFluidUVMotion(in);
float f5 = in.readFloatBig(); float turbSpeed = in.readFloatBig();
float f6 = in.readFloatBig(); float turbDistance = in.readFloatBig();
float f7 = in.readFloatBig(); float turbFreqMax = in.readFloatBig();
float f8 = in.readFloatBig(); float turbFreqMin = in.readFloatBig();
float f9 = zeus::degToRad(in.readFloatBig()); float turbPhaseMax = zeus::degToRad(in.readFloatBig());
float f10 = zeus::degToRad(in.readFloatBig()); float turbPhaseMin = zeus::degToRad(in.readFloatBig());
float f11 = in.readFloatBig(); float turbAmplitudeMax = in.readFloatBig();
float f12 = in.readFloatBig(); float turbAmplitudeMin = in.readFloatBig();
zeus::CColor c1; zeus::CColor splashColor;
c1.readRGBABig(in); splashColor.readRGBABig(in);
zeus::CColor c2; zeus::CColor unkColor;
c2.readRGBABig(in); unkColor.readRGBABig(in);
ResId enterParticle = in.readUint32Big(); ResId splashParticle1 = in.readUint32Big();
ResId partId2 = in.readUint32Big(); ResId splashParticle2 = in.readUint32Big();
ResId partId3 = in.readUint32Big(); ResId splashParticle3 = in.readUint32Big();
ResId partId4 = in.readUint32Big(); ResId particle4 = in.readUint32Big();
ResId partId5 = in.readUint32Big(); ResId particle5 = in.readUint32Big();
u32 soundId1 = in.readUint32Big(); u32 unkSfx = in.readUint32Big();
u32 soundId2 = in.readUint32Big(); u32 visorRunoffSfx = in.readUint32Big();
u32 soundId3 = in.readUint32Big(); u32 splashSfx1 = in.readUint32Big();
u32 soundId4 = in.readUint32Big(); u32 splashSfx2 = in.readUint32Big();
u32 soundId5 = in.readUint32Big(); u32 splashSfx3 = in.readUint32Big();
float f13 = in.readFloatBig(); float tileSize = in.readFloatBig();
u32 w19 = in.readUint32Big(); u32 tileSubdivisions = in.readUint32Big();
float f14 = in.readFloatBig(); float specularMin = in.readFloatBig();
float f15 = in.readFloatBig(); float specularMax = in.readFloatBig();
float f16 = in.readFloatBig(); float reflectionSize = in.readFloatBig();
float f17 = in.readFloatBig(); float rippleIntensity = in.readFloatBig();
float f18 = in.readFloatBig(); float reflectionBlend = in.readFloatBig();
float f19 = in.readFloatBig(); float fogBias = in.readFloatBig();
float heatWaveHeight = in.readFloatBig(); float fogMagnitude = in.readFloatBig();
float heatWaveSpeed = in.readFloatBig(); float fogSpeed = in.readFloatBig();
zeus::CColor heatWaveColor; zeus::CColor fogColor;
heatWaveColor.readRGBABig(in); fogColor.readRGBABig(in);
ResId lightmap = in.readUint32Big(); ResId lightmap = in.readUint32Big();
float f22 = in.readFloatBig(); float unitsPerLightmapTexel = in.readFloatBig();
float f23 = in.readFloatBig(); float alphaInTime = in.readFloatBig();
float f24 = in.readFloatBig(); float alphaOutTime = in.readFloatBig();
u32 w21 = in.readUint32Big(); u32 w21 = in.readUint32Big();
u32 w22 = in.readUint32Big(); u32 w22 = in.readUint32Big();
bool b5 = in.readBool(); bool b5 = in.readBool();
@ -1287,21 +1280,23 @@ CEntity* ScriptLoader::LoadWater(CStateManager& mgr, CInputStream& in, int propC
zeus::CAABox box(-extent * 0.5f, extent * 0.5f); zeus::CAABox box(-extent * 0.5f, extent * 0.5f);
ResId realTextureId6 = -1; ResId envBumpMap = -1;
if (textureId4 == -1) if (bumpMap == -1)
realTextureId6 = textureId6; envBumpMap = _envBumpMap;
ResId realTextureId5 = -1; ResId envMap = -1;
if (textureId4 == -1) if (bumpMap == -1)
realTextureId5 = textureId5; envMap = _envMap;
return new CScriptWater( return new CScriptWater(
mgr, mgr.AllocateUniqueId(), name, info, position, box, dInfo, orientedForce, triggerFlags, b1, displaySurface, mgr, mgr.AllocateUniqueId(), name, info, position, box, dInfo, orientedForce, triggerFlags, thermalCold,
textureId1, textureId2, textureId3, textureId4, realTextureId5, realTextureId6, -1, otherV2, f1, f2, f3, active, displaySurface, patternMap1, patternMap2, colorMap, bumpMap, envMap, envBumpMap, -1, bumpLightDir, bumpScale,
fluidType, b4, f4, fluidMotion, f5, f6, f7, f8, f9, f10, f11, f12, c1, c2, enterParticle, partId2, partId3, morphInTime, morphOutTime, active, fluidType, b4, alpha, uvMotion, turbSpeed, turbDistance, turbFreqMax,
partId4, partId5, soundId1, soundId2, soundId3, soundId4, soundId5, f13, w19, f14, f15, f16, f17, f18, f19, turbFreqMin, turbPhaseMax, turbPhaseMin, turbAmplitudeMax, turbAmplitudeMin, splashColor, unkColor,
heatWaveHeight, heatWaveSpeed, heatWaveColor, lightmap, f22, f23, f24, w21, w22, b5, bitVal0, bitVal1, splashParticle1, splashParticle2, splashParticle3, particle4, particle5, unkSfx, visorRunoffSfx, splashSfx1,
std::move(bitset)); splashSfx2, splashSfx3, tileSize, tileSubdivisions, specularMin, specularMax, reflectionSize, rippleIntensity,
reflectionBlend, fogBias, fogMagnitude, fogSpeed, fogColor, lightmap, unitsPerLightmapTexel, alphaInTime,
alphaOutTime, w21, w22, b5, bitVal0, bitVal1, std::move(bitset));
} }
CEntity* ScriptLoader::LoadWarWasp(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) CEntity* ScriptLoader::LoadWarWasp(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)