diff --git a/Runtime/World/CFishCloud.cpp b/Runtime/World/CFishCloud.cpp index a518c3fc2..81399b7bd 100644 --- a/Runtime/World/CFishCloud.cpp +++ b/Runtime/World/CFishCloud.cpp @@ -63,14 +63,18 @@ CFishCloud::CFishCloud(TUniqueId uid, bool active, std::string_view name, const x1b0_models.emplace_back(std::make_unique(aRes)); x250_27_validModel = true; } - if (part1.IsValid()) + if (part1.IsValid()) { x1c4_particleDescs.push_back(g_SimplePool->GetObj({FOURCC('PART'), part1})); - if (part2.IsValid()) + } + if (part2.IsValid()) { x1c4_particleDescs.push_back(g_SimplePool->GetObj({FOURCC('PART'), part2})); - if (part3.IsValid()) + } + if (part3.IsValid()) { x1c4_particleDescs.push_back(g_SimplePool->GetObj({FOURCC('PART'), part3})); - if (part4.IsValid()) + } + if (part4.IsValid()) { x1c4_particleDescs.push_back(g_SimplePool->GetObj({FOURCC('PART'), part4})); + } for (const auto& p : x1c4_particleDescs) { x1f8_particleGens.emplace_back(std::make_unique(p)); x1f8_particleGens.back()->SetParticleEmission(false); @@ -79,7 +83,7 @@ CFishCloud::CFishCloud(TUniqueId uid, bool active, std::string_view name, const x21c_deathParticleCounts.push_back(partCount2); x21c_deathParticleCounts.push_back(partCount3); x21c_deathParticleCounts.push_back(partCount4); - zeus::CAABox aabb = GetBoundingBox(); + const zeus::CAABox aabb = GetBoundingBox(); x238_partitionPitch = (aabb.max - aabb.min) / 7.f; x244_ooPartitionPitch = 1.f / x238_partitionPitch; } @@ -87,17 +91,18 @@ CFishCloud::CFishCloud(TUniqueId uid, bool active, std::string_view name, const void CFishCloud::Accept(IVisitor& visitor) { visitor.Visit(this); } void CFishCloud::UpdateParticles(float dt) { - for (auto& p : x1f8_particleGens) + for (auto& p : x1f8_particleGens) { p->Update(dt); + } } void CFishCloud::UpdatePartitionList() { xf8_boidPartitionLists.clear(); xf8_boidPartitionLists.resize(xf8_boidPartitionLists.capacity()); - auto aabb = GetBoundingBox(); + const auto aabb = GetBoundingBox(); for (auto& b : xe8_boids) { - zeus::CVector3f idxs = (b.x0_pos - aabb.min) * x244_ooPartitionPitch; - int idx = int(idxs.x()) + int(idxs.y()) * 7 + int(idxs.z()) * 49; + const zeus::CVector3f idxs = (b.x0_pos - aabb.min) * x244_ooPartitionPitch; + const int idx = int(idxs.x()) + int(idxs.y()) * 7 + int(idxs.z()) * 49; if (idx >= 0 && idx < 343) { b.x1c_next = xf8_boidPartitionLists[idx]; xf8_boidPartitionLists[idx] = &b; @@ -106,39 +111,41 @@ void CFishCloud::UpdatePartitionList() { } bool CFishCloud::PointInBox(const zeus::CAABox& aabb, const zeus::CVector3f& point) const { - if (!x250_25_worldSpace) + if (!x250_25_worldSpace) { return aabb.pointInside(point); + } return GetUntransformedBoundingBox().pointInside(GetTransform().transposeRotate(point - GetTranslation())); } zeus::CPlane CFishCloud::FindClosestPlane(const zeus::CAABox& aabb, const zeus::CVector3f& point) const { if (!x250_25_worldSpace) { float minDist = FLT_MAX; - zeus::CAABox::EBoxFaceId minFace = zeus::CAABox::EBoxFaceId::YMin; + auto minFace = zeus::CAABox::EBoxFaceId::YMin; for (int i = 0; i < 6; ++i) { - auto tri = aabb.getTri(zeus::CAABox::EBoxFaceId(i), 0); - float dist = zeus::CPlane(tri.x10_verts[0], tri.x10_verts[2], tri.x10_verts[1]).pointToPlaneDist(point); + const auto tri = aabb.getTri(zeus::CAABox::EBoxFaceId(i), 0); + const float dist = zeus::CPlane(tri.x10_verts[0], tri.x10_verts[2], tri.x10_verts[1]).pointToPlaneDist(point); if (dist >= 0.f && dist < minDist) { minDist = dist; minFace = zeus::CAABox::EBoxFaceId(i); } } - auto tri = aabb.getTri(minFace, 0); + const auto tri = aabb.getTri(minFace, 0); return zeus::CPlane(tri.x10_verts[0], tri.x10_verts[2], tri.x10_verts[1]); } else { - auto unPoint = GetTransform().transposeRotate(point - GetTranslation()); - auto unAabb = GetUntransformedBoundingBox(); + const auto unPoint = GetTransform().transposeRotate(point - GetTranslation()); + const auto unAabb = GetUntransformedBoundingBox(); float minDist = FLT_MAX; - zeus::CAABox::EBoxFaceId minFace = zeus::CAABox::EBoxFaceId::YMin; + auto minFace = zeus::CAABox::EBoxFaceId::YMin; for (int i = 0; i < 6; ++i) { - auto tri = unAabb.getTri(zeus::CAABox::EBoxFaceId(i), 0); - float dist = zeus::CPlane(tri.x10_verts[0], tri.x10_verts[2], tri.x10_verts[1]).pointToPlaneDist(unPoint); + const auto tri = unAabb.getTri(zeus::CAABox::EBoxFaceId(i), 0); + const float dist = zeus::CPlane(tri.x10_verts[0], tri.x10_verts[2], tri.x10_verts[1]).pointToPlaneDist(unPoint); if (dist >= 0.f && dist < minDist) { minDist = dist; minFace = zeus::CAABox::EBoxFaceId(i); } } - auto tri = unAabb.getTri(minFace, 0); + + const auto tri = unAabb.getTri(minFace, 0); return zeus::CPlane(GetTransform() * tri.x10_verts[0], GetTransform() * tri.x10_verts[2], GetTransform() * tri.x10_verts[1]); @@ -146,23 +153,28 @@ zeus::CPlane CFishCloud::FindClosestPlane(const zeus::CAABox& aabb, const zeus:: } CFishCloud::CBoid* CFishCloud::GetListAt(const zeus::CVector3f& pos) { - zeus::CAABox aabb = GetBoundingBox(); - zeus::CVector3f ints = (pos - aabb.min) * x244_ooPartitionPitch; - int idx = int(ints.x()) + int(ints.y()) * 7 + int(ints.z()) * 49; - if (idx < 0 || idx >= 343) + const zeus::CAABox aabb = GetBoundingBox(); + const zeus::CVector3f ints = (pos - aabb.min) * x244_ooPartitionPitch; + const int idx = int(ints.x()) + int(ints.y()) * 7 + int(ints.z()) * 49; + + if (idx < 0 || idx >= 343) { return nullptr; + } + return xf8_boidPartitionLists[idx]; } void CFishCloud::BuildBoidNearList(const zeus::CVector3f& pos, float radius, rstl::reserved_vector& nearList) { - float radiusSq = radius * radius; + const float radiusSq = radius * radius; CBoid* b = GetListAt(pos); - while (b && nearList.size() < 25) { + + while (b != nullptr && nearList.size() < 25) { if (b->x20_active) { - float distSq = (b->GetTranslation() - pos).magSquared(); - if (distSq != 0.f && distSq < radiusSq) + const float distSq = (b->GetTranslation() - pos).magSquared(); + if (distSq != 0.f && distSq < radiusSq) { nearList.push_back(b); + } } b = b->x1c_next; } @@ -170,45 +182,54 @@ void CFishCloud::BuildBoidNearList(const zeus::CVector3f& pos, float radius, void CFishCloud::BuildBoidNearPartitionList(const zeus::CVector3f& pos, float radius, rstl::reserved_vector& nearList) { - float radiusSq = radius * radius; - zeus::CAABox aabb = GetBoundingBox(); - float x = std::max(radius * x244_ooPartitionPitch.x(), float(x238_partitionPitch.x())); - float y = std::max(radius * x244_ooPartitionPitch.y(), float(x238_partitionPitch.y())); - float z = std::max(radius * x244_ooPartitionPitch.z(), float(x238_partitionPitch.z())); - float nx = 0.01f - x; - float ny = 0.01f - y; - float nz = 0.01f - z; + const float radiusSq = radius * radius; + const zeus::CAABox aabb = GetBoundingBox(); + const float x = std::max(radius * x244_ooPartitionPitch.x(), float(x238_partitionPitch.x())); + const float y = std::max(radius * x244_ooPartitionPitch.y(), float(x238_partitionPitch.y())); + const float z = std::max(radius * x244_ooPartitionPitch.z(), float(x238_partitionPitch.z())); + const float nx = 0.01f - x; + const float ny = 0.01f - y; + const float nz = 0.01f - z; + for (float lnx = nx; lnx < x; lnx += x238_partitionPitch.x()) { - float cx = lnx + pos.x(); - if (cx < aabb.min.x()) + const float cx = lnx + pos.x(); + if (cx < aabb.min.x()) { continue; - if (cx >= aabb.max.x()) + } + if (cx >= aabb.max.x()) { break; + } for (float lny = ny; lny < y; lny += x238_partitionPitch.y()) { - float cy = lny + pos.y(); - if (cy < aabb.min.y()) + const float cy = lny + pos.y(); + if (cy < aabb.min.y()) { continue; - if (cy >= aabb.max.y()) + } + if (cy >= aabb.max.y()) { break; + } for (float lnz = nz; lnz < z; lnz += x238_partitionPitch.z()) { - float cz = lnz + pos.z(); - if (cz < aabb.min.z()) + const float cz = lnz + pos.z(); + if (cz < aabb.min.z()) { continue; - if (cz >= aabb.max.z()) + } + if (cz >= aabb.max.z()) { break; - zeus::CVector3f ints = (zeus::CVector3f(cx, cy, cz) - aabb.min) * x244_ooPartitionPitch; - int idx = int(ints.x()) + int(ints.y()) * 7 + int(ints.z()) * 49; - if (idx < 0) + } + const zeus::CVector3f ints = (zeus::CVector3f(cx, cy, cz) - aabb.min) * x244_ooPartitionPitch; + const int idx = int(ints.x()) + int(ints.y()) * 7 + int(ints.z()) * 49; + if (idx < 0) { continue; + } if (idx < 343) { CBoid* boid = xf8_boidPartitionLists[idx]; - while (boid) { + while (boid != nullptr) { if (boid->x20_active) { - float distSq = (boid->x0_pos - pos).magSquared(); + const float distSq = (boid->x0_pos - pos).magSquared(); if (distSq != 0.f && distSq < radiusSq) { nearList.push_back(boid); - if (nearList.size() == 25) + if (nearList.size() == 25) { return; + } } } boid = boid->x1c_next; @@ -220,7 +241,7 @@ void CFishCloud::BuildBoidNearPartitionList(const zeus::CVector3f& pos, float ra } void CFishCloud::PlaceBoid(CStateManager& mgr, CBoid& boid, const zeus::CAABox& aabb) const { - auto plane = FindClosestPlane(aabb, boid.x0_pos); + const auto plane = FindClosestPlane(aabb, boid.x0_pos); boid.x0_pos -= plane.pointToPlaneDist(boid.x0_pos) * plane.normal() + 0.0001f * plane.normal(); boid.xc_vel.y() = mgr.GetActiveRandom()->Float() - 0.5f; boid.xc_vel.x() = mgr.GetActiveRandom()->Float() - 0.5f; @@ -233,7 +254,7 @@ void CFishCloud::PlaceBoid(CStateManager& mgr, CBoid& boid, const zeus::CAABox& } } else { if (!PointInBox(aabb, boid.x0_pos)) { - auto unAabb = GetUntransformedBoundingBox(); + const auto unAabb = GetUntransformedBoundingBox(); boid.x0_pos.z() = mgr.GetActiveRandom()->Float() * (unAabb.max.z() - unAabb.min.z()) + unAabb.min.z(); boid.x0_pos.y() = mgr.GetActiveRandom()->Float() * (unAabb.max.y() - unAabb.min.y()) + unAabb.min.y(); boid.x0_pos.x() = mgr.GetActiveRandom()->Float() * (unAabb.max.x() - unAabb.min.x()) + unAabb.min.x(); @@ -243,57 +264,75 @@ void CFishCloud::PlaceBoid(CStateManager& mgr, CBoid& boid, const zeus::CAABox& } void CFishCloud::ApplySeparation(CBoid& boid, const rstl::reserved_vector& nearList) const { - if (nearList.empty()) + if (nearList.empty()) { return; + } + float minDist = FLT_MAX; zeus::CVector3f pos; - for (CBoid* b : nearList) { - float dist = (boid.GetTranslation() - b->GetTranslation()).magSquared(); + for (const CBoid* b : nearList) { + const float dist = (boid.GetTranslation() - b->GetTranslation()).magSquared(); if (dist < minDist) { minDist = dist; pos = b->GetTranslation(); } } + ApplySeparation(boid, pos, x138_separationRadius, x144_separationMagnitude); } void CFishCloud::ApplySeparation(CBoid& boid, const zeus::CVector3f& separateFrom, float separationRadius, float separationMagnitude) const { - zeus::CVector3f delta = boid.GetTranslation() - separateFrom; - if (delta.canBeNormalized()) { - float deltaDistSq = delta.magSquared(); - float capDeltaDistSq = separationRadius * separationRadius; - if (deltaDistSq < capDeltaDistSq) - boid.xc_vel += (1.f - deltaDistSq / capDeltaDistSq) * delta.normalized() * separationMagnitude; + const zeus::CVector3f delta = boid.GetTranslation() - separateFrom; + if (!delta.canBeNormalized()) { + return; } + + const float deltaDistSq = delta.magSquared(); + const float capDeltaDistSq = separationRadius * separationRadius; + if (deltaDistSq >= capDeltaDistSq) { + return; + } + + boid.xc_vel += (1.f - deltaDistSq / capDeltaDistSq) * delta.normalized() * separationMagnitude; } void CFishCloud::ApplyCohesion(CBoid& boid, const rstl::reserved_vector& nearList) const { - if (nearList.empty()) + if (nearList.empty()) { return; + } + zeus::CVector3f avg; - for (CBoid* b : nearList) + for (const CBoid* b : nearList) { avg += b->GetTranslation(); + } + avg = avg / float(nearList.size()); ApplyCohesion(boid, avg, x138_separationRadius, x13c_cohesionMagnitude); } void CFishCloud::ApplyCohesion(CBoid& boid, const zeus::CVector3f& cohesionFrom, float cohesionRadius, float cohesionMagnitude) const { - zeus::CVector3f delta = cohesionFrom - boid.GetTranslation(); - if (delta.canBeNormalized()) { - float distSq = delta.magSquared(); - float capDistSq = cohesionRadius * cohesionRadius; - boid.xc_vel += ((distSq > capDistSq) ? 1.f : distSq / capDistSq) * delta.normalized() * cohesionMagnitude; + const zeus::CVector3f delta = cohesionFrom - boid.GetTranslation(); + if (!delta.canBeNormalized()) { + return; } + + const float distSq = delta.magSquared(); + const float capDistSq = cohesionRadius * cohesionRadius; + boid.xc_vel += ((distSq > capDistSq) ? 1.f : distSq / capDistSq) * delta.normalized() * cohesionMagnitude; } void CFishCloud::ApplyAlignment(CBoid& boid, const rstl::reserved_vector& nearList) const { - if (nearList.empty()) + if (nearList.empty()) { return; + } + zeus::CVector3f avg; - for (CBoid* b : nearList) + for (const CBoid* b : nearList) { avg += b->xc_vel; + } + avg = avg / float(nearList.size()); boid.xc_vel += zeus::CVector3f::getAngleDiff(boid.xc_vel, avg) / M_PIF * (avg * x140_alignmentWeight); @@ -301,12 +340,14 @@ void CFishCloud::ApplyAlignment(CBoid& boid, const rstl::reserved_vector capDistSq) ? 0.f : (1.f - distSq / capDistSq)) * delta.normalized() * attractionMagnitude; + const zeus::CVector3f delta = attractTo - boid.GetTranslation(); + if (!delta.canBeNormalized()) { + return; } + + const float distSq = delta.magSquared(); + const float capDistSq = attractionRadius * attractionRadius; + boid.xc_vel += ((distSq > capDistSq) ? 0.f : (1.f - distSq / capDistSq)) * delta.normalized() * attractionMagnitude; } void CFishCloud::ApplyRepulsion(CBoid& boid, const zeus::CVector3f& attractTo, @@ -316,74 +357,93 @@ void CFishCloud::ApplyRepulsion(CBoid& boid, const zeus::CVector3f& attractTo, void CFishCloud::ApplySwirl(CBoid& boid, const zeus::CVector3f& swirlPoint, bool clockwise, float magnitude, float radius) const { - zeus::CVector3f delta = boid.x0_pos - swirlPoint; - float deltaMag = delta.magnitude(); + const zeus::CVector3f delta = boid.x0_pos - swirlPoint; + const float deltaMag = delta.magnitude(); + zeus::CVector3f alignVec; - if (clockwise) + if (clockwise) { alignVec = delta.normalized().cross(zeus::skUp); - else + } else { alignVec = zeus::skUp.cross(delta / deltaMag); - float weight = deltaMag > radius ? 0.f : 1.f - deltaMag / radius; + } + + const float weight = deltaMag > radius ? 0.f : 1.f - deltaMag / radius; boid.xc_vel += zeus::CVector3f::getAngleDiff(boid.xc_vel, alignVec) / M_PIF * weight * (magnitude * alignVec); } void CFishCloud::ApplyContainment(CBoid& boid, const zeus::CAABox& aabb) const { - if (boid.xc_vel.canBeNormalized()) { - if (!PointInBox(aabb, boid.xc_vel.normalized() * x130_speed * x174_containmentRadius + boid.x0_pos)) { - ApplyAttraction(boid, aabb.center(), 100000.f, x158_containmentMagnitude); - } + if (!boid.xc_vel.canBeNormalized()) { + return; } + + if (PointInBox(aabb, boid.xc_vel.normalized() * x130_speed * x174_containmentRadius + boid.x0_pos)) { + return; + } + + ApplyAttraction(boid, aabb.center(), 100000.f, x158_containmentMagnitude); } void CFishCloud::ScatterBoid(CStateManager& mgr, CBoid& b) const { - float angle = (mgr.GetActiveRandom()->Float() - 0.5f) * M_PIF * x154_maxScatterAngle; - float cosAngle = std::cos(angle); - float sinAngle = std::sin(angle); + const float angle = (mgr.GetActiveRandom()->Float() - 0.5f) * M_PIF * x154_maxScatterAngle; + const float cosAngle = std::cos(angle); + const float sinAngle = std::sin(angle); b.xc_vel.x() += x150_scatterVel * (b.xc_vel.y() * sinAngle + b.xc_vel.x() * cosAngle); b.xc_vel.y() += x150_scatterVel * (b.xc_vel.y() * cosAngle + b.xc_vel.x() * sinAngle); } void CFishCloud::Think(float dt, CStateManager& mgr) { - if (!GetActive()) + if (!GetActive()) { return; + } + const CGameArea* area = mgr.GetWorld()->GetAreaAlways(x4_areaId); - auto occState = area->IsPostConstructed() ? area->GetOcclusionState() : CGameArea::EOcclusionState::Occluded; + const auto occState = area->IsPostConstructed() ? area->GetOcclusionState() : CGameArea::EOcclusionState::Occluded; if (occState == CGameArea::EOcclusionState::Visible) { x168_weaponRepelDamping = std::max(0.f, x168_weaponRepelDamping - x160_weaponRepelDampingSpeed * dt * 0.1f); - if (x250_26_enableWeaponRepelDamping) - x168_weaponRepelDamping = std::min(x160_weaponRepelDampingSpeed * dt + x168_weaponRepelDamping, - x148_weaponRepelMagnitude); + if (x250_26_enableWeaponRepelDamping) { + x168_weaponRepelDamping = + std::min(x160_weaponRepelDampingSpeed * dt + x168_weaponRepelDamping, x148_weaponRepelMagnitude); + } + x164_playerRepelDamping = std::max(0.f, x164_playerRepelDamping - x15c_playerRepelDampingSpeed * dt * 0.1f); - if (x250_30_enablePlayerRepelDamping) - x164_playerRepelDamping = std::min(x15c_playerRepelDampingSpeed * dt + x164_playerRepelDamping, - x14c_playerRepelMagnitude); + if (x250_30_enablePlayerRepelDamping) { + x164_playerRepelDamping = + std::min(x15c_playerRepelDampingSpeed * dt + x164_playerRepelDamping, x14c_playerRepelMagnitude); + } + x250_26_enableWeaponRepelDamping = false; x250_30_enablePlayerRepelDamping = false; ++x118_thinkCounter; + UpdateParticles(dt); UpdatePartitionList(); - zeus::CAABox aabb = GetBoundingBox(); + + const zeus::CAABox aabb = GetBoundingBox(); int idx = 0; for (auto& b : xe8_boids) { if (b.x20_active && (idx & x11c_updateMask) == (x118_thinkCounter & x11c_updateMask)) { rstl::reserved_vector nearList; - if (x250_31_updateWithoutPartitions) + if (x250_31_updateWithoutPartitions) { BuildBoidNearList(b.x0_pos, x138_separationRadius, nearList); - else + } else { BuildBoidNearPartitionList(b.x0_pos, x138_separationRadius, nearList); + } + for (int i = 0; i < 5; ++i) { switch (i) { case 1: ApplySeparation(b, nearList); break; case 2: - if (!x250_24_randomMovement || mgr.GetActiveRandom()->Float() > x12c_randomMovementTimer) + if (!x250_24_randomMovement || mgr.GetActiveRandom()->Float() > x12c_randomMovementTimer) { ApplyCohesion(b, nearList); + } break; case 3: - if (!x250_24_randomMovement || mgr.GetActiveRandom()->Float() > x12c_randomMovementTimer) + if (!x250_24_randomMovement || mgr.GetActiveRandom()->Float() > x12c_randomMovementTimer) { ApplyAlignment(b, nearList); + } break; case 4: ScatterBoid(mgr, b); @@ -391,12 +451,14 @@ void CFishCloud::Think(float dt, CStateManager& mgr) { default: break; } - if (b.xc_vel.magSquared() > 3.2f) + if (b.xc_vel.magSquared() > 3.2f) { break; + } } + if (!x250_24_randomMovement && b.xc_vel.magSquared() < 3.2f) { - for (auto& m : x108_modifierSources) { - if (TCastToPtr act = mgr.ObjectById(m.x0_source)) { + for (const auto& m : x108_modifierSources) { + if (const TCastToConstPtr act = mgr.ObjectById(m.x0_source)) { if (m.xd_isSwirl) { ApplySwirl(b, act->GetTranslation(), m.xc_isRepulsor, m.x8_priority, m.x4_radius); } else if (m.xc_isRepulsor) { @@ -416,28 +478,34 @@ void CFishCloud::Think(float dt, CStateManager& mgr) { } ++idx; } + for (auto& b : xe8_boids) { if (b.x20_active) { ApplyContainment(b, aabb); - float velMag = b.xc_vel.magnitude(); - if (!zeus::close_enough(velMag, 0.f)) + const float velMag = b.xc_vel.magnitude(); + if (!zeus::close_enough(velMag, 0.f)) { b.xc_vel = b.xc_vel / velMag; + } b.xc_vel.z() *= 0.99f; } } + if (x12c_randomMovementTimer > 0.f) { x12c_randomMovementTimer -= dt; } else { x12c_randomMovementTimer = 0.f; x250_24_randomMovement = false; } + for (auto& b : xe8_boids) { if (b.x20_active) { b.x0_pos += b.xc_vel * dt * x130_speed; - if (!PointInBox(aabb, b.x0_pos)) + if (!PointInBox(aabb, b.x0_pos)) { PlaceBoid(mgr, b, aabb); + } } } + if (x250_27_validModel) { for (auto& m : x1b0_models) { m->GetAnimationData()->SetPlaybackRate(1.f); @@ -455,8 +523,8 @@ void CFishCloud::AllocateSkinnedModels(CStateManager& mgr, CModelData::EWhichMod int idx = 0; for (auto& m : x1b0_models) { m->EnableLooping(true); - m->AdvanceAnimation( - m->GetAnimationData()->GetAnimTimeRemaining("Whole Body"sv) * 0.25f * idx, mgr, x4_areaId, true); + m->AdvanceAnimation(m->GetAnimationData()->GetAnimTimeRemaining("Whole Body"sv) * 0.25f * float(idx), mgr, + x4_areaId, true); ++idx; } x230_whichModel = which; @@ -467,10 +535,10 @@ void CFishCloud::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CSt switch (msg) { case EScriptObjectMessage::Registered: { xe8_boids.reserve(x134_numBoids); - zeus::CAABox aabb = GetUntransformedBoundingBox(); - zeus::CVector3f extent = aabb.max - aabb.min; + const zeus::CAABox aabb = GetUntransformedBoundingBox(); + const zeus::CVector3f extent = aabb.max - aabb.min; zeus::CVector3f randPoint; - for (int i = 0; i < x134_numBoids; ++i) { + for (u32 i = 0; i < x134_numBoids; ++i) { randPoint.z() = mgr.GetActiveRandom()->Float() * extent.z() + aabb.min.z(); randPoint.y() = mgr.GetActiveRandom()->Float() * extent.y() + aabb.min.y(); randPoint.x() = mgr.GetActiveRandom()->Float() * extent.x() + aabb.min.x(); @@ -481,8 +549,9 @@ void CFishCloud::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CSt 0.2f * std::pow(mgr.GetActiveRandom()->Float(), 7.f) + 0.9f); } CreatePartitionList(); - if (x250_27_validModel) + if (x250_27_validModel) { AllocateSkinnedModels(mgr, CModelData::EWhichModel::Normal); + } break; } default: @@ -501,22 +570,26 @@ void CFishCloud::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) { } void CFishCloud::AddParticlesToRenderer() const { - for (const auto& p : x1f8_particleGens) + for (const auto& p : x1f8_particleGens) { g_Renderer->AddParticleGen(*p); + } } void CFishCloud::RenderBoid(int idx, const CBoid& boid, u32& drawMask, bool thermalHot, const CModelFlags& flags) const { - u32 modelIndex = idx & 0x3; + const u32 modelIndex = idx & 0x3; CModelData& mData = *x1b0_models[modelIndex]; CSkinnedModel& model = mData.PickAnimatedModel(CModelData::EWhichModel::Normal); - if (!model.GetModelInst()->TryLockTextures()) + if (!model.GetModelInst()->TryLockTextures()) { return; - u32 thisDrawMask = 1u << modelIndex; - if (drawMask & thisDrawMask) { + } + + const u32 thisDrawMask = 1u << modelIndex; + if ((drawMask & thisDrawMask) != 0) { drawMask &= ~thisDrawMask; mData.GetAnimationData()->BuildPose(); } + model.GetModelInst()->SetAmbientColor(zeus::skWhite); CGraphics::SetModelMatrix(zeus::lookAt(boid.x0_pos, boid.x0_pos + boid.xc_vel)); if (thermalHot) { @@ -528,24 +601,31 @@ void CFishCloud::RenderBoid(int idx, const CBoid& boid, u32& drawMask, } void CFishCloud::Render(CStateManager& mgr) { - if (!GetActive()) + if (!GetActive()) { return; + } + SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(FMT_STRING("CFishCloud::Render {} {} {}"), x8_uid, xc_editorId, x10_name).c_str(), zeus::skOrange); - bool thermalHot = mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot; + + const bool thermalHot = mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot; CModelFlags flags(0, 0, 3, zeus::skWhite); - if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay) + if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay) { flags = CModelFlags(5, 0, 3, x16c_color); - else + } else { flags = CModelFlags(1, 0, 3, x16c_color); + } + AddParticlesToRenderer(); + if (x250_27_validModel) { // Ambient white int idx = 0; u32 drawMask = 0xffffffff; for (const auto& b : xe8_boids) { - if (b.x20_active) + if (b.x20_active) { RenderBoid(idx, b, drawMask, thermalHot, flags); + } ++idx; } } else { @@ -595,35 +675,41 @@ void CFishCloud::KillBoid(CBoid& b) const { void CFishCloud::Touch(CActor& other, CStateManager& mgr) { CActor::Touch(other, mgr); - if (TCastToPtr weap = other) { + + if (const TCastToConstPtr weap = other) { if (!x250_26_enableWeaponRepelDamping && x250_29_repelFromThreats) { int idx = 0; for (auto& b : xe8_boids) { - if ((idx & 0x3) == (x118_thinkCounter & 0x3)) + if ((idx & 0x3) == (x118_thinkCounter & 0x3)) { ApplyRepulsion(b, weap->GetTranslation(), 8.f, x148_weaponRepelMagnitude - x168_weaponRepelDamping); + } ++idx; } } + x250_26_enableWeaponRepelDamping = true; + if (x250_28_killable) { - if (auto tb = weap->GetTouchBounds()) { + if (const auto tb = weap->GetTouchBounds()) { for (auto& b : xe8_boids) { - if (b.x20_active && - tb->intersects(zeus::CAABox(weap->GetTranslation() - x170_weaponKillRadius, - weap->GetTranslation() + x170_weaponKillRadius))) + if (b.x20_active && tb->intersects(zeus::CAABox(weap->GetTranslation() - x170_weaponKillRadius, + weap->GetTranslation() + x170_weaponKillRadius))) { KillBoid(b); + } } } } } + if (x250_29_repelFromThreats) { - if (TCastToPtr player = other) { - zeus::CVector3f playerPos = player->GetTranslation(); + if (const TCastToConstPtr player = other) { + const zeus::CVector3f playerPos = player->GetTranslation(); for (auto& b : xe8_boids) { zeus::CVector3f adjPlayerPos = playerPos; - float zDelta = b.x0_pos.z() - adjPlayerPos.z(); - if (zDelta > 0.f && zDelta < 2.3f) + const float zDelta = b.x0_pos.z() - adjPlayerPos.z(); + if (zDelta > 0.f && zDelta < 2.3f) { adjPlayerPos.z() = float(b.x0_pos.z()); + } adjPlayerPos.x() += mgr.GetActiveRandom()->Float() * 0.2f - 0.1f; adjPlayerPos.y() += mgr.GetActiveRandom()->Float() * 0.2f - 0.1f; ApplyRepulsion(b, adjPlayerPos, 8.f, x14c_playerRepelMagnitude - x164_playerRepelDamping); @@ -634,7 +720,7 @@ void CFishCloud::Touch(CActor& other, CStateManager& mgr) { } zeus::CAABox CFishCloud::GetUntransformedBoundingBox() const { - zeus::CVector3f extent = x120_scale * 0.75f; + const zeus::CVector3f extent = x120_scale * 0.75f; return zeus::CAABox(-extent, extent); } @@ -643,46 +729,62 @@ zeus::CAABox CFishCloud::GetBoundingBox() const { } void CFishCloud::RemoveRepulsor(TUniqueId sourceId) { - CModifierSource source(sourceId, true, false, 0.f, 0.f); - auto it = rstl::binary_find(x108_modifierSources.begin(), x108_modifierSources.end(), source); - if (it != x108_modifierSources.end()) - x108_modifierSources.erase(it); + const CModifierSource source(sourceId, true, false, 0.f, 0.f); + const auto it = rstl::binary_find(x108_modifierSources.begin(), x108_modifierSources.end(), source); + + if (it == x108_modifierSources.end()) { + return; + } + + x108_modifierSources.erase(it); } void CFishCloud::RemoveAttractor(TUniqueId sourceId) { - CModifierSource source(sourceId, false, false, 0.f, 0.f); - auto it = rstl::binary_find(x108_modifierSources.begin(), x108_modifierSources.end(), source); - if (it != x108_modifierSources.end()) - x108_modifierSources.erase(it); + const CModifierSource source(sourceId, false, false, 0.f, 0.f); + const auto it = rstl::binary_find(x108_modifierSources.begin(), x108_modifierSources.end(), source); + + if (it == x108_modifierSources.end()) { + return; + } + + x108_modifierSources.erase(it); } bool CFishCloud::AddRepulsor(TUniqueId sourceId, bool swirl, float radius, float priority) { - CModifierSource source(sourceId, true, swirl, radius, priority); - auto it = rstl::binary_find(x108_modifierSources.begin(), x108_modifierSources.end(), source); + const CModifierSource source(sourceId, true, swirl, radius, priority); + const auto it = rstl::binary_find(x108_modifierSources.begin(), x108_modifierSources.end(), source); + if (it != x108_modifierSources.end()) { it->x4_radius = radius; it->x8_priority = priority; return true; - } else if (x108_modifierSources.size() < x108_modifierSources.capacity()) { - x108_modifierSources.insert(std::lower_bound( - x108_modifierSources.begin(), x108_modifierSources.end(), source), source); + } + + if (x108_modifierSources.size() < x108_modifierSources.capacity()) { + x108_modifierSources.insert(std::lower_bound(x108_modifierSources.begin(), x108_modifierSources.end(), source), + source); return true; } + return false; } bool CFishCloud::AddAttractor(TUniqueId sourceId, bool swirl, float radius, float priority) { - CModifierSource source(sourceId, false, swirl, radius, priority); - auto it = rstl::binary_find(x108_modifierSources.begin(), x108_modifierSources.end(), source); + const CModifierSource source(sourceId, false, swirl, radius, priority); + const auto it = rstl::binary_find(x108_modifierSources.begin(), x108_modifierSources.end(), source); + if (it != x108_modifierSources.end()) { it->x4_radius = radius; it->x8_priority = priority; return true; - } else if (x108_modifierSources.size() < x108_modifierSources.capacity()) { - x108_modifierSources.insert(std::lower_bound( - x108_modifierSources.begin(), x108_modifierSources.end(), source), source); + } + + if (x108_modifierSources.size() < x108_modifierSources.capacity()) { + x108_modifierSources.insert(std::lower_bound(x108_modifierSources.begin(), x108_modifierSources.end(), source), + source); return true; } + return false; }