diff --git a/src/graphics/engine/lightning.cpp b/src/graphics/engine/lightning.cpp index 0bada54d..c27e44d0 100644 --- a/src/graphics/engine/lightning.cpp +++ b/src/graphics/engine/lightning.cpp @@ -37,6 +37,7 @@ #include "object/auto/autopowercaptor.h" +#include "object/interface/destroyable_object.h" #include "object/interface/transportable_object.h" @@ -103,6 +104,7 @@ bool CLightning::EventFrame(const Event &event) m_pos = obj->GetPosition(); m_terrain->AdjustToFloor(m_pos, true); + // TODO: CLightningConductorObject ObjectType type = obj->GetType(); if (type == OBJECT_BASE) { @@ -118,7 +120,8 @@ bool CLightning::EventFrame(const Event &event) } else { - obj->ExplodeObject(ExplosionType::Bang, 1.0f); + assert(obj->Implements(ObjectInterfaceType::Destroyable)); + dynamic_cast(obj)->DamageObject(DamageType::Lightning); } } @@ -329,64 +332,12 @@ CObject* CLightning::SearchObject(Math::Vector pos) { paraObj.push_back(obj); paraObjPos.push_back(obj->GetPosition()); + continue; } - float detect = 0.0f; - if ( type == OBJECT_BASE || - type == OBJECT_DERRICK || - type == OBJECT_FACTORY || - type == OBJECT_REPAIR || - type == OBJECT_DESTROYER|| - type == OBJECT_STATION || - type == OBJECT_CONVERT || - type == OBJECT_TOWER || - type == OBJECT_RESEARCH || - type == OBJECT_RADAR || - type == OBJECT_INFO || - type == OBJECT_ENERGY || - type == OBJECT_LABO || - type == OBJECT_NUCLEAR || - type == OBJECT_PARA || - type == OBJECT_SAFE || - type == OBJECT_HUSTON ) - { - detect = m_magnetic; - } - if ( type == OBJECT_METAL || - type == OBJECT_POWER || - type == OBJECT_ATOMIC ) - { - detect = m_magnetic*0.3f; - } - if ( type == OBJECT_MOBILEfa || - type == OBJECT_MOBILEta || - type == OBJECT_MOBILEwa || - type == OBJECT_MOBILEia || - type == OBJECT_MOBILEfc || - type == OBJECT_MOBILEtc || - type == OBJECT_MOBILEwc || - type == OBJECT_MOBILEic || - type == OBJECT_MOBILEfi || - type == OBJECT_MOBILEti || - type == OBJECT_MOBILEwi || - type == OBJECT_MOBILEii || - type == OBJECT_MOBILEfs || - type == OBJECT_MOBILEts || - type == OBJECT_MOBILEws || - type == OBJECT_MOBILEis || - type == OBJECT_MOBILErt || - type == OBJECT_MOBILErc || - type == OBJECT_MOBILErr || - type == OBJECT_MOBILErs || - type == OBJECT_MOBILEsa || - type == OBJECT_MOBILEft || - type == OBJECT_MOBILEtt || - type == OBJECT_MOBILEwt || - type == OBJECT_MOBILEit || - type == OBJECT_MOBILEdr ) - { - detect = m_magnetic*0.5f; - } + if (!obj->Implements(ObjectInterfaceType::Destroyable)) continue; + + float detect = m_magnetic * dynamic_cast(obj)->GetLightningHitProbability(); if (detect == 0.0f) continue; Math::Vector oPos = obj->GetPosition(); diff --git a/src/graphics/engine/particle.cpp b/src/graphics/engine/particle.cpp index 8cbc6102..70dd1fa5 100644 --- a/src/graphics/engine/particle.cpp +++ b/src/graphics/engine/particle.cpp @@ -38,6 +38,8 @@ #include "object/object.h" #include "object/object_manager.h" +#include "object/interface/damageable_object.h" + #include @@ -64,12 +66,6 @@ bool IsAlien(ObjectType type) type == OBJECT_MOBILEtg ); } -//! Check if an object can be destroyed, but is not an enemy -bool IsSoft(CObject* object) -{ - return object->Implements(ObjectInterfaceType::Destroyable) && !IsAlien(object->GetType()); -} - CParticle::CParticle(CEngine* engine) : m_engine(engine) { @@ -953,10 +949,8 @@ void CParticle::FrameParticle(float rTime) m_particle[i].goal = m_particle[i].pos; if (object != nullptr) { - if (object->GetType() == OBJECT_MOTHER) - object->ExplodeObject(ExplosionType::Bang, 0.1f); - else - object->ExplodeObject(ExplosionType::Bang, 0.0f); + assert(object->Implements(ObjectInterfaceType::Damageable)); + dynamic_cast(object)->DamageObject(DamageType::Phazer, 0.0f); } m_particle[i].zoom = 1.0f-(m_particle[i].time-m_particle[i].duration); @@ -1157,7 +1151,8 @@ void CParticle::FrameParticle(float rTime) m_particle[i].goal = m_particle[i].pos; if (object != nullptr) { - object->ExplodeObject(ExplosionType::Burn, 0.0f); + assert(object->Implements(ObjectInterfaceType::Damageable)); + dynamic_cast(object)->DamageObject(DamageType::Fire, 0.0f); m_exploGunCounter++; @@ -1238,7 +1233,8 @@ void CParticle::FrameParticle(float rTime) if (object->GetType() != OBJECT_HUMAN) Play(SOUND_TOUCH, m_particle[i].pos, 1.0f); - object->ExplodeObject(ExplosionType::Bang, 0.0f); // starts explosion + assert(object->Implements(ObjectInterfaceType::Damageable)); + dynamic_cast(object)->DamageObject(DamageType::Organic, 0.0f); // starts explosion } } } @@ -1280,7 +1276,8 @@ void CParticle::FrameParticle(float rTime) } else { - object->ExplodeObject(ExplosionType::Burn, 1.0f); // starts explosion + assert(object->Implements(ObjectInterfaceType::Damageable)); + dynamic_cast(object)->DamageObject(DamageType::Fire); // starts explosion } } } @@ -1336,7 +1333,8 @@ void CParticle::FrameParticle(float rTime) m_particle[i].goal = m_particle[i].pos; if (object != nullptr) { - object->ExplodeObject(ExplosionType::Bang, 0.0f); + assert(object->Implements(ObjectInterfaceType::Damageable)); + dynamic_cast(object)->DamageObject(DamageType::Organic, 0.0f); m_exploGunCounter ++; @@ -2411,7 +2409,10 @@ void CParticle::FrameParticle(float rTime) CObject* object = SearchObjectRay(m_particle[i].pos, m_particle[i].goal, m_particle[i].type, m_particle[i].objFather); if (object != nullptr) - object->ExplodeObject(ExplosionType::Bang, 0.0f); + { + assert(object->Implements(ObjectInterfaceType::Damageable)); + dynamic_cast(object)->DamageObject(DamageType::Tower); + } } ts.x = 0.00f; @@ -3589,29 +3590,27 @@ CObject* CParticle::SearchObjectGun(Math::Vector old, Math::Vector pos, if (type == PARTIGUN1) // fireball shooting? { if (oType == OBJECT_MOTHER) continue; - if (!obj->Implements(ObjectInterfaceType::Destroyable)) continue; } else if (type == PARTIGUN2) // shooting insect? { - if (!IsSoft(obj)) continue; + if (IsAlien(obj->GetType())) continue; } else if (type == PARTIGUN3) // suiciding spider? { - if (!IsSoft(obj)) continue; + if (!IsAlien(obj->GetType())) continue; } else if (type == PARTIGUN4) // orgaball shooting? { if (oType == OBJECT_MOTHER) continue; - if (!obj->Implements(ObjectInterfaceType::Destroyable)) continue; } else if (type == PARTITRACK11) // phazer shooting? { - if (!obj->Implements(ObjectInterfaceType::Destroyable)) continue; } else { continue; } + if (!obj->Implements(ObjectInterfaceType::Damageable)) continue; Math::Vector oPos = obj->GetPosition(); diff --git a/src/graphics/engine/pyro.cpp b/src/graphics/engine/pyro.cpp index 77fedc58..4bdc1bcc 100644 --- a/src/graphics/engine/pyro.cpp +++ b/src/graphics/engine/pyro.cpp @@ -2198,55 +2198,7 @@ CObject* CPyro::FallSearchBeeExplo() for (CObject* obj : CObjectManager::GetInstancePointer()->GetAllObjects()) { - ObjectType oType = obj->GetType(); - if ( oType != OBJECT_HUMAN && - oType != OBJECT_MOBILEfa && - oType != OBJECT_MOBILEta && - oType != OBJECT_MOBILEwa && - oType != OBJECT_MOBILEia && - oType != OBJECT_MOBILEfc && - oType != OBJECT_MOBILEtc && - oType != OBJECT_MOBILEwc && - oType != OBJECT_MOBILEic && - oType != OBJECT_MOBILEfi && - oType != OBJECT_MOBILEti && - oType != OBJECT_MOBILEwi && - oType != OBJECT_MOBILEii && - oType != OBJECT_MOBILEfs && - oType != OBJECT_MOBILEts && - oType != OBJECT_MOBILEws && - oType != OBJECT_MOBILEis && - oType != OBJECT_MOBILErt && - oType != OBJECT_MOBILErc && - oType != OBJECT_MOBILErr && - oType != OBJECT_MOBILErs && - oType != OBJECT_MOBILEsa && - oType != OBJECT_MOBILEtg && - oType != OBJECT_MOBILEft && - oType != OBJECT_MOBILEtt && - oType != OBJECT_MOBILEwt && - oType != OBJECT_MOBILEit && - oType != OBJECT_MOBILEdr && - oType != OBJECT_BASE && - oType != OBJECT_DERRICK && - oType != OBJECT_STATION && - oType != OBJECT_FACTORY && - oType != OBJECT_REPAIR && - oType != OBJECT_DESTROYER&& - oType != OBJECT_CONVERT && - oType != OBJECT_TOWER && - oType != OBJECT_RESEARCH && - oType != OBJECT_RADAR && - oType != OBJECT_INFO && - oType != OBJECT_ENERGY && - oType != OBJECT_LABO && - oType != OBJECT_NUCLEAR && - oType != OBJECT_PARA && - oType != OBJECT_SAFE && - oType != OBJECT_HUSTON && - oType != OBJECT_METAL && - oType != OBJECT_POWER && - oType != OBJECT_ATOMIC ) continue; + if ( obj->Implements(ObjectInterfaceType::Destroyable) ) continue; if (IsObjectBeingTransported(obj)) continue; @@ -2260,7 +2212,7 @@ CObject* CPyro::FallSearchBeeExplo() return obj; } - if ( oType == OBJECT_BASE ) + if ( obj->GetType() == OBJECT_BASE ) { float distance = Math::Distance(oPos, bulletCrashSphere.sphere.pos); if (distance < 25.0f) @@ -2317,7 +2269,8 @@ void CPyro::FallProgress(float rTime) { if (floor) // reaches the ground? { - m_object->ExplodeObject(ExplosionType::Bang, 0.0f); // start explosion + assert(m_object->Implements(ObjectInterfaceType::Destroyable)); + dynamic_cast(m_object)->DestroyObject(DestructionType::Explosion); } } else @@ -2332,13 +2285,15 @@ void CPyro::FallProgress(float rTime) } else { - if (obj->ExplodeObject(ExplosionType::Bang, 1.0f)) // start explosion + assert(obj->Implements(ObjectInterfaceType::Damageable)); + if (dynamic_cast(obj)->DamageObject(DamageType::FallingObject)) { DeleteObject(true, true); // removes the ball } else { - m_object->ExplodeObject(ExplosionType::Bang, 0.0f); // start explosion + assert(m_object->Implements(ObjectInterfaceType::Destroyable)); + dynamic_cast(m_object)->DestroyObject(DestructionType::Explosion); } } } diff --git a/src/graphics/engine/pyro_type.h b/src/graphics/engine/pyro_type.h index 119cb180..5f9ca912 100644 --- a/src/graphics/engine/pyro_type.h +++ b/src/graphics/engine/pyro_type.h @@ -43,7 +43,7 @@ enum PyroType PT_SHOTT = 9, //! < hit technical object PT_SHOTH = 10, //! < hit human PT_SHOTM = 11, //! < hit queen - PT_SHOTW = 12, //! < hit under water + PT_SHOTW = 12, //! < hit under water (TODO: check if unused) PT_EGG = 13, //! < break the egg PT_BURNT = 14, //! < burning of technical object PT_BURNO = 15, //! < burning of organic object diff --git a/src/object/auto/autodestroyer.cpp b/src/object/auto/autodestroyer.cpp index 857030fd..094b647d 100644 --- a/src/object/auto/autodestroyer.cpp +++ b/src/object/auto/autodestroyer.cpp @@ -175,8 +175,8 @@ bool CAutoDestroyer::EventProcess(const Event &event) scrap = SearchPlastic(); if ( scrap != nullptr ) { - //m_engine->GetPyroManager()->Create(Gfx::PT_FRAGT, scrap); - scrap->ExplodeObject(ExplosionType::Bang, 1.0f); + assert(scrap->Implements(ObjectInterfaceType::Destroyable)); + dynamic_cast(scrap)->DestroyObject(DestructionType::Explosion); } m_bExplo = true; } @@ -283,57 +283,9 @@ CObject* CAutoDestroyer::SearchPlastic() for (CObject* obj : CObjectManager::GetInstancePointer()->GetAllObjects()) { - ObjectType type = obj->GetType(); - //if ( type != OBJECT_SCRAP4 && - // type != OBJECT_SCRAP5 ) continue; - if ( type != OBJECT_FRET && - type != OBJECT_STONE && - type != OBJECT_URANIUM && - type != OBJECT_METAL && - type != OBJECT_POWER && - type != OBJECT_ATOMIC && - type != OBJECT_TNT && - type != OBJECT_SCRAP1 && - type != OBJECT_SCRAP2 && - type != OBJECT_SCRAP3 && - type != OBJECT_SCRAP4 && - type != OBJECT_SCRAP5 && - // Robots: - type != OBJECT_HUMAN && - type != OBJECT_MOBILEfa && - type != OBJECT_MOBILEta && - type != OBJECT_MOBILEwa && - type != OBJECT_MOBILEia && - type != OBJECT_MOBILEfc && - type != OBJECT_MOBILEtc && - type != OBJECT_MOBILEwc && - type != OBJECT_MOBILEic && - type != OBJECT_MOBILEfi && - type != OBJECT_MOBILEti && - type != OBJECT_MOBILEwi && - type != OBJECT_MOBILEii && - type != OBJECT_MOBILEfs && - type != OBJECT_MOBILEts && - type != OBJECT_MOBILEws && - type != OBJECT_MOBILEis && - type != OBJECT_MOBILErt && - type != OBJECT_MOBILErc && - type != OBJECT_MOBILErr && - type != OBJECT_MOBILErs && - type != OBJECT_MOBILEsa && - type != OBJECT_MOBILEtg && - type != OBJECT_MOBILEft && - type != OBJECT_MOBILEtt && - type != OBJECT_MOBILEwt && - type != OBJECT_MOBILEit && - type != OBJECT_MOBILEdr && - type != OBJECT_MOTHER && - type != OBJECT_ANT && - type != OBJECT_SPIDER && - type != OBJECT_BEE && - type != OBJECT_WORM ) continue; - - + if (!obj->Implements(ObjectInterfaceType::Destroyable)) continue; + if (obj->GetType() == OBJECT_HUMAN || obj->GetType() == OBJECT_TECH) continue; + Math::Vector oPos = obj->GetPosition(); float dist = Math::Distance(oPos, sPos); if ( dist <= 5.0f ) return obj; diff --git a/src/object/interface/damageable_object.h b/src/object/interface/damageable_object.h new file mode 100644 index 00000000..cfc5eb2d --- /dev/null +++ b/src/object/interface/damageable_object.h @@ -0,0 +1,53 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2015, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsiteс.ch; http://colobot.info; http://github.com/colobot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ + +#pragma once + +#include "object/object_interface_type.h" + +enum class DamageType +{ + Fire = 1, //!< fire damage (AlienSpider or Shooter), burns on destruction + Organic = 2, //!< organical damage (AlienAnt or OrgaShooter), explodes on destruction + Phazer = 3, //!< damage from PhazerShooter, explodes on destruction + Tower = 4, //!< damage from DefenseTower, explodes on destruction + FallingObject = 5, //!< damaged by an falling object (OrgaMatter dropped by an AlienWasp), explodes on destruction + Explosive = 6, //!< destroyed by an explosive, explodes on destruction + Collision = 7, //!< damage after one object hits another, explodes on destruction + Lightning = 8, //!< struck by lightning, explodes on destruction + Fall = 9, //!< fall damage, explodes on destruction +}; + +/** + * \class CDamageableObject + * \brief Interface for objects that generate particles when hit + */ +class CDamageableObject +{ +public: + explicit CDamageableObject(ObjectInterfaceTypes& types) + { + types[static_cast(ObjectInterfaceType::Damageable)] = true; + } + virtual ~CDamageableObject() + {} + + //! Damage the object, with the given force. Returns true if the object has been fully destroyed (if the object is destroyable). force < 0 => destroy immediately (default), force == 0 => default damage values + virtual bool DamageObject(DamageType type, float force = -1.0f) = 0; +}; diff --git a/src/object/interface/destroyable_object.h b/src/object/interface/destroyable_object.h index 0cc863f9..81138cd4 100644 --- a/src/object/interface/destroyable_object.h +++ b/src/object/interface/destroyable_object.h @@ -19,7 +19,16 @@ #pragma once -#include "object/object_interface_type.h" +#include "object/interface/damageable_object.h" + +enum class DestructionType +{ + NoEffect = 0, //!< no effect, just disappear (only for MissionController constants, do not actually pass this to DestroyObject) + Explosion = 1, //!< explosion + ExplosionWater = 2, //!< explosion underwater + Burn = 3, //!< burning + Drowned = 4, //!< drowned (only for Me) +}; /** * \class CDestroyableObject @@ -27,13 +36,20 @@ * * NOTE: None of the objects should inherit this class directly. Instead, inherit one of the subclasses (CShieldedObject or CFragileObject) */ -class CDestroyableObject +class CDestroyableObject : public CDamageableObject { public: explicit CDestroyableObject(ObjectInterfaceTypes& types) + : CDamageableObject(types) { types[static_cast(ObjectInterfaceType::Destroyable)] = true; } virtual ~CDestroyableObject() {} + + //! Destroy the object immediately. Use this only if you are 100% sure this is what you want, because object with magnifyDamage=0 should be able to bypass all damage. It's recommended to use CDamageableObject::DamageObject() instead. + virtual void DestroyObject(DestructionType type) = 0; + + //! Returns the distance modifier for lightning, used to modify hit probability. Value in range [0..1], where 0 is never and 1 is normal probability + virtual float GetLightningHitProbability() = 0; }; diff --git a/src/object/object_interface_type.h b/src/object/object_interface_type.h index 8f935c4f..a4cdd327 100644 --- a/src/object/object_interface_type.h +++ b/src/object/object_interface_type.h @@ -47,6 +47,7 @@ enum class ObjectInterfaceType PowerContainer, //!< objects that hold power Ranged, //!< objects that have a operation range to be displayed after pressing button in the UI TraceDrawing, //!< objects that can draw wheel trace + Damageable, //!< objects that generate particles when hit Destroyable, //!< objects that can be destroyed (base for Shielded and Fragile) Fragile, //!< objects that are destroyed immediately after hit Shielded, //!< objects that can be destroyed after the shield goes down to 0 diff --git a/src/object/object_manager.cpp b/src/object/object_manager.cpp index dc30e994..23e13bf5 100644 --- a/src/object/object_manager.cpp +++ b/src/object/object_manager.cpp @@ -202,7 +202,16 @@ void CObjectManager::DestroyTeam(int team) for (CObject* object : GetAllObjects()) { if (object->GetTeam() == team) - object->ExplodeObject(ExplosionType::Bang, 1.0f); + { + if (object->Implements(ObjectInterfaceType::Destroyable)) + { + dynamic_cast(object)->DestroyObject(DestructionType::Explosion); + } + else + { + DeleteObject(object); + } + } } } diff --git a/src/object/old_object.cpp b/src/object/old_object.cpp index 382758ae..b5aac319 100644 --- a/src/object/old_object.cpp +++ b/src/object/old_object.cpp @@ -68,9 +68,6 @@ const float VIRUS_DELAY = 60.0f; // duration of virus infection -const float LOSS_SHIELD = 0.24f; // loss of the shield by shot -const float LOSS_SHIELD_H = 0.10f; // loss of the shield for humans -const float LOSS_SHIELD_M = 0.02f; // loss of the shield for the laying // Object's constructor. @@ -331,192 +328,208 @@ void COldObject::Simplify() } -// Detonates an object, when struck by a shot. -// If false is returned, the object is still screwed. -// If true is returned, the object is destroyed. - -bool COldObject::ExplodeObject(ExplosionType type, float force) +bool COldObject::DamageObject(DamageType type, float force) { - assert(Implements(ObjectInterfaceType::Destroyable)); - assert(Implements(ObjectInterfaceType::Shielded) || Implements(ObjectInterfaceType::Fragile)); + assert(Implements(ObjectInterfaceType::Damageable)); + assert(!Implements(ObjectInterfaceType::Destroyable) || Implements(ObjectInterfaceType::Shielded) || Implements(ObjectInterfaceType::Fragile)); - if ( type == ExplosionType::Burn ) + if ( m_bDead ) return false; + + if ( m_type == OBJECT_ANT || + m_type == OBJECT_WORM || + m_type == OBJECT_SPIDER || + m_type == OBJECT_BEE ) { - if ( Implements(ObjectInterfaceType::Fragile) ) // object that isn't burning? - { - type = ExplosionType::Bang; - force = 1.0f; - } + // Fragile, but can have fire effect + // TODO: IsBurnable() + force = -1.0f; + } + else if ( Implements(ObjectInterfaceType::Fragile) ) + { + if ( m_type == OBJECT_BOMB && type != DamageType::Explosive ) return false; // Mine can't be destroyed by shooting + + DestroyObject(DestructionType::Explosion); + return true; } - if ( type == ExplosionType::Bang ) + if ( type != DamageType::Phazer && m_type == OBJECT_MOTHER ) return false; // AlienQueen can be destroyed only by PhazerShooter + + if ( type == DamageType::Organic ) { // TODO: I don't understand, why does it apply damage only once every 0.5 second? if ( m_shotTime < 0.5f ) return false; m_shotTime = 0.0f; } - if ( m_type == OBJECT_HUMAN && m_bDead ) return false; - - bool deadAlready = true; float loss = 1.0f; - if ( Implements(ObjectInterfaceType::Shielded) ) + bool dead = true; + if (Implements(ObjectInterfaceType::Shielded)) { - // Calculate the power lost by the explosion. - loss = force; - if ( loss == 0.0f ) + float magnifyDamage = m_magnifyDamage * m_main->GetGlobalMagnifyDamage(); + if (force >= 0) { - if ( m_type == OBJECT_HUMAN ) + // Calculate the shield lost by the explosion + if ( force == 0.0f ) // use default? { - loss = LOSS_SHIELD_H; - } - else if ( m_type == OBJECT_MOTHER ) - { - loss = LOSS_SHIELD_M; + if ( m_type == OBJECT_HUMAN || m_type == OBJECT_MOTHER ) + { + loss = 0.1f; + } + else + { + loss = 0.24f; + } } else { - loss = LOSS_SHIELD; + loss = force; } - } - loss *= m_magnifyDamage; - loss *= m_main->GetGlobalMagnifyDamage(); + loss *= magnifyDamage; + if (loss > 1.0f) loss = 1.0f; - // Decreases the power of the shield. - float shield = GetShield(); - shield -= loss; - SetShield(shield); - - deadAlready = (shield <= 0.0f); - } - - Gfx::PyroType pyroType = Gfx::PT_NULL; - if ( !deadAlready ) // not dead yet? - { - if ( type == ExplosionType::Water ) - { - if ( m_type == OBJECT_HUMAN ) - { - pyroType = Gfx::PT_SHOTH; - } - else - { - pyroType = Gfx::PT_SHOTW; - } + // Decreases the the shield + float shield = GetShield(); + shield -= loss; + SetShield(shield); } else { - if ( m_type == OBJECT_HUMAN ) + if ( magnifyDamage != 0.0f ) { - pyroType = Gfx::PT_SHOTH; - } - else if ( m_type == OBJECT_MOTHER ) - { - pyroType = Gfx::PT_SHOTM; - } - else - { - pyroType = Gfx::PT_SHOTT; + // Dead immediately + SetShield(0.0f); } } + dead = (GetShield() <= 0.0f); } - else // completely dead? + + if (dead && Implements(ObjectInterfaceType::Destroyable)) { - if ( type == ExplosionType::Burn ) // burning? + if (type == DamageType::Fire) { - if ( m_type == OBJECT_MOTHER || - m_type == OBJECT_ANT || - m_type == OBJECT_SPIDER || - m_type == OBJECT_BEE || - m_type == OBJECT_WORM || - m_type == OBJECT_BULLET ) - { - pyroType = Gfx::PT_BURNO; - SetBurn(true); - } - else if ( m_type == OBJECT_HUMAN ) - { - pyroType = Gfx::PT_DEADG; - } - else - { - pyroType = Gfx::PT_BURNT; - SetBurn(true); - } - SetVirusMode(false); + DestroyObject(DestructionType::Burn); } - else if ( type == ExplosionType::Water ) + else { - if ( m_type == OBJECT_HUMAN ) - { - pyroType = Gfx::PT_DEADW; - } - else - { - pyroType = Gfx::PT_FRAGW; - } - } - else if ( type == ExplosionType::Bang ) // explosion? - { - if ( m_type == OBJECT_ANT || - m_type == OBJECT_SPIDER || - m_type == OBJECT_BEE || - m_type == OBJECT_WORM ) - { - pyroType = Gfx::PT_EXPLOO; - } - else if ( m_type == OBJECT_MOTHER || - m_type == OBJECT_NEST || - m_type == OBJECT_BULLET ) - { - pyroType = Gfx::PT_FRAGO; - } - else if ( m_type == OBJECT_HUMAN ) - { - pyroType = Gfx::PT_DEADG; - } - else if ( m_type == OBJECT_BASE || - m_type == OBJECT_DERRICK || - m_type == OBJECT_FACTORY || - m_type == OBJECT_STATION || - m_type == OBJECT_CONVERT || - m_type == OBJECT_REPAIR || - m_type == OBJECT_DESTROYER|| - m_type == OBJECT_TOWER || - m_type == OBJECT_NEST || - m_type == OBJECT_RESEARCH || - m_type == OBJECT_RADAR || - m_type == OBJECT_INFO || - m_type == OBJECT_ENERGY || - m_type == OBJECT_LABO || - m_type == OBJECT_NUCLEAR || - m_type == OBJECT_PARA || - m_type == OBJECT_SAFE || - m_type == OBJECT_HUSTON || - m_type == OBJECT_START || - m_type == OBJECT_END ) // building? - { - pyroType = Gfx::PT_FRAGT; - } - else if ( m_type == OBJECT_MOBILEtg ) - { - pyroType = Gfx::PT_FRAGT; - } - else - { - pyroType = Gfx::PT_EXPLOT; - } - - loss = 1.0f; + DestroyObject(DestructionType::Explosion); } + return true; } - if (pyroType != Gfx::PT_NULL) + if ( m_type == OBJECT_HUMAN ) { - m_engine->GetPyroManager()->Create(pyroType, this, loss); + m_engine->GetPyroManager()->Create(Gfx::PT_SHOTH, this, loss); + } + else if ( m_type == OBJECT_MOTHER ) + { + m_engine->GetPyroManager()->Create(Gfx::PT_SHOTM, this, loss); + } + else + { + m_engine->GetPyroManager()->Create(Gfx::PT_SHOTT, this, loss); } - if ( !deadAlready ) return false; // not dead yet + return false; +} + +void COldObject::DestroyObject(DestructionType type) +{ + assert(Implements(ObjectInterfaceType::Destroyable)); + + if(type == DestructionType::NoEffect) assert(!!"DestructionType::NoEffect should not be passed to DestroyObject()!"); + assert(type != DestructionType::Drowned || m_type == OBJECT_HUMAN); + + if ( m_bDead ) return; + + if (Implements(ObjectInterfaceType::Shielded)) + { + SetShield(0.0f); + } + + Gfx::PyroType pyroType; + if ( type == DestructionType::Explosion ) // explosion? + { + if ( m_type == OBJECT_ANT || + m_type == OBJECT_SPIDER || + m_type == OBJECT_BEE || + m_type == OBJECT_WORM ) + { + pyroType = Gfx::PT_EXPLOO; + } + else if ( m_type == OBJECT_MOTHER || + m_type == OBJECT_NEST || + m_type == OBJECT_BULLET ) + { + pyroType = Gfx::PT_FRAGO; + } + else if ( m_type == OBJECT_HUMAN ) + { + pyroType = Gfx::PT_DEADG; + } + else if ( m_type == OBJECT_BASE || + m_type == OBJECT_DERRICK || + m_type == OBJECT_FACTORY || + m_type == OBJECT_STATION || + m_type == OBJECT_CONVERT || + m_type == OBJECT_REPAIR || + m_type == OBJECT_DESTROYER|| + m_type == OBJECT_TOWER || + m_type == OBJECT_NEST || + m_type == OBJECT_RESEARCH || + m_type == OBJECT_RADAR || + m_type == OBJECT_INFO || + m_type == OBJECT_ENERGY || + m_type == OBJECT_LABO || + m_type == OBJECT_NUCLEAR || + m_type == OBJECT_PARA || + m_type == OBJECT_SAFE || + m_type == OBJECT_HUSTON || + m_type == OBJECT_START || + m_type == OBJECT_END ) // building? + { + pyroType = Gfx::PT_FRAGT; + } + else if ( m_type == OBJECT_MOBILEtg ) + { + pyroType = Gfx::PT_FRAGT; + } + else + { + pyroType = Gfx::PT_EXPLOT; + } + } + else if ( type == DestructionType::ExplosionWater ) + { + pyroType = Gfx::PT_FRAGW; + } + else if ( type == DestructionType::Burn ) // burning? + { + if ( m_type == OBJECT_MOTHER || + m_type == OBJECT_ANT || + m_type == OBJECT_SPIDER || + m_type == OBJECT_BEE || + m_type == OBJECT_WORM || + m_type == OBJECT_BULLET ) + { + pyroType = Gfx::PT_BURNO; + SetBurn(true); + } + else if ( m_type == OBJECT_HUMAN ) + { + pyroType = Gfx::PT_DEADG; + } + else + { + pyroType = Gfx::PT_BURNT; + SetBurn(true); + } + SetVirusMode(false); + } + else if ( type == DestructionType::Drowned ) + { + pyroType = Gfx::PT_DEADW; + } + m_engine->GetPyroManager()->Create(pyroType, this); if ( Implements(ObjectInterfaceType::Programmable) ) { @@ -553,8 +566,6 @@ bool COldObject::ExplodeObject(ExplosionType type, float force) CScriptFunctions::DestroyObjectVar(m_botVar, false); } } - - return true; } // (*) If a robot or cosmonaut dies, the subject must continue to exist, @@ -715,13 +726,19 @@ void COldObject::SetType(ObjectType type) m_type == OBJECT_SCRAP4 || m_type == OBJECT_SCRAP5 || m_type == OBJECT_BULLET || - m_type == OBJECT_EGG ) + m_type == OBJECT_EGG || + m_type == OBJECT_BOMB || + m_type == OBJECT_ANT || + m_type == OBJECT_WORM || + m_type == OBJECT_SPIDER || + m_type == OBJECT_BEE ) { + m_implementedInterfaces[static_cast(ObjectInterfaceType::Damageable)] = true; m_implementedInterfaces[static_cast(ObjectInterfaceType::Destroyable)] = true; m_implementedInterfaces[static_cast(ObjectInterfaceType::Fragile)] = true; m_implementedInterfaces[static_cast(ObjectInterfaceType::Shielded)] = false; } - else if( m_type == OBJECT_HUMAN || + else if (m_type == OBJECT_HUMAN || m_type == OBJECT_MOBILEfa || m_type == OBJECT_MOBILEta || m_type == OBJECT_MOBILEwa || @@ -743,7 +760,6 @@ void COldObject::SetType(ObjectType type) m_type == OBJECT_MOBILErr || m_type == OBJECT_MOBILErs || m_type == OBJECT_MOBILEsa || - m_type == OBJECT_MOBILEtg || m_type == OBJECT_MOBILEft || m_type == OBJECT_MOBILEtt || m_type == OBJECT_MOBILEwt || @@ -761,12 +777,22 @@ void COldObject::SetType(ObjectType type) m_type == OBJECT_ENERGY || m_type == OBJECT_LABO || m_type == OBJECT_NUCLEAR || - m_type == OBJECT_PARA ) + m_type == OBJECT_PARA || + m_type == OBJECT_MOTHER ) { + m_implementedInterfaces[static_cast(ObjectInterfaceType::Damageable)] = true; m_implementedInterfaces[static_cast(ObjectInterfaceType::Destroyable)] = true; m_implementedInterfaces[static_cast(ObjectInterfaceType::Fragile)] = false; m_implementedInterfaces[static_cast(ObjectInterfaceType::Shielded)] = true; } + else if (m_type == OBJECT_HUSTON || + m_type == OBJECT_BASE ) + { + m_implementedInterfaces[static_cast(ObjectInterfaceType::Damageable)] = true; + m_implementedInterfaces[static_cast(ObjectInterfaceType::Destroyable)] = false; + m_implementedInterfaces[static_cast(ObjectInterfaceType::Fragile)] = false; + m_implementedInterfaces[static_cast(ObjectInterfaceType::Shielded)] = false; + } else { m_implementedInterfaces[static_cast(ObjectInterfaceType::Destroyable)] = false; @@ -3330,3 +3356,63 @@ float COldObject::GetShieldFullRegenTime() assert(false); return 0.0f; } + +float COldObject::GetLightningHitProbability() +{ + if ( m_type == OBJECT_BASE || + m_type == OBJECT_DERRICK || + m_type == OBJECT_FACTORY || + m_type == OBJECT_REPAIR || + m_type == OBJECT_DESTROYER|| + m_type == OBJECT_STATION || + m_type == OBJECT_CONVERT || + m_type == OBJECT_TOWER || + m_type == OBJECT_RESEARCH || + m_type == OBJECT_RADAR || + m_type == OBJECT_INFO || + m_type == OBJECT_ENERGY || + m_type == OBJECT_LABO || + m_type == OBJECT_NUCLEAR || + m_type == OBJECT_PARA || + m_type == OBJECT_SAFE || + m_type == OBJECT_HUSTON ) // building? + { + return 1.0f; + } + if ( m_type == OBJECT_METAL || + m_type == OBJECT_POWER || + m_type == OBJECT_ATOMIC ) // resource? + { + return 0.3f; + } + if ( m_type == OBJECT_MOBILEfa || + m_type == OBJECT_MOBILEta || + m_type == OBJECT_MOBILEwa || + m_type == OBJECT_MOBILEia || + m_type == OBJECT_MOBILEfc || + m_type == OBJECT_MOBILEtc || + m_type == OBJECT_MOBILEwc || + m_type == OBJECT_MOBILEic || + m_type == OBJECT_MOBILEfi || + m_type == OBJECT_MOBILEti || + m_type == OBJECT_MOBILEwi || + m_type == OBJECT_MOBILEii || + m_type == OBJECT_MOBILEfs || + m_type == OBJECT_MOBILEts || + m_type == OBJECT_MOBILEws || + m_type == OBJECT_MOBILEis || + m_type == OBJECT_MOBILErt || + m_type == OBJECT_MOBILErc || + m_type == OBJECT_MOBILErr || + m_type == OBJECT_MOBILErs || + m_type == OBJECT_MOBILEsa || + m_type == OBJECT_MOBILEft || + m_type == OBJECT_MOBILEtt || + m_type == OBJECT_MOBILEwt || + m_type == OBJECT_MOBILEit || + m_type == OBJECT_MOBILEdr ) // robot? + { + return 0.5f; + } + return 0.0f; +} diff --git a/src/object/old_object.h b/src/object/old_object.h index f4285f91..c21fd924 100644 --- a/src/object/old_object.h +++ b/src/object/old_object.h @@ -105,7 +105,9 @@ public: ~COldObject(); void Simplify() override; - bool ExplodeObject(ExplosionType type, float force = 1.0f) override; + + bool DamageObject(DamageType type, float force = -1.0f) override; + void DestroyObject(DestructionType type) override; bool EventProcess(const Event& event) override; void UpdateMapping(); @@ -321,6 +323,8 @@ public: bool IsRepairable() override; float GetShieldFullRegenTime() override; + float GetLightningHitProbability() override; + protected: bool EventFrame(const Event &event); void VirusFrame(float rTime); diff --git a/src/object/old_object_interface.cpp b/src/object/old_object_interface.cpp index e3ee5fa4..c849ffbc 100644 --- a/src/object/old_object_interface.cpp +++ b/src/object/old_object_interface.cpp @@ -25,11 +25,6 @@ void COldObjectInterface::Simplify() throw std::logic_error("Simplify: not implemented!"); } -bool COldObjectInterface::ExplodeObject(ExplosionType type, float force) -{ - throw std::logic_error("ExplodeObject: not implemented!"); -} - void COldObjectInterface::DeletePart(int part) { throw std::logic_error("DeletePart: not implemented!"); diff --git a/src/object/old_object_interface.h b/src/object/old_object_interface.h index 7ab70f85..ea534c52 100644 --- a/src/object/old_object_interface.h +++ b/src/object/old_object_interface.h @@ -50,20 +50,12 @@ struct Character Math::Vector posPower; // position of the battery }; -enum class ExplosionType -{ - Bang = 1, - Burn = 2, - Water = 3, -}; - class COldObjectInterface { public: virtual ~COldObjectInterface() {} virtual void Simplify(); - virtual bool ExplodeObject(ExplosionType type, float force = 1.0f); virtual void DeletePart(int part); virtual void SetType(ObjectType type); diff --git a/src/physics/physics.cpp b/src/physics/physics.cpp index 189ae96f..e0450931 100644 --- a/src/physics/physics.cpp +++ b/src/physics/physics.cpp @@ -1573,7 +1573,7 @@ bool CPhysics::EventFrame(const Event &event) if ( m_bLand && m_fallingHeight != 0.0f ) // if fell { float force = (m_fallingHeight - m_object->GetPosition().y) * m_fallDamageFraction; - m_object->ExplodeObject(ExplosionType::Bang, force); + m_object->DamageObject(DamageType::Fall, force); m_fallingHeight = 0.0f; } @@ -1775,10 +1775,13 @@ void CPhysics::WaterFrame(float aTime, float rTime) if ( !m_object->GetActive() ) return; - if ( m_water->GetLava() || - (type == OBJECT_HUMAN && - m_object->GetOption() != 0 ) || // human without a helmet? - type == OBJECT_MOBILEfa || + if (type == OBJECT_HUMAN && m_object->GetOption() != 0 ) // human without a helmet?) + { + assert(m_object->Implements(ObjectInterfaceType::Destroyable)); + dynamic_cast(m_object)->DestroyObject(DestructionType::Drowned); + } + else if ( m_water->GetLava() || + type == OBJECT_MOBILEfa || // TODO: A function in CObject to check if object is waterproof or not type == OBJECT_MOBILEta || type == OBJECT_MOBILEwa || type == OBJECT_MOBILEia || @@ -1803,9 +1806,12 @@ void CPhysics::WaterFrame(float aTime, float rTime) type == OBJECT_MOBILEwt || type == OBJECT_MOBILEit || type == OBJECT_MOBILEdr || - type == OBJECT_APOLLO2 ) // vehicle not underwater? + type == OBJECT_APOLLO2 ) { - m_object->ExplodeObject(ExplosionType::Water, 1.0f); // starts explosion + if (m_object->Implements(ObjectInterfaceType::Destroyable)) + { + dynamic_cast(m_object)->DestroyObject(DestructionType::ExplosionWater); + } } } @@ -2697,91 +2703,78 @@ bool CPhysics::ExploOther(ObjectType iType, { JostleObject(pObj, 1.0f); // shakes the object - if ( force > 50.0f && - (oType == OBJECT_FRET || - oType == OBJECT_METAL ) ) + if (pObj->Implements(ObjectInterfaceType::Fragile)) { - m_engine->GetPyroManager()->Create(Gfx::PT_EXPLOT, pObj); // total destruction + // TODO: CFragileObject::GetDestructionForce (I can't do this now because you can't inherit both in COldObject ~krzys_h) + DamageType damageType = DamageType::Collision; + float destructionForce = 50.0f; // Titanium, PowerCell, NuclearCell, default + if (pObj->GetType() == OBJECT_STONE ) { destructionForce = 25.0f; } // TitaniumOre + if (pObj->GetType() == OBJECT_URANIUM ) { destructionForce = 25.0f; } // UraniumOre + if (pObj->GetType() == OBJECT_MOBILEtg) { destructionForce = 10.0f; damageType = DamageType::Explosive; } // TargetBot + if (pObj->GetType() == OBJECT_TNT ) { destructionForce = 10.0f; damageType = DamageType::Explosive; } // TNT + if (pObj->GetType() == OBJECT_BOMB ) { destructionForce = 0.0f; damageType = DamageType::Explosive; } // Mine + + if ( force > destructionForce ) + { + dynamic_cast(pObj)->DamageObject(damageType); + } } - if ( force > 50.0f && - (oType == OBJECT_POWER || - oType == OBJECT_ATOMIC ) ) + if ( force > 25.0f ) { - m_engine->GetPyroManager()->Create(Gfx::PT_FRAGT, pObj); // total destruction - } + // TODO: Some function in CShieldedObject. GetCollisionResistance()? + if (oType == OBJECT_DERRICK || + oType == OBJECT_FACTORY || + oType == OBJECT_STATION || + oType == OBJECT_CONVERT || + oType == OBJECT_REPAIR || + oType == OBJECT_DESTROYER|| + oType == OBJECT_TOWER || + oType == OBJECT_RESEARCH || + oType == OBJECT_RADAR || + oType == OBJECT_INFO || + oType == OBJECT_ENERGY || + oType == OBJECT_LABO || + oType == OBJECT_NUCLEAR || + oType == OBJECT_PARA || + oType == OBJECT_SAFE || + oType == OBJECT_HUSTON ) // building? + { + assert(pObj->Implements(ObjectInterfaceType::Damageable)); + dynamic_cast(pObj)->DamageObject(DamageType::Collision, force/400.0f); + } - if ( force > 25.0f && - (oType == OBJECT_STONE || - oType == OBJECT_URANIUM ) ) - { - m_engine->GetPyroManager()->Create(Gfx::PT_FRAGT, pObj); // total destruction - } - - if ( force > 25.0f && - (oType == OBJECT_DERRICK || - oType == OBJECT_FACTORY || - oType == OBJECT_STATION || - oType == OBJECT_CONVERT || - oType == OBJECT_REPAIR || - oType == OBJECT_DESTROYER|| - oType == OBJECT_TOWER || - oType == OBJECT_RESEARCH || - oType == OBJECT_RADAR || - oType == OBJECT_INFO || - oType == OBJECT_ENERGY || - oType == OBJECT_LABO || - oType == OBJECT_NUCLEAR || - oType == OBJECT_PARA || - oType == OBJECT_SAFE || - oType == OBJECT_HUSTON ) ) // building? - { - pObj->ExplodeObject(ExplosionType::Bang, force/400.0f); - } - - if ( force > 25.0f && - (oType == OBJECT_MOBILEwa || - oType == OBJECT_MOBILEta || - oType == OBJECT_MOBILEfa || - oType == OBJECT_MOBILEia || - oType == OBJECT_MOBILEwc || - oType == OBJECT_MOBILEtc || - oType == OBJECT_MOBILEfc || - oType == OBJECT_MOBILEic || - oType == OBJECT_MOBILEwi || - oType == OBJECT_MOBILEti || - oType == OBJECT_MOBILEfi || - oType == OBJECT_MOBILEii || - oType == OBJECT_MOBILEws || - oType == OBJECT_MOBILEts || - oType == OBJECT_MOBILEfs || - oType == OBJECT_MOBILEis || - oType == OBJECT_MOBILErt || - oType == OBJECT_MOBILErc || - oType == OBJECT_MOBILErr || - oType == OBJECT_MOBILErs || - oType == OBJECT_MOBILEsa || - oType == OBJECT_MOBILEwt || - oType == OBJECT_MOBILEtt || - oType == OBJECT_MOBILEft || - oType == OBJECT_MOBILEit || - oType == OBJECT_MOBILEdr || - oType == OBJECT_APOLLO2 ) ) // vehicle? - { - pObj->ExplodeObject(ExplosionType::Bang, force/200.0f); - } - - if ( force > 10.0f && - (oType == OBJECT_MOBILEtg || - oType == OBJECT_TNT ) ) - { - m_engine->GetPyroManager()->Create(Gfx::PT_FRAGT, pObj); // total destruction - } - - if ( force > 0.0f && - oType == OBJECT_BOMB ) - { - m_engine->GetPyroManager()->Create(Gfx::PT_FRAGT, pObj); // total destruction + if (oType == OBJECT_MOBILEwa || + oType == OBJECT_MOBILEta || + oType == OBJECT_MOBILEfa || + oType == OBJECT_MOBILEia || + oType == OBJECT_MOBILEwc || + oType == OBJECT_MOBILEtc || + oType == OBJECT_MOBILEfc || + oType == OBJECT_MOBILEic || + oType == OBJECT_MOBILEwi || + oType == OBJECT_MOBILEti || + oType == OBJECT_MOBILEfi || + oType == OBJECT_MOBILEii || + oType == OBJECT_MOBILEws || + oType == OBJECT_MOBILEts || + oType == OBJECT_MOBILEfs || + oType == OBJECT_MOBILEis || + oType == OBJECT_MOBILErt || + oType == OBJECT_MOBILErc || + oType == OBJECT_MOBILErr || + oType == OBJECT_MOBILErs || + oType == OBJECT_MOBILEsa || + oType == OBJECT_MOBILEwt || + oType == OBJECT_MOBILEtt || + oType == OBJECT_MOBILEft || + oType == OBJECT_MOBILEit || + oType == OBJECT_MOBILEdr || + oType == OBJECT_APOLLO2 ) // vehicle? + { + assert(pObj->Implements(ObjectInterfaceType::Damageable)); + dynamic_cast(pObj)->DamageObject(DamageType::Collision, force/200.0f); + } } return false; @@ -2794,118 +2787,99 @@ bool CPhysics::ExploOther(ObjectType iType, int CPhysics::ExploHimself(ObjectType iType, ObjectType oType, float force) { + if (!m_object->Implements(ObjectInterfaceType::Damageable)) return 1; - if ( force > 10.0f && - (oType == OBJECT_TNT || - oType == OBJECT_MOBILEtg ) ) + // TODO: CExplosiveObject? derrives from CFragileObject + float destructionForce = -1.0f; // minimal force required to destroy an object using this explosive, default: not explosive + if ( oType == OBJECT_TNT ) destructionForce = 10.0f; // TNT + if ( oType == OBJECT_MOBILEtg ) destructionForce = 10.0f; // TargetBot + if ( oType == OBJECT_BOMB ) destructionForce = 0.0f; // Mine + + if ( force > destructionForce && destructionForce >= 0.0f ) { - Gfx::PyroType type; - if ( iType == OBJECT_HUMAN ) type = Gfx::PT_DEADG; - else type = Gfx::PT_EXPLOT; - m_engine->GetPyroManager()->Create(type, m_object); // total destruction + dynamic_cast(m_object)->DamageObject(DamageType::Explosive); return 2; } - if ( force > 0.0f && - oType == OBJECT_BOMB ) + if ( force > 25.0f ) { - Gfx::PyroType type; - if ( iType == OBJECT_HUMAN ) + if ( iType == OBJECT_HUMAN || + iType == OBJECT_MOBILEwa || + iType == OBJECT_MOBILEta || + iType == OBJECT_MOBILEfa || + iType == OBJECT_MOBILEia || + iType == OBJECT_MOBILEwc || + iType == OBJECT_MOBILEtc || + iType == OBJECT_MOBILEfc || + iType == OBJECT_MOBILEic || + iType == OBJECT_MOBILEwi || + iType == OBJECT_MOBILEti || + iType == OBJECT_MOBILEfi || + iType == OBJECT_MOBILEii || + iType == OBJECT_MOBILEws || + iType == OBJECT_MOBILEts || + iType == OBJECT_MOBILEfs || + iType == OBJECT_MOBILEis || + iType == OBJECT_MOBILErt || + iType == OBJECT_MOBILErc || + iType == OBJECT_MOBILErr || + iType == OBJECT_MOBILErs || + iType == OBJECT_MOBILEsa || + iType == OBJECT_MOBILEwt || + iType == OBJECT_MOBILEtt || + iType == OBJECT_MOBILEft || + iType == OBJECT_MOBILEit || + iType == OBJECT_MOBILEdr || + iType == OBJECT_APOLLO2 ) // vehicle? { - type = Gfx::PT_DEADG; - } - else if ( iType == OBJECT_ANT || - iType == OBJECT_SPIDER || - iType == OBJECT_BEE ) - { - type = Gfx::PT_EXPLOO; - } - else - { - type = Gfx::PT_EXPLOT; - } - m_engine->GetPyroManager()->Create(type, m_object); // total destruction - return 2; - } + if ( oType == OBJECT_DERRICK || + oType == OBJECT_FACTORY || + oType == OBJECT_STATION || + oType == OBJECT_CONVERT || + oType == OBJECT_REPAIR || + oType == OBJECT_DESTROYER|| + oType == OBJECT_TOWER || + oType == OBJECT_RESEARCH || + oType == OBJECT_RADAR || + oType == OBJECT_INFO || + oType == OBJECT_ENERGY || + oType == OBJECT_LABO || + oType == OBJECT_NUCLEAR || + oType == OBJECT_PARA || + oType == OBJECT_SAFE || + oType == OBJECT_HUSTON ) // building? + { + force /= 200.0f; + } + else if ( oType == OBJECT_MOTHER || + oType == OBJECT_ANT || + oType == OBJECT_SPIDER || + oType == OBJECT_BEE || + oType == OBJECT_WORM ) // insect? + { + force /= 400.0f; + } + else + if ( oType == OBJECT_FRET || + oType == OBJECT_STONE || + oType == OBJECT_METAL ) + { + force /= 500.0f; + } + else + if ( oType == OBJECT_URANIUM || + oType == OBJECT_POWER || + oType == OBJECT_ATOMIC ) + { + force /= 100.0f; + } + else + { + force /= 200.0f; + } - if ( force > 25.0f && - (iType == OBJECT_HUMAN || - iType == OBJECT_MOBILEwa || - iType == OBJECT_MOBILEta || - iType == OBJECT_MOBILEfa || - iType == OBJECT_MOBILEia || - iType == OBJECT_MOBILEwc || - iType == OBJECT_MOBILEtc || - iType == OBJECT_MOBILEfc || - iType == OBJECT_MOBILEic || - iType == OBJECT_MOBILEwi || - iType == OBJECT_MOBILEti || - iType == OBJECT_MOBILEfi || - iType == OBJECT_MOBILEii || - iType == OBJECT_MOBILEws || - iType == OBJECT_MOBILEts || - iType == OBJECT_MOBILEfs || - iType == OBJECT_MOBILEis || - iType == OBJECT_MOBILErt || - iType == OBJECT_MOBILErc || - iType == OBJECT_MOBILErr || - iType == OBJECT_MOBILErs || - iType == OBJECT_MOBILEsa || - iType == OBJECT_MOBILEwt || - iType == OBJECT_MOBILEtt || - iType == OBJECT_MOBILEft || - iType == OBJECT_MOBILEit || - iType == OBJECT_MOBILEdr || - iType == OBJECT_APOLLO2 ) ) // vehicle? - { - if ( oType == OBJECT_DERRICK || - oType == OBJECT_FACTORY || - oType == OBJECT_STATION || - oType == OBJECT_CONVERT || - oType == OBJECT_REPAIR || - oType == OBJECT_DESTROYER|| - oType == OBJECT_TOWER || - oType == OBJECT_RESEARCH || - oType == OBJECT_RADAR || - oType == OBJECT_INFO || - oType == OBJECT_ENERGY || - oType == OBJECT_LABO || - oType == OBJECT_NUCLEAR || - oType == OBJECT_PARA || - oType == OBJECT_SAFE || - oType == OBJECT_HUSTON ) // building? - { - force /= 200.0f; + if ( dynamic_cast(m_object)->DamageObject(DamageType::Collision, force) ) return 2; } - else - if ( oType == OBJECT_MOTHER || - oType == OBJECT_ANT || - oType == OBJECT_SPIDER || - oType == OBJECT_BEE || - oType == OBJECT_WORM ) // insect? - { - force /= 400.0f; - } - else - if ( oType == OBJECT_FRET || - oType == OBJECT_STONE || - oType == OBJECT_METAL ) - { - force /= 500.0f; - } - else - if ( oType == OBJECT_URANIUM || - oType == OBJECT_POWER || - oType == OBJECT_ATOMIC ) - { - force /= 100.0f; - } - else - { - force /= 200.0f; - } - - if ( m_object->ExplodeObject(ExplosionType::Bang, force) ) return 2; } return 1; diff --git a/src/script/scriptfunc.cpp b/src/script/scriptfunc.cpp index 26a4fcc6..ae9772e7 100644 --- a/src/script/scriptfunc.cpp +++ b/src/script/scriptfunc.cpp @@ -46,6 +46,7 @@ #include "object/auto/autobase.h" #include "object/auto/autofactory.h" +#include "object/interface/destroyable_object.h" #include "object/interface/programmable_object.h" #include "object/interface/task_executor_object.h" #include "object/interface/trace_drawing_object.h" @@ -886,25 +887,19 @@ bool CScriptFunctions::rTakeOff(CBotVar* thisclass, CBotVar* var, CBotVar* resul return true; } -// Compilation of the instruction "delete(rank[, exploType[, force]])". +// Compilation of the instruction "delete(rank[, exploType])". CBotTypResult CScriptFunctions::cDelete(CBotVar* &var, void* user) { if ( var == 0 ) return CBotTypResult(CBotErrLowParam); - if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + if ( var->GetType() != CBotTypInt ) return CBotTypResult(CBotErrBadNum); var = var->GetNext(); if ( var != 0 ) { if ( var->GetType() != CBotTypInt ) return CBotTypResult(CBotErrBadNum); var = var->GetNext(); - - if ( var != 0 ) - { - if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); - var = var->GetNext(); - } } if ( var != 0 ) return CBotTypResult(CBotErrOverParam); @@ -912,23 +907,18 @@ CBotTypResult CScriptFunctions::cDelete(CBotVar* &var, void* user) return CBotTypResult(CBotTypFloat); } -// Instruction "delete(rank[, exploType[, force]])". +// Instruction "delete(rank[, exploType])". bool CScriptFunctions::rDelete(CBotVar* var, CBotVar* result, int& exception, void* user) { - int exploType = 0; - float force = 1.0f; + int rank; + DestructionType exploType = DestructionType::Explosion; - int rank = var->GetValInt(); + rank = var->GetValInt(); var->GetNext(); if ( var != 0 ) { - exploType = var->GetValInt(); - var->GetNext(); - if ( var != 0 ) - { - force = var->GetValFloat(); - } + exploType = static_cast(var->GetValInt()); } CObject* obj = CObjectManager::GetInstancePointer()->GetObjectById(rank); @@ -938,9 +928,9 @@ bool CScriptFunctions::rDelete(CBotVar* var, CBotVar* result, int& exception, vo } else { - if ( exploType != 0 ) + if ( exploType != DestructionType::NoEffect && obj->Implements(ObjectInterfaceType::Destroyable) ) { - obj->ExplodeObject(static_cast(exploType), force); + dynamic_cast(obj)->DestroyObject(static_cast(exploType)); } else { @@ -3624,10 +3614,11 @@ void CScriptFunctions::Init() CBotProgram::DefineNum("FilterEnemy", FILTER_ENEMY); CBotProgram::DefineNum("FilterNeutral", FILTER_NEUTRAL); - CBotProgram::DefineNum("ExplosionNone", 0); - CBotProgram::DefineNum("ExplosionBang", static_cast(ExplosionType::Bang)); - CBotProgram::DefineNum("ExplosionBurn", static_cast(ExplosionType::Burn)); - CBotProgram::DefineNum("ExplosionWater", static_cast(ExplosionType::Water)); + CBotProgram::DefineNum("DestructionNone", static_cast(DestructionType::NoEffect)); + CBotProgram::DefineNum("DestructionExplosion", static_cast(DestructionType::Explosion)); + CBotProgram::DefineNum("DestructionExplosionWater", static_cast(DestructionType::ExplosionWater)); + CBotProgram::DefineNum("DestructionBurn", static_cast(DestructionType::Burn)); + CBotProgram::DefineNum("DestructionDrowned", static_cast(DestructionType::Drowned)); CBotProgram::DefineNum("ResultNotEnded", ERR_MISSION_NOTERM); CBotProgram::DefineNum("ResultLost", INFO_LOST);