diff --git a/src/graphics/engine/particle.cpp b/src/graphics/engine/particle.cpp index 5aaf45fa..9297a6cd 100644 --- a/src/graphics/engine/particle.cpp +++ b/src/graphics/engine/particle.cpp @@ -952,9 +952,8 @@ void CParticle::FrameParticle(float rTime) { CObject* object = SearchObjectGun(m_particle[i].goal, m_particle[i].pos, m_particle[i].type, m_particle[i].objFather); m_particle[i].goal = m_particle[i].pos; - if (object != nullptr) + if (object != nullptr && object->Implements(ObjectInterfaceType::Damageable)) { - assert(object->Implements(ObjectInterfaceType::Damageable)); dynamic_cast(object)->DamageObject(DamageType::Phazer, 0.002f); } @@ -1107,7 +1106,7 @@ void CParticle::FrameParticle(float rTime) continue; } - if (m_particle[i].testTime >= 0.1f) + if (m_particle[i].testTime >= 0.05f) { m_particle[i].testTime = 0.0f; @@ -1156,8 +1155,10 @@ void CParticle::FrameParticle(float rTime) m_particle[i].goal = m_particle[i].pos; if (object != nullptr) { - assert(object->Implements(ObjectInterfaceType::Damageable)); - dynamic_cast(object)->DamageObject(DamageType::Fire, 0.002f); + if (object->Implements(ObjectInterfaceType::Damageable)) + { + dynamic_cast(object)->DamageObject(DamageType::Fire, 0.001f); + } m_exploGunCounter++; @@ -1215,7 +1216,7 @@ void CParticle::FrameParticle(float rTime) continue; } - if (m_particle[i].testTime >= 0.2f) + if (m_particle[i].testTime >= 0.1f) { m_particle[i].testTime = 0.0f; CObject* object = SearchObjectGun(m_particle[i].goal, m_particle[i].pos, m_particle[i].type, m_particle[i].objFather); @@ -1238,8 +1239,10 @@ void CParticle::FrameParticle(float rTime) if (object->GetType() != OBJECT_HUMAN) Play(SOUND_TOUCH, m_particle[i].pos, 1.0f); - assert(object->Implements(ObjectInterfaceType::Damageable)); - dynamic_cast(object)->DamageObject(DamageType::Organic, 0.2f); // starts explosion + if (object->Implements(ObjectInterfaceType::Damageable)) + { + dynamic_cast(object)->DamageObject(DamageType::Organic, 0.1f); // starts explosion + } } } } @@ -1261,7 +1264,7 @@ void CParticle::FrameParticle(float rTime) continue; } - if (m_particle[i].testTime >= 0.2f) + if (m_particle[i].testTime >= 0.1f) { m_particle[i].testTime = 0.0f; CObject* object = SearchObjectGun(m_particle[i].goal, m_particle[i].pos, m_particle[i].type, m_particle[i].objFather); @@ -1281,8 +1284,10 @@ void CParticle::FrameParticle(float rTime) } else { - assert(object->Implements(ObjectInterfaceType::Damageable)); - dynamic_cast(object)->DamageObject(DamageType::Fire); // starts explosion + if (object->Implements(ObjectInterfaceType::Damageable)) + { + dynamic_cast(object)->DamageObject(DamageType::Fire); // starts explosion + } } } } @@ -1301,7 +1306,7 @@ void CParticle::FrameParticle(float rTime) continue; } - if (m_particle[i].testTime >= 0.1f) + if (m_particle[i].testTime >= 0.05f) { m_particle[i].testTime = 0.0f; @@ -1338,8 +1343,10 @@ void CParticle::FrameParticle(float rTime) m_particle[i].goal = m_particle[i].pos; if (object != nullptr) { - assert(object->Implements(ObjectInterfaceType::Damageable)); - dynamic_cast(object)->DamageObject(DamageType::Organic, 0.002f); + if (object->Implements(ObjectInterfaceType::Damageable)) + { + dynamic_cast(object)->DamageObject(DamageType::Organic, 0.0005f); + } m_exploGunCounter ++; @@ -3502,6 +3509,7 @@ CObject* CParticle::SearchObjectGun(Math::Vector old, Math::Vector pos, box2.z += min; CObject* best = nullptr; + float best_dist = std::numeric_limits::infinity(); bool shield = false; for (CObject* obj : CObjectManager::GetInstancePointer()->GetAllObjects()) { @@ -3535,7 +3543,7 @@ CObject* CParticle::SearchObjectGun(Math::Vector old, Math::Vector pos, { continue; } - if (!obj->Implements(ObjectInterfaceType::Damageable)) continue; + if (!obj->Implements(ObjectInterfaceType::Damageable) && !obj->IsBulletWall()) continue; Math::Vector oPos = obj->GetPosition(); @@ -3563,8 +3571,12 @@ CObject* CParticle::SearchObjectGun(Math::Vector old, Math::Vector pos, // Test the center of the object, which is necessary for objects // that have no sphere in the center (station). float dist = Math::Distance(oPos, pos)-4.0f; - if (dist < min) + float obj_dist = Math::Distance(old, oPos); + if (dist < min && obj_dist < best_dist) + { best = obj; + best_dist = obj_dist; + } for (const auto& crashSphere : obj->GetAllCrashSpheres()) { @@ -3577,8 +3589,12 @@ CObject* CParticle::SearchObjectGun(Math::Vector old, Math::Vector pos, Math::Vector p = Math::Projection(old, pos, oPos); float ddist = Math::Distance(p, oPos)-oRadius; - if (ddist < min) + float obj_dist = Math::Distance(old, oPos); + if (ddist < min && obj_dist < best_dist) + { best = obj; + best_dist = obj_dist; + } } } diff --git a/src/object/object.h b/src/object/object.h index 960d753e..4fcfe686 100644 --- a/src/object/object.h +++ b/src/object/object.h @@ -206,6 +206,11 @@ public: //! Is this object detectable (not dead and not underground)? virtual bool GetDetectable() { return true; } + //! Returns true if this object can collide with bullets even though it's not damageable itself + //! This is useful to make Barriers protect from bullets + //! \todo It will work like this for now but later I'd like to refactor this to something more manageable ~krzys_h + virtual bool IsBulletWall() { return false; } + protected: //! Transform crash sphere by object's world matrix virtual void TransformCrashSphere(Math::Sphere& crashSphere) = 0; diff --git a/src/object/old_object.cpp b/src/object/old_object.cpp index c7200c8e..5c67ee44 100644 --- a/src/object/old_object.cpp +++ b/src/object/old_object.cpp @@ -940,6 +940,9 @@ void COldObject::Write(CLevelParserLine* line) if ( GetCameraLock() ) line->AddParam("cameraLock", MakeUnique(GetCameraLock())); + if ( IsBulletWall() ) + line->AddParam("bulletWall", MakeUnique(IsBulletWall())); + if ( GetEnergyLevel() != 0.0f ) line->AddParam("energy", MakeUnique(GetEnergyLevel())); @@ -1035,6 +1038,8 @@ void COldObject::Read(CLevelParserLine* line) if (line->GetParam("pyro")->IsDefined()) m_engine->GetPyroManager()->Create(line->GetParam("pyro")->AsPyroType(), this); + SetBulletWall(line->GetParam("bulletWall")->AsBool(false)); + SetProxyActivate(line->GetParam("proxyActivate")->AsBool(false)); SetProxyDistance(line->GetParam("proxyDistance")->AsFloat(15.0f)*g_unit); SetCollisions(line->GetParam("clip")->AsBool(true)); @@ -3188,3 +3193,13 @@ bool COldObject::IsSelectableByDefault(ObjectType type) } return true; } + +void COldObject::SetBulletWall(bool bulletWall) +{ + m_bulletWall = bulletWall; +} + +bool COldObject::IsBulletWall() +{ + return m_bulletWall; +} diff --git a/src/object/old_object.h b/src/object/old_object.h index ff96fcfe..b000ac62 100644 --- a/src/object/old_object.h +++ b/src/object/old_object.h @@ -288,6 +288,9 @@ public: float GetLightningHitProbability() override; + void SetBulletWall(bool bulletWall); + bool IsBulletWall() override; + protected: bool EventFrame(const Event &event); void VirusFrame(float rTime); @@ -376,4 +379,6 @@ protected: bool m_traceDown; TraceColor m_traceColor; float m_traceWidth; + + bool m_bulletWall = false; };