diff --git a/MM2Hook.vcxproj b/MM2Hook.vcxproj index efffb327..91bdfcc2 100644 --- a/MM2Hook.vcxproj +++ b/MM2Hook.vcxproj @@ -820,6 +820,7 @@ + diff --git a/MM2Hook.vcxproj.filters b/MM2Hook.vcxproj.filters index 62c6950f..934e6dc4 100644 --- a/MM2Hook.vcxproj.filters +++ b/MM2Hook.vcxproj.filters @@ -2797,6 +2797,8 @@ Source Files\modules\node + + Source Files\modules\effects Source Files\modules\vehicle diff --git a/mm2hook.ini b/mm2hook.ini index ecb5336b..75ed426a 100644 --- a/mm2hook.ini +++ b/mm2hook.ini @@ -23,6 +23,7 @@ UseModsFolder=1 ; Enable use of the mods folder for overriding the MaximumCopsLimit=3 ; Limits the number of cops pursuing the player. 3 = Default, 0 = Unlimited. Ragdolls=1 ; Enable collision with pedestrians, with ragdoll physics like Midnight Club: Street Racing. 3DDamage=1 ; Enable 3D damage on supported mods like Midnight Club: Street Racing. +3DDynamicDamage=0 ; Enable switching 3D damage type from specific to dynamic on all vehicles when 3D damage is enabled. 3DShadows=0 ; Enable 3D shadows on player vehicles, opponent vehicles, traffic, and props DynamicParkedCarDensity=1 ; Allows the traffic density slider to also control how many parked cars you see in Cruise mode. No traffic = no parked cars. OpponentsUseAllColors=0 ; Allow opponents to use more than their default four colors @@ -36,6 +37,9 @@ HornSirenThreshold=0.15 ; Threshold in seconds for how long the horn butto ExplosionSound=1 ; Enables explosion sound effect for player's emergency vehicles if they're damaged out with activated siren, it also turns off the engine for all cars if they're destroyed. ReflectionsOnBreakables=1 ; Enables reflections on breakable parts, such as mirrors. ReflectionsOnCarParts=0 ; Enables reflections on car parts such as wheels and fenders. Note that addon cars will have shiny tires with this enabled if they are not set up correctly. +ReflectionsOnDamagedParts=0 ; Enables reflections on damaged parts of the vehicle when MM1 damage is enabled. +MM1StyleDamage=1 ; Modifies the way damage textures are applied to vehicles, in a way that resembles how Midtown Madness 1 did it. +MM1StyleFlipOver=0 ; Modifies the way the car flips over itself in a way that resembles how Midtown Madness 1 did it. MM1StyleTransmission=0 ; Improves transmission physics with more realistic behavior. MM1StyleAutoReverse=0 ; Improves auto reverse system with behavior resembling Midtown Madness 1. EnableHudArrowStyles=1 ; Enables the unused alternative style hud arrows for Blitz and Crash Course game modes. @@ -44,8 +48,6 @@ EscapeDeepWater=1 ; Enables a new check which allows you to continue ResetToNearestLocation=0 ; Resets you to the nearest valid location if you fall into deep water. PhysicalEngineDamage=0 ; Damage affects engine torque when the engine spews smoke and that means the vehicle will have less acceleration and less top speed. EnableMouseBar=0 ; Enables showing up the mouse bar for all input devices, this style is similar to the steering bar in Gran Turismo games. -MM1StyleFlipOver=0 ; Modifies the way the car flips over itself in a way that resembles how Midtown Madness 1 did it. -MM1StyleDamage=1 ; Modifies the way damage textures are applied to vehicles, in a way that resembles how Midtown Madness 1 did it. UseRichPresence=1 ; Broadcast your current game mode, city, and vehicle on your Discord profile. EnableLua=1 ; Enable the Lua script system. Always disabled in multiplayer. diff --git a/src/handlers/feature_handlers/vehCarModelFeatureHandler.cpp b/src/handlers/feature_handlers/vehCarModelFeatureHandler.cpp index 12ee1e6f..6298f13d 100644 --- a/src/handlers/feature_handlers/vehCarModelFeatureHandler.cpp +++ b/src/handlers/feature_handlers/vehCarModelFeatureHandler.cpp @@ -5,6 +5,7 @@ using namespace MM2; static ConfigValue cfgMm1StyleTransmission("MM1StyleTransmission", false); static ConfigValue cfgMm1StyleDamage("MM1StyleDamage", true); static ConfigValue cfgEnable3DDamage("3DDamage", true); +static ConfigValue cfgEnable3DDynamicDamage("3DDynamicDamage", false); static ConfigValue cfgCarShadows("3DShadows", false); /* @@ -48,7 +49,7 @@ void vehCarModelFeatureHandler::ApplyImpact(vehDamageImpactInfo* a1) auto damage3d = damage->GetCar()->GetModel()->GetDamage3D(); if (damage3d) { - damage3d->Impact(a1->LocalPosition); + damage3d->Impact(a1->LocalPosition, vehCarModel::Enable3DDynamicDamage); } auto mm1Damage = damage->GetCar()->GetModel()->GetMM1Damage(); @@ -144,6 +145,7 @@ void vehCarModelFeatureHandler::Install() { ConfigValue cfgEnableSpinningWheels("EnableSpinningWheels", true); ConfigValue cfgPartReflections("ReflectionsOnCarParts", false); + ConfigValue cfgDamageReflections("ReflectionsOnDamagedParts", false); ConfigValue cfgHeadlightFlashing("EnableHeadlightFlashing", true); ConfigValue cfgNfsMwStyleTotaledCar("NFSMWStyleTotaledCar", false); ConfigValue cfgBreakableRenderTweak("BreakableRenderTweak", false); @@ -162,12 +164,14 @@ void vehCarModelFeatureHandler::Install() { vehCarModel::PartReflections = cfgPartReflections.Get(); vehCarModel::WheelReflections = vehCarModel::PartReflections; + vehCarModel::DamageReflections = cfgDamageReflections.Get(); vehCarModel::mm1StyleTransmission = cfgMm1StyleTransmission.Get(); vehCarModel::mm1StyleDamage = cfgMm1StyleDamage.Get(); vehCarModel::breakableRenderTweak = cfgBreakableRenderTweak.Get(); vehCarModel::Enable3DDamage = cfgEnable3DDamage.Get(); + vehCarModel::Enable3DDynamicDamage = cfgEnable3DDynamicDamage.Get(); vehCarModel::Enable3DShadows = cfgCarShadows.Get(); } diff --git a/src/mm2_vehicle.cpp b/src/mm2_vehicle.cpp index adfd4951..dd5c7ccd 100644 --- a/src/mm2_vehicle.cpp +++ b/src/mm2_vehicle.cpp @@ -14,6 +14,7 @@ bool vehCarModel::EnableHeadlightFlashing = true; bool vehCarModel::MWStyleTotaledCar = false; bool vehCarModel::PartReflections = false; bool vehCarModel::WheelReflections = false; +bool vehCarModel::DamageReflections = false; int vehCarModel::SirenType = 0; int vehCarModel::HeadlightType = 0; float vehCarModel::SirenCycle = 0.25f; @@ -29,6 +30,7 @@ bool vehCarModel::mm1StyleDamage = true; bool vehCarModel::breakableRenderTweak = false; bool vehCarModel::Enable3DDamage = true; +bool vehCarModel::Enable3DDynamicDamage = false; bool vehCarModel::Enable3DShadows = true; /* diff --git a/src/modules/effects/damage3d.cpp b/src/modules/effects/damage3d.cpp new file mode 100644 index 00000000..30416188 --- /dev/null +++ b/src/modules/effects/damage3d.cpp @@ -0,0 +1,274 @@ +#include "damage3d.h" + +namespace MM2 +{ + fxDamage3D::fxDamage3D() + { + m_DamageRadius = 0.25f; + } + + fxDamage3D::~fxDamage3D() + { + delete[] m_VertDeformAmount; + delete[] m_PacketMatchesVertCount; + + if (m_EnableMM1Damage) + delete[] m_VertDeformPosition; + } + + void fxDamage3D::Init(modStatic* bodyModel, modStatic* damageModel, bool mm1Damage) + { + m_BodyModel = bodyModel; + m_DamageModel = damageModel; + m_DeformModel = bodyModel->Clone(); + m_DeformDamageModel = bodyModel->Clone(); + + int bodyPacketCount = 0; + int bodyVertCount = 0; + for (int i = 0; i < bodyModel->GetPacketCount(); i++) + { + auto packet = bodyModel->GetPacket(i); + while (packet) + { + bodyVertCount += packet->GetAdjunctCount(); + bodyPacketCount++; + packet = packet->GetNext(); + } + } + + m_VertDeformAmount = new float[bodyVertCount]; + m_PacketMatchesVertCount = new bool[bodyPacketCount]; + + int currentPacket = 0; + for (int i = 0; i < bodyModel->GetPacketCount(); i++) + { + if (i >= damageModel->GetPacketCount()) break; + + auto bodyPacket = bodyModel->GetPacket(i); + auto damagePacket = damageModel->GetPacket(i); + + while (bodyPacket && damagePacket) + { + m_PacketMatchesVertCount[currentPacket] = (bodyPacket->GetAdjunctCount() == damagePacket->GetAdjunctCount()); + bodyPacket = bodyPacket->GetNext(); + damagePacket = damagePacket->GetNext(); + currentPacket++; + } + } + + m_EnableMM1Damage = mm1Damage; + + if (mm1Damage) + { + m_VertDeformPosition = new Vector3[bodyVertCount]; + + int currentVertex = 0; + for (int i = 0; i < bodyModel->GetPacketCount(); i++) + { + auto bodyPacket = bodyModel->GetPacket(i); + while (bodyPacket) + { + bodyPacket->DoLock(); + + for (unsigned int j = 0; j < bodyPacket->GetAdjunctCount(); j++) + { + bodyPacket->GetPosition(m_VertDeformPosition[currentVertex], j); + currentVertex++; + } + + bodyPacket->DoUnlock(); + bodyPacket = bodyPacket->GetNext(); + } + } + } + + SetNoDamage(); + } + + void fxDamage3D::SetNoDamage() + { + int currentVertex = 0; + + for (int i = 0; i < m_DeformModel->GetPacketCount(); i++) + { + if (i >= m_BodyModel->GetPacketCount()) break; + + auto deformDamagePacket = m_DeformDamageModel->GetPacket(i); + auto deformPacket = m_DeformModel->GetPacket(i); + auto bodyPacket = m_BodyModel->GetPacket(i); + + while (bodyPacket && deformPacket && deformDamagePacket) + { + bodyPacket->DoLock(); deformPacket->DoLock(); deformDamagePacket->DoLock(); + + for (unsigned int j = 0; j < bodyPacket->GetAdjunctCount() && j < deformPacket->GetAdjunctCount(); j++) + { + Vector3 position = Vector3::ORIGIN; + bodyPacket->GetPosition(position, j); + deformPacket->SetPosition(position, j); + deformDamagePacket->SetPosition(position, j); + m_VertDeformAmount[currentVertex] = 0.0f; + currentVertex++; + } + + if (m_EnableMM1Damage) + { + for (unsigned int j = 0; j < deformPacket->GetTriangleCount() / 3; j++) + { + int tri[3]; + bodyPacket->GetTri(tri, j); + deformPacket->SetTri(tri[0], tri[1], tri[2], j); + deformDamagePacket->SetTri(0, 0, 0, j); + } + } + + bodyPacket->DoUnlock(); deformPacket->DoUnlock(); deformDamagePacket->DoUnlock(); + + bodyPacket = bodyPacket->GetNext(); + deformPacket = deformPacket->GetNext(); + deformDamagePacket = deformDamagePacket->GetNext(); + } + } + } + + void fxDamage3D::SetFullDamage() + { + int currentVertex = 0; + + for (int i = 0; i < m_DeformModel->GetPacketCount(); i++) + { + if (i >= m_DamageModel->GetPacketCount()) break; + + auto deformDamagePacket = m_DeformDamageModel->GetPacket(i); + auto deformPacket = m_DeformModel->GetPacket(i); + auto damagePacket = m_DamageModel->GetPacket(i); + + while (damagePacket && deformPacket && deformDamagePacket) + { + damagePacket->DoLock(); deformPacket->DoLock(); deformDamagePacket->DoLock(); + + for (unsigned int j = 0; j < damagePacket->GetAdjunctCount() && j < deformPacket->GetAdjunctCount(); j++) + { + Vector3 position = Vector3::ORIGIN; + damagePacket->GetPosition(position, j); + deformPacket->SetPosition(position, j); + deformDamagePacket->SetPosition(position, j); + m_VertDeformAmount[currentVertex] = 1.0f; + currentVertex++; + } + + if (m_EnableMM1Damage) + { + for (unsigned int j = 0; j < deformDamagePacket->GetTriangleCount() / 3; j++) + { + int tri[3]; + damagePacket->GetTri(tri, j); + deformDamagePacket->SetTri(tri[0], tri[1], tri[2], j); + deformPacket->SetTri(0, 0, 0, j); + } + } + + damagePacket->DoUnlock(); deformPacket->DoUnlock(); deformDamagePacket->DoUnlock(); + + damagePacket = damagePacket->GetNext(); + deformPacket = deformPacket->GetNext(); + deformDamagePacket = deformDamagePacket->GetNext(); + } + } + } + + void fxDamage3D::Impact(Vector3& localImpactPosition, bool dynamicDamage) + { + int currentVertex = 0; + int currentVertex2 = 0; + int currentPacket = 0; + + for (int i = 0; i < m_DeformModel->GetPacketCount(); i++) + { + if (i >= m_DamageModel->GetPacketCount()) break; + + auto deformDamagePacket = m_DeformDamageModel->GetPacket(i); + auto deformPacket = m_DeformModel->GetPacket(i); + auto damagePacket = m_DamageModel->GetPacket(i); + auto bodyPacket = m_DamageModel->GetPacket(i); + + while (damagePacket && deformPacket && bodyPacket && deformDamagePacket) + { + if (m_PacketMatchesVertCount[currentPacket]) { + damagePacket->DoLock(); deformPacket->DoLock(); bodyPacket->DoLock(); deformDamagePacket->DoLock(); + + for (unsigned int j = 0; j < damagePacket->GetAdjunctCount() && j < deformPacket->GetAdjunctCount(); j++) + { + Vector3 position = Vector3::ORIGIN; + bodyPacket->GetPosition(position, j); + + float squareDistance = (localImpactPosition - position).Mag2(); + if (squareDistance < m_DamageRadius) + { + Vector3 fullDamagePosition = Vector3::ORIGIN; + Vector3 bodyModelPosition = Vector3::ORIGIN; + + damagePacket->GetPosition(fullDamagePosition, j); + bodyPacket->GetPosition(bodyModelPosition, j); + + float deformAmount = 1.0f - (squareDistance / m_DamageRadius); + if (deformAmount < m_VertDeformAmount[currentVertex]) + { + deformAmount = m_VertDeformAmount[currentVertex]; + } + if (!dynamicDamage) + m_VertDeformAmount[currentVertex] = deformAmount; + + Vector3 deformedPosition = Vector3::ORIGIN; + dynamicDamage ? + deformedPosition.Lerp(deformAmount, bodyModelPosition, fullDamagePosition - localImpactPosition * 0.1f) : + deformedPosition.Lerp(deformAmount, bodyModelPosition, fullDamagePosition); + deformPacket->SetPosition(deformedPosition, j); + deformDamagePacket->SetPosition(deformedPosition, j); + + currentVertex++; + } + } + + if (m_EnableMM1Damage) + { + for (unsigned int j = 0; j < deformDamagePacket->GetTriangleCount() / 3; j++) + { + int tri[3]; + bodyPacket->GetTri(tri, j); + + float dist0 = (m_VertDeformPosition[currentVertex2 + tri[0]] - localImpactPosition).Mag2(); + float dist1 = (m_VertDeformPosition[currentVertex2 + tri[1]] - localImpactPosition).Mag2(); + float dist2 = (m_VertDeformPosition[currentVertex2 + tri[2]] - localImpactPosition).Mag2(); + + if (dist0 < m_DamageRadius || dist1 < m_DamageRadius || dist2 < m_DamageRadius) + { + deformDamagePacket->SetTri(tri[0], tri[1], tri[2], j); + deformPacket->SetTri(0, 0, 0, j); + } + } + } + + damagePacket->DoUnlock(); deformPacket->DoUnlock(); bodyPacket->DoUnlock(); deformDamagePacket->DoUnlock(); + } + currentVertex2 += deformDamagePacket->GetAdjunctCount(); + + damagePacket = damagePacket->GetNext(); + deformPacket = deformPacket->GetNext(); + bodyPacket = bodyPacket->GetNext(); + deformDamagePacket = deformDamagePacket->GetNext(); + currentPacket++; + } + } + } + + modStatic* fxDamage3D::GetDeformModel() + { + return m_DeformModel; + } + + modStatic* fxDamage3D::GetDeformDamageModel() + { + return m_DeformDamageModel; + } +} \ No newline at end of file diff --git a/src/modules/effects/damage3d.h b/src/modules/effects/damage3d.h index f2904b2f..687a112c 100644 --- a/src/modules/effects/damage3d.h +++ b/src/modules/effects/damage3d.h @@ -17,188 +17,29 @@ namespace MM2 modStatic* m_BodyModel; modStatic* m_DamageModel; modStatic* m_DeformModel; + modStatic* m_DeformDamageModel; + Vector3* m_VertDeformPosition; float* m_VertDeformAmount; float m_DamageRadius; bool* m_PacketMatchesVertCount; + bool m_EnableMM1Damage; public: ANGEL_ALLOCATOR - fxDamage3D() - { - m_DamageRadius = 0.9f; - } + fxDamage3D(); - virtual ~fxDamage3D() - { - delete[] m_VertDeformAmount; - delete[] m_PacketMatchesVertCount; - } + virtual ~fxDamage3D(); - void Init(modStatic* bodyModel, modStatic* damageModel) - { - m_BodyModel = bodyModel; - m_DamageModel = damageModel; - m_DeformModel = bodyModel->Clone(); + void Init(modStatic* bodyModel, modStatic* damageModel, bool mm1Damage); - int bodyPacketCount = 0; - int bodyVertCount = 0; - for (int i = 0; i < bodyModel->GetPacketCount(); i++) - { - auto packet = bodyModel->GetPacket(i); - while (packet) - { - bodyVertCount += packet->GetAdjunctCount(); - bodyPacketCount++; - packet = packet->GetNext(); - } - } + void SetNoDamage(); - m_VertDeformAmount = new float[bodyVertCount]; - m_PacketMatchesVertCount = new bool[bodyPacketCount]; + void SetFullDamage(); - int currentPacket = 0; - for (int i = 0; i < bodyModel->GetPacketCount(); i++) - { - if (i >= damageModel->GetPacketCount()) break; + void Impact(Vector3& localImpactPosition, bool dynamicDamage); - auto bodyPacket = bodyModel->GetPacket(i); - auto damagePacket = damageModel->GetPacket(i); + modStatic* GetDeformModel(); - while (bodyPacket && damagePacket) - { - m_PacketMatchesVertCount[currentPacket] = (bodyPacket->GetAdjunctCount() == damagePacket->GetAdjunctCount()); - bodyPacket = bodyPacket->GetNext(); - damagePacket = damagePacket->GetNext(); - currentPacket++; - } - } - - SetNoDamage(); - } - - void SetNoDamage() - { - int currentVertex = 0; - - for (int i = 0; i < m_DeformModel->GetPacketCount(); i++) - { - if (i >= m_BodyModel->GetPacketCount()) break; - - auto deformPacket = m_DeformModel->GetPacket(i); - auto bodyPacket = m_BodyModel->GetPacket(i); - - while (bodyPacket && deformPacket) - { - bodyPacket->DoLock(); deformPacket->DoLock(); - - for (unsigned int j = 0; j < bodyPacket->GetAdjunctCount() && j < deformPacket->GetAdjunctCount(); j++) - { - Vector3 position = Vector3::ORIGIN; - bodyPacket->GetPosition(position, j); - deformPacket->SetPosition(position, j); - m_VertDeformAmount[currentVertex] = 0.0f; - currentVertex++; - } - - bodyPacket->DoUnlock(); deformPacket->DoUnlock(); - bodyPacket = bodyPacket->GetNext(); - deformPacket = deformPacket->GetNext(); - } - } - } - - void SetFullDamage() - { - int currentVertex = 0; - - for (int i = 0; i < m_DeformModel->GetPacketCount(); i++) - { - if (i >= m_DamageModel->GetPacketCount()) break; - - auto deformPacket = m_DeformModel->GetPacket(i); - auto damagePacket = m_DamageModel->GetPacket(i); - - while (damagePacket && deformPacket) - { - damagePacket->DoLock(); deformPacket->DoLock(); - - for (unsigned int j = 0; j < damagePacket->GetAdjunctCount() && j < deformPacket->GetAdjunctCount(); j++) - { - Vector3 position = Vector3::ORIGIN; - damagePacket->GetPosition(position, j); - deformPacket->SetPosition(position, j); - m_VertDeformAmount[currentVertex] = 1.0f; - currentVertex++; - } - - damagePacket->DoUnlock(); deformPacket->DoUnlock(); - damagePacket = damagePacket->GetNext(); - deformPacket = deformPacket->GetNext(); - } - } - } - - void Impact(Vector3 localImpactPosition) - { - int currentVertex = 0; - int currentPacket = 0; - - for (int i = 0; i < m_DeformModel->GetPacketCount(); i++) - { - if (i >= m_DamageModel->GetPacketCount()) break; - - auto deformPacket = m_DeformModel->GetPacket(i); - auto damagePacket = m_DamageModel->GetPacket(i); - auto bodyPacket = m_DamageModel->GetPacket(i); - - while (damagePacket && deformPacket && bodyPacket) - { - if (m_PacketMatchesVertCount[currentPacket]) { - damagePacket->DoLock(); deformPacket->DoLock(); bodyPacket->DoLock(); - - for (unsigned int j = 0; j < damagePacket->GetAdjunctCount() && j < deformPacket->GetAdjunctCount(); j++) - { - Vector3 position = Vector3::ORIGIN; - bodyPacket->GetPosition(position, j); - - float squareDistance = (localImpactPosition - position).Mag2(); - if (squareDistance <= m_DamageRadius) - { - Vector3 fullDamagePosition = Vector3::ORIGIN; - Vector3 bodyModelPosition = Vector3::ORIGIN; - - damagePacket->GetPosition(fullDamagePosition, j); - bodyPacket->GetPosition(bodyModelPosition, j); - - float deformAmount = 1.0f - (squareDistance / m_DamageRadius); - if (deformAmount < m_VertDeformAmount[currentVertex]) - { - deformAmount = m_VertDeformAmount[currentVertex]; - } - m_VertDeformAmount[currentVertex] = deformAmount; - - Vector3 deformedPosition = Vector3::ORIGIN; - deformedPosition.Lerp(deformAmount, bodyModelPosition, fullDamagePosition); - deformPacket->SetPosition(deformedPosition, j); - - currentVertex++; - } - } - - damagePacket->DoUnlock(); deformPacket->DoUnlock(); bodyPacket->DoUnlock(); - } - - damagePacket = damagePacket->GetNext(); - deformPacket = deformPacket->GetNext(); - bodyPacket = bodyPacket->GetNext(); - currentPacket++; - } - } - } - - modStatic* GetDeformModel() - { - return m_DeformModel; - } + modStatic* GetDeformDamageModel(); }; } \ No newline at end of file diff --git a/src/modules/vehicle/carmodel.cpp b/src/modules/vehicle/carmodel.cpp index 58bc72e8..6cf6fd48 100644 --- a/src/modules/vehicle/carmodel.cpp +++ b/src/modules/vehicle/carmodel.cpp @@ -598,25 +598,6 @@ namespace MM2 } } } - - //init damage3d - if (this->damage3D != nullptr) - { - // delete old damage3D - delete this->damage3D; - this->damage3D = nullptr; - } - - if (this->GetGeomIndex() != 0 && vehCarModel::Enable3DDamage) - { - auto bodyEntry = this->GetGeomBase(0); - auto bodyDamageEntry = this->GetGeomBase(BODYDAMAGE_GEOM_ID); - if (bodyEntry->GetHighLOD() != nullptr && bodyDamageEntry->GetHighLOD() != nullptr) - { - this->damage3D = new fxDamage3D(); - damage3D->Init(bodyEntry->GetHighLOD(), bodyDamageEntry->GetHighLOD()); - } - } } else { @@ -639,6 +620,28 @@ namespace MM2 } } + if (vehCarModel::Enable3DDamage) + { + //init damage3d + if (this->damage3D != nullptr) + { + // delete old damage3D + delete this->damage3D; + this->damage3D = nullptr; + } + + if (this->GetGeomIndex() != 0) + { + auto bodyEntry = this->GetGeomBase(0); + auto bodyDamageEntry = this->GetGeomBase(BODYDAMAGE_GEOM_ID); + if (bodyEntry->GetHighLOD() != nullptr) + { + this->damage3D = new fxDamage3D(); + damage3D->Init(bodyEntry->GetHighLOD(), bodyDamageEntry->GetHighLOD() != nullptr ? bodyDamageEntry->GetHighLOD() : bodyEntry->GetHighLOD(), vehCarModel::mm1StyleDamage); + } + } + } + //optimize this instance if (hasGeometry) lvlInstance::Optimize(this->variant); @@ -809,13 +812,35 @@ namespace MM2 //draw the body modStatic* bodyGeom = this->GetGeom(lod, 0); - if (!mm1StyleDamage) + if (Enable3DDamage) { - bodyGeom = (damage3D != nullptr && lod >= 2) ? damage3D->GetDeformModel() : this->GetGeom(lod, 0); - if (bodyGeom != nullptr) - bodyGeom->Draw(shaders); + if (damage3D != nullptr) + { + bodyGeom = lod >= 2 ? damage3D->GetDeformModel() : this->GetGeom(lod, 0); + if (bodyGeom != nullptr) + bodyGeom->Draw(shaders); + + if (mm1StyleDamage) + { + modStatic* bodyDamage = lod >= 2 ? damage3D->GetDeformDamageModel() : this->GetGeom(lod, 0); + if (bodyDamage != nullptr) + bodyDamage->Draw(lod >= 2 && mm1Damage != nullptr ? mm1Damage->GetDamageShaders() : shaders); + + if (DamageReflections) + { + float reflectionIntensity; + auto reflectionMap = lvlLevel::GetSingleton()->GetEnvMap(this->GetRoomId(), this->GetPosition(), reflectionIntensity); + if (lod == 3 && reflectionMap != nullptr && bodyDamage != nullptr) + { + modShader::BeginEnvMap(reflectionMap, *this->carSim->GetWorldMatrix()); + bodyDamage->DrawEnvMapped(shaders, reflectionMap, reflectionIntensity); + modShader::EndEnvMap(); + } + } + } + } } - else + else if (mm1StyleDamage) { if (mm1Damage != nullptr) { @@ -826,8 +851,25 @@ namespace MM2 modStatic* bodyDamage = lod >= 2 ? mm1Damage->GetDamageModel() : this->GetGeom(lod, 0); if (bodyDamage != nullptr) bodyDamage->Draw(lod >= 2 ? mm1Damage->GetDamageShaders() : shaders); + + if (DamageReflections) + { + float reflectionIntensity; + auto reflectionMap = lvlLevel::GetSingleton()->GetEnvMap(this->GetRoomId(), this->GetPosition(), reflectionIntensity); + if (lod == 3 && reflectionMap != nullptr && bodyDamage != nullptr) + { + modShader::BeginEnvMap(reflectionMap, *this->carSim->GetWorldMatrix()); + bodyDamage->DrawEnvMapped(shaders, reflectionMap, reflectionIntensity); + modShader::EndEnvMap(); + } + } } } + else + { + if (bodyGeom != nullptr) + bodyGeom->Draw(shaders); + } //draw BREAK objects below the body if (!breakableRenderTweak) diff --git a/src/modules/vehicle/carmodel.h b/src/modules/vehicle/carmodel.h index 89194d02..42768d11 100644 --- a/src/modules/vehicle/carmodel.h +++ b/src/modules/vehicle/carmodel.h @@ -126,6 +126,7 @@ namespace MM2 static float HeadlightFlashingSpeed; static bool PartReflections; static bool WheelReflections; + static bool DamageReflections; static bool mm1StyleTransmission; static bool mm1StyleDamage; static bool breakableRenderTweak; @@ -139,6 +140,7 @@ namespace MM2 //3d damage feature static bool Enable3DDamage; + static bool Enable3DDynamicDamage; private: bool enabledElectrics[4]; //0/1 are back, 2/3 are front vehCar* car;