Refactored ExplodeObject

master
krzys-h 2015-08-13 18:54:44 +02:00
parent bc05cda0e7
commit bfd3a5b23c
15 changed files with 551 additions and 573 deletions

View File

@ -37,6 +37,7 @@
#include "object/auto/autopowercaptor.h" #include "object/auto/autopowercaptor.h"
#include "object/interface/destroyable_object.h"
#include "object/interface/transportable_object.h" #include "object/interface/transportable_object.h"
@ -103,6 +104,7 @@ bool CLightning::EventFrame(const Event &event)
m_pos = obj->GetPosition(); m_pos = obj->GetPosition();
m_terrain->AdjustToFloor(m_pos, true); m_terrain->AdjustToFloor(m_pos, true);
// TODO: CLightningConductorObject
ObjectType type = obj->GetType(); ObjectType type = obj->GetType();
if (type == OBJECT_BASE) if (type == OBJECT_BASE)
{ {
@ -118,7 +120,8 @@ bool CLightning::EventFrame(const Event &event)
} }
else else
{ {
obj->ExplodeObject(ExplosionType::Bang, 1.0f); assert(obj->Implements(ObjectInterfaceType::Destroyable));
dynamic_cast<CDestroyableObject*>(obj)->DamageObject(DamageType::Lightning);
} }
} }
@ -329,64 +332,12 @@ CObject* CLightning::SearchObject(Math::Vector pos)
{ {
paraObj.push_back(obj); paraObj.push_back(obj);
paraObjPos.push_back(obj->GetPosition()); paraObjPos.push_back(obj->GetPosition());
continue;
} }
float detect = 0.0f; if (!obj->Implements(ObjectInterfaceType::Destroyable)) continue;
if ( type == OBJECT_BASE ||
type == OBJECT_DERRICK || float detect = m_magnetic * dynamic_cast<CDestroyableObject*>(obj)->GetLightningHitProbability();
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 (detect == 0.0f) continue; if (detect == 0.0f) continue;
Math::Vector oPos = obj->GetPosition(); Math::Vector oPos = obj->GetPosition();

View File

@ -38,6 +38,8 @@
#include "object/object.h" #include "object/object.h"
#include "object/object_manager.h" #include "object/object_manager.h"
#include "object/interface/damageable_object.h"
#include <cstring> #include <cstring>
@ -64,12 +66,6 @@ bool IsAlien(ObjectType type)
type == OBJECT_MOBILEtg ); 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) CParticle::CParticle(CEngine* engine)
: m_engine(engine) : m_engine(engine)
{ {
@ -953,10 +949,8 @@ void CParticle::FrameParticle(float rTime)
m_particle[i].goal = m_particle[i].pos; m_particle[i].goal = m_particle[i].pos;
if (object != nullptr) if (object != nullptr)
{ {
if (object->GetType() == OBJECT_MOTHER) assert(object->Implements(ObjectInterfaceType::Damageable));
object->ExplodeObject(ExplosionType::Bang, 0.1f); dynamic_cast<CDamageableObject*>(object)->DamageObject(DamageType::Phazer, 0.0f);
else
object->ExplodeObject(ExplosionType::Bang, 0.0f);
} }
m_particle[i].zoom = 1.0f-(m_particle[i].time-m_particle[i].duration); 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; m_particle[i].goal = m_particle[i].pos;
if (object != nullptr) if (object != nullptr)
{ {
object->ExplodeObject(ExplosionType::Burn, 0.0f); assert(object->Implements(ObjectInterfaceType::Damageable));
dynamic_cast<CDamageableObject*>(object)->DamageObject(DamageType::Fire, 0.0f);
m_exploGunCounter++; m_exploGunCounter++;
@ -1238,7 +1233,8 @@ void CParticle::FrameParticle(float rTime)
if (object->GetType() != OBJECT_HUMAN) if (object->GetType() != OBJECT_HUMAN)
Play(SOUND_TOUCH, m_particle[i].pos, 1.0f); Play(SOUND_TOUCH, m_particle[i].pos, 1.0f);
object->ExplodeObject(ExplosionType::Bang, 0.0f); // starts explosion assert(object->Implements(ObjectInterfaceType::Damageable));
dynamic_cast<CDamageableObject*>(object)->DamageObject(DamageType::Organic, 0.0f); // starts explosion
} }
} }
} }
@ -1280,7 +1276,8 @@ void CParticle::FrameParticle(float rTime)
} }
else else
{ {
object->ExplodeObject(ExplosionType::Burn, 1.0f); // starts explosion assert(object->Implements(ObjectInterfaceType::Damageable));
dynamic_cast<CDamageableObject*>(object)->DamageObject(DamageType::Fire); // starts explosion
} }
} }
} }
@ -1336,7 +1333,8 @@ void CParticle::FrameParticle(float rTime)
m_particle[i].goal = m_particle[i].pos; m_particle[i].goal = m_particle[i].pos;
if (object != nullptr) if (object != nullptr)
{ {
object->ExplodeObject(ExplosionType::Bang, 0.0f); assert(object->Implements(ObjectInterfaceType::Damageable));
dynamic_cast<CDamageableObject*>(object)->DamageObject(DamageType::Organic, 0.0f);
m_exploGunCounter ++; m_exploGunCounter ++;
@ -2411,7 +2409,10 @@ void CParticle::FrameParticle(float rTime)
CObject* object = SearchObjectRay(m_particle[i].pos, m_particle[i].goal, CObject* object = SearchObjectRay(m_particle[i].pos, m_particle[i].goal,
m_particle[i].type, m_particle[i].objFather); m_particle[i].type, m_particle[i].objFather);
if (object != nullptr) if (object != nullptr)
object->ExplodeObject(ExplosionType::Bang, 0.0f); {
assert(object->Implements(ObjectInterfaceType::Damageable));
dynamic_cast<CDamageableObject*>(object)->DamageObject(DamageType::Tower);
}
} }
ts.x = 0.00f; ts.x = 0.00f;
@ -3589,29 +3590,27 @@ CObject* CParticle::SearchObjectGun(Math::Vector old, Math::Vector pos,
if (type == PARTIGUN1) // fireball shooting? if (type == PARTIGUN1) // fireball shooting?
{ {
if (oType == OBJECT_MOTHER) continue; if (oType == OBJECT_MOTHER) continue;
if (!obj->Implements(ObjectInterfaceType::Destroyable)) continue;
} }
else if (type == PARTIGUN2) // shooting insect? else if (type == PARTIGUN2) // shooting insect?
{ {
if (!IsSoft(obj)) continue; if (IsAlien(obj->GetType())) continue;
} }
else if (type == PARTIGUN3) // suiciding spider? else if (type == PARTIGUN3) // suiciding spider?
{ {
if (!IsSoft(obj)) continue; if (!IsAlien(obj->GetType())) continue;
} }
else if (type == PARTIGUN4) // orgaball shooting? else if (type == PARTIGUN4) // orgaball shooting?
{ {
if (oType == OBJECT_MOTHER) continue; if (oType == OBJECT_MOTHER) continue;
if (!obj->Implements(ObjectInterfaceType::Destroyable)) continue;
} }
else if (type == PARTITRACK11) // phazer shooting? else if (type == PARTITRACK11) // phazer shooting?
{ {
if (!obj->Implements(ObjectInterfaceType::Destroyable)) continue;
} }
else else
{ {
continue; continue;
} }
if (!obj->Implements(ObjectInterfaceType::Damageable)) continue;
Math::Vector oPos = obj->GetPosition(); Math::Vector oPos = obj->GetPosition();

View File

@ -2198,55 +2198,7 @@ CObject* CPyro::FallSearchBeeExplo()
for (CObject* obj : CObjectManager::GetInstancePointer()->GetAllObjects()) for (CObject* obj : CObjectManager::GetInstancePointer()->GetAllObjects())
{ {
ObjectType oType = obj->GetType(); if ( obj->Implements(ObjectInterfaceType::Destroyable) ) continue;
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 (IsObjectBeingTransported(obj)) continue; if (IsObjectBeingTransported(obj)) continue;
@ -2260,7 +2212,7 @@ CObject* CPyro::FallSearchBeeExplo()
return obj; return obj;
} }
if ( oType == OBJECT_BASE ) if ( obj->GetType() == OBJECT_BASE )
{ {
float distance = Math::Distance(oPos, bulletCrashSphere.sphere.pos); float distance = Math::Distance(oPos, bulletCrashSphere.sphere.pos);
if (distance < 25.0f) if (distance < 25.0f)
@ -2317,7 +2269,8 @@ void CPyro::FallProgress(float rTime)
{ {
if (floor) // reaches the ground? if (floor) // reaches the ground?
{ {
m_object->ExplodeObject(ExplosionType::Bang, 0.0f); // start explosion assert(m_object->Implements(ObjectInterfaceType::Destroyable));
dynamic_cast<CDestroyableObject*>(m_object)->DestroyObject(DestructionType::Explosion);
} }
} }
else else
@ -2332,13 +2285,15 @@ void CPyro::FallProgress(float rTime)
} }
else else
{ {
if (obj->ExplodeObject(ExplosionType::Bang, 1.0f)) // start explosion assert(obj->Implements(ObjectInterfaceType::Damageable));
if (dynamic_cast<CDamageableObject*>(obj)->DamageObject(DamageType::FallingObject))
{ {
DeleteObject(true, true); // removes the ball DeleteObject(true, true); // removes the ball
} }
else else
{ {
m_object->ExplodeObject(ExplosionType::Bang, 0.0f); // start explosion assert(m_object->Implements(ObjectInterfaceType::Destroyable));
dynamic_cast<CDestroyableObject*>(m_object)->DestroyObject(DestructionType::Explosion);
} }
} }
} }

View File

@ -43,7 +43,7 @@ enum PyroType
PT_SHOTT = 9, //! < hit technical object PT_SHOTT = 9, //! < hit technical object
PT_SHOTH = 10, //! < hit human PT_SHOTH = 10, //! < hit human
PT_SHOTM = 11, //! < hit queen 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_EGG = 13, //! < break the egg
PT_BURNT = 14, //! < burning of technical object PT_BURNT = 14, //! < burning of technical object
PT_BURNO = 15, //! < burning of organic object PT_BURNO = 15, //! < burning of organic object

View File

@ -175,8 +175,8 @@ bool CAutoDestroyer::EventProcess(const Event &event)
scrap = SearchPlastic(); scrap = SearchPlastic();
if ( scrap != nullptr ) if ( scrap != nullptr )
{ {
//m_engine->GetPyroManager()->Create(Gfx::PT_FRAGT, scrap); assert(scrap->Implements(ObjectInterfaceType::Destroyable));
scrap->ExplodeObject(ExplosionType::Bang, 1.0f); dynamic_cast<CDestroyableObject*>(scrap)->DestroyObject(DestructionType::Explosion);
} }
m_bExplo = true; m_bExplo = true;
} }
@ -283,57 +283,9 @@ CObject* CAutoDestroyer::SearchPlastic()
for (CObject* obj : CObjectManager::GetInstancePointer()->GetAllObjects()) for (CObject* obj : CObjectManager::GetInstancePointer()->GetAllObjects())
{ {
ObjectType type = obj->GetType(); if (!obj->Implements(ObjectInterfaceType::Destroyable)) continue;
//if ( type != OBJECT_SCRAP4 && if (obj->GetType() == OBJECT_HUMAN || obj->GetType() == OBJECT_TECH) continue;
// 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;
Math::Vector oPos = obj->GetPosition(); Math::Vector oPos = obj->GetPosition();
float dist = Math::Distance(oPos, sPos); float dist = Math::Distance(oPos, sPos);
if ( dist <= 5.0f ) return obj; if ( dist <= 5.0f ) return obj;

View File

@ -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<int>(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;
};

View File

@ -19,7 +19,16 @@
#pragma once #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 * \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) * 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: public:
explicit CDestroyableObject(ObjectInterfaceTypes& types) explicit CDestroyableObject(ObjectInterfaceTypes& types)
: CDamageableObject(types)
{ {
types[static_cast<int>(ObjectInterfaceType::Destroyable)] = true; types[static_cast<int>(ObjectInterfaceType::Destroyable)] = true;
} }
virtual ~CDestroyableObject() 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;
}; };

View File

@ -47,6 +47,7 @@ enum class ObjectInterfaceType
PowerContainer, //!< objects that hold power PowerContainer, //!< objects that hold power
Ranged, //!< objects that have a operation range to be displayed after pressing button in the UI Ranged, //!< objects that have a operation range to be displayed after pressing button in the UI
TraceDrawing, //!< objects that can draw wheel trace 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) Destroyable, //!< objects that can be destroyed (base for Shielded and Fragile)
Fragile, //!< objects that are destroyed immediately after hit Fragile, //!< objects that are destroyed immediately after hit
Shielded, //!< objects that can be destroyed after the shield goes down to 0 Shielded, //!< objects that can be destroyed after the shield goes down to 0

View File

@ -202,7 +202,16 @@ void CObjectManager::DestroyTeam(int team)
for (CObject* object : GetAllObjects()) for (CObject* object : GetAllObjects())
{ {
if (object->GetTeam() == team) if (object->GetTeam() == team)
object->ExplodeObject(ExplosionType::Bang, 1.0f); {
if (object->Implements(ObjectInterfaceType::Destroyable))
{
dynamic_cast<CDestroyableObject*>(object)->DestroyObject(DestructionType::Explosion);
}
else
{
DeleteObject(object);
}
}
} }
} }

View File

@ -68,9 +68,6 @@
const float VIRUS_DELAY = 60.0f; // duration of virus infection 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. // Object's constructor.
@ -331,192 +328,208 @@ void COldObject::Simplify()
} }
// Detonates an object, when struck by a shot. bool COldObject::DamageObject(DamageType type, float force)
// If false is returned, the object is still screwed.
// If true is returned, the object is destroyed.
bool COldObject::ExplodeObject(ExplosionType type, float force)
{ {
assert(Implements(ObjectInterfaceType::Destroyable)); assert(Implements(ObjectInterfaceType::Damageable));
assert(Implements(ObjectInterfaceType::Shielded) || Implements(ObjectInterfaceType::Fragile)); 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? // Fragile, but can have fire effect
{ // TODO: IsBurnable()
type = ExplosionType::Bang; force = -1.0f;
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? // TODO: I don't understand, why does it apply damage only once every 0.5 second?
if ( m_shotTime < 0.5f ) return false; if ( m_shotTime < 0.5f ) return false;
m_shotTime = 0.0f; m_shotTime = 0.0f;
} }
if ( m_type == OBJECT_HUMAN && m_bDead ) return false;
bool deadAlready = true;
float loss = 1.0f; float loss = 1.0f;
if ( Implements(ObjectInterfaceType::Shielded) ) bool dead = true;
if (Implements(ObjectInterfaceType::Shielded))
{ {
// Calculate the power lost by the explosion. float magnifyDamage = m_magnifyDamage * m_main->GetGlobalMagnifyDamage();
loss = force; if (force >= 0)
if ( loss == 0.0f )
{ {
if ( m_type == OBJECT_HUMAN ) // Calculate the shield lost by the explosion
if ( force == 0.0f ) // use default?
{ {
loss = LOSS_SHIELD_H; if ( m_type == OBJECT_HUMAN || m_type == OBJECT_MOTHER )
} {
else if ( m_type == OBJECT_MOTHER ) loss = 0.1f;
{ }
loss = LOSS_SHIELD_M; else
{
loss = 0.24f;
}
} }
else else
{ {
loss = LOSS_SHIELD; loss = force;
} }
} loss *= magnifyDamage;
loss *= m_magnifyDamage; if (loss > 1.0f) loss = 1.0f;
loss *= m_main->GetGlobalMagnifyDamage();
// Decreases the power of the shield. // Decreases the the shield
float shield = GetShield(); float shield = GetShield();
shield -= loss; shield -= loss;
SetShield(shield); 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;
}
} }
else else
{ {
if ( m_type == OBJECT_HUMAN ) if ( magnifyDamage != 0.0f )
{ {
pyroType = Gfx::PT_SHOTH; // Dead immediately
} SetShield(0.0f);
else if ( m_type == OBJECT_MOTHER )
{
pyroType = Gfx::PT_SHOTM;
}
else
{
pyroType = Gfx::PT_SHOTT;
} }
} }
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 || DestroyObject(DestructionType::Burn);
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 == ExplosionType::Water ) else
{ {
if ( m_type == OBJECT_HUMAN ) DestroyObject(DestructionType::Explosion);
{
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;
} }
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) ) if ( Implements(ObjectInterfaceType::Programmable) )
{ {
@ -553,8 +566,6 @@ bool COldObject::ExplodeObject(ExplosionType type, float force)
CScriptFunctions::DestroyObjectVar(m_botVar, false); CScriptFunctions::DestroyObjectVar(m_botVar, false);
} }
} }
return true;
} }
// (*) If a robot or cosmonaut dies, the subject must continue to exist, // (*) 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_SCRAP4 ||
m_type == OBJECT_SCRAP5 || m_type == OBJECT_SCRAP5 ||
m_type == OBJECT_BULLET || 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<int>(ObjectInterfaceType::Damageable)] = true;
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Destroyable)] = true; m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Destroyable)] = true;
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Fragile)] = true; m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Fragile)] = true;
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Shielded)] = false; m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Shielded)] = false;
} }
else if( m_type == OBJECT_HUMAN || else if (m_type == OBJECT_HUMAN ||
m_type == OBJECT_MOBILEfa || m_type == OBJECT_MOBILEfa ||
m_type == OBJECT_MOBILEta || m_type == OBJECT_MOBILEta ||
m_type == OBJECT_MOBILEwa || m_type == OBJECT_MOBILEwa ||
@ -743,7 +760,6 @@ void COldObject::SetType(ObjectType type)
m_type == OBJECT_MOBILErr || m_type == OBJECT_MOBILErr ||
m_type == OBJECT_MOBILErs || m_type == OBJECT_MOBILErs ||
m_type == OBJECT_MOBILEsa || m_type == OBJECT_MOBILEsa ||
m_type == OBJECT_MOBILEtg ||
m_type == OBJECT_MOBILEft || m_type == OBJECT_MOBILEft ||
m_type == OBJECT_MOBILEtt || m_type == OBJECT_MOBILEtt ||
m_type == OBJECT_MOBILEwt || m_type == OBJECT_MOBILEwt ||
@ -761,12 +777,22 @@ void COldObject::SetType(ObjectType type)
m_type == OBJECT_ENERGY || m_type == OBJECT_ENERGY ||
m_type == OBJECT_LABO || m_type == OBJECT_LABO ||
m_type == OBJECT_NUCLEAR || m_type == OBJECT_NUCLEAR ||
m_type == OBJECT_PARA ) m_type == OBJECT_PARA ||
m_type == OBJECT_MOTHER )
{ {
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Damageable)] = true;
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Destroyable)] = true; m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Destroyable)] = true;
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Fragile)] = false; m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Fragile)] = false;
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Shielded)] = true; m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Shielded)] = true;
} }
else if (m_type == OBJECT_HUSTON ||
m_type == OBJECT_BASE )
{
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Damageable)] = true;
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Destroyable)] = false;
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Fragile)] = false;
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Shielded)] = false;
}
else else
{ {
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Destroyable)] = false; m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Destroyable)] = false;
@ -3330,3 +3356,63 @@ float COldObject::GetShieldFullRegenTime()
assert(false); assert(false);
return 0.0f; 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;
}

View File

@ -105,7 +105,9 @@ public:
~COldObject(); ~COldObject();
void Simplify() override; 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; bool EventProcess(const Event& event) override;
void UpdateMapping(); void UpdateMapping();
@ -321,6 +323,8 @@ public:
bool IsRepairable() override; bool IsRepairable() override;
float GetShieldFullRegenTime() override; float GetShieldFullRegenTime() override;
float GetLightningHitProbability() override;
protected: protected:
bool EventFrame(const Event &event); bool EventFrame(const Event &event);
void VirusFrame(float rTime); void VirusFrame(float rTime);

View File

@ -25,11 +25,6 @@ void COldObjectInterface::Simplify()
throw std::logic_error("Simplify: not implemented!"); 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) void COldObjectInterface::DeletePart(int part)
{ {
throw std::logic_error("DeletePart: not implemented!"); throw std::logic_error("DeletePart: not implemented!");

View File

@ -50,20 +50,12 @@ struct Character
Math::Vector posPower; // position of the battery Math::Vector posPower; // position of the battery
}; };
enum class ExplosionType
{
Bang = 1,
Burn = 2,
Water = 3,
};
class COldObjectInterface class COldObjectInterface
{ {
public: public:
virtual ~COldObjectInterface() {} virtual ~COldObjectInterface() {}
virtual void Simplify(); virtual void Simplify();
virtual bool ExplodeObject(ExplosionType type, float force = 1.0f);
virtual void DeletePart(int part); virtual void DeletePart(int part);
virtual void SetType(ObjectType type); virtual void SetType(ObjectType type);

View File

@ -1573,7 +1573,7 @@ bool CPhysics::EventFrame(const Event &event)
if ( m_bLand && m_fallingHeight != 0.0f ) // if fell if ( m_bLand && m_fallingHeight != 0.0f ) // if fell
{ {
float force = (m_fallingHeight - m_object->GetPosition().y) * m_fallDamageFraction; 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; m_fallingHeight = 0.0f;
} }
@ -1775,10 +1775,13 @@ void CPhysics::WaterFrame(float aTime, float rTime)
if ( !m_object->GetActive() ) return; if ( !m_object->GetActive() ) return;
if ( m_water->GetLava() || if (type == OBJECT_HUMAN && m_object->GetOption() != 0 ) // human without a helmet?)
(type == OBJECT_HUMAN && {
m_object->GetOption() != 0 ) || // human without a helmet? assert(m_object->Implements(ObjectInterfaceType::Destroyable));
type == OBJECT_MOBILEfa || dynamic_cast<CDestroyableObject*>(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_MOBILEta ||
type == OBJECT_MOBILEwa || type == OBJECT_MOBILEwa ||
type == OBJECT_MOBILEia || type == OBJECT_MOBILEia ||
@ -1803,9 +1806,12 @@ void CPhysics::WaterFrame(float aTime, float rTime)
type == OBJECT_MOBILEwt || type == OBJECT_MOBILEwt ||
type == OBJECT_MOBILEit || type == OBJECT_MOBILEit ||
type == OBJECT_MOBILEdr || 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<CDestroyableObject*>(m_object)->DestroyObject(DestructionType::ExplosionWater);
}
} }
} }
@ -2697,91 +2703,78 @@ bool CPhysics::ExploOther(ObjectType iType,
{ {
JostleObject(pObj, 1.0f); // shakes the object JostleObject(pObj, 1.0f); // shakes the object
if ( force > 50.0f && if (pObj->Implements(ObjectInterfaceType::Fragile))
(oType == OBJECT_FRET ||
oType == OBJECT_METAL ) )
{ {
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<CDamageableObject*>(pObj)->DamageObject(damageType);
}
} }
if ( force > 50.0f && if ( force > 25.0f )
(oType == OBJECT_POWER ||
oType == OBJECT_ATOMIC ) )
{ {
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<CDamageableObject*>(pObj)->DamageObject(DamageType::Collision, force/400.0f);
}
if ( force > 25.0f && if (oType == OBJECT_MOBILEwa ||
(oType == OBJECT_STONE || oType == OBJECT_MOBILEta ||
oType == OBJECT_URANIUM ) ) oType == OBJECT_MOBILEfa ||
{ oType == OBJECT_MOBILEia ||
m_engine->GetPyroManager()->Create(Gfx::PT_FRAGT, pObj); // total destruction oType == OBJECT_MOBILEwc ||
} oType == OBJECT_MOBILEtc ||
oType == OBJECT_MOBILEfc ||
if ( force > 25.0f && oType == OBJECT_MOBILEic ||
(oType == OBJECT_DERRICK || oType == OBJECT_MOBILEwi ||
oType == OBJECT_FACTORY || oType == OBJECT_MOBILEti ||
oType == OBJECT_STATION || oType == OBJECT_MOBILEfi ||
oType == OBJECT_CONVERT || oType == OBJECT_MOBILEii ||
oType == OBJECT_REPAIR || oType == OBJECT_MOBILEws ||
oType == OBJECT_DESTROYER|| oType == OBJECT_MOBILEts ||
oType == OBJECT_TOWER || oType == OBJECT_MOBILEfs ||
oType == OBJECT_RESEARCH || oType == OBJECT_MOBILEis ||
oType == OBJECT_RADAR || oType == OBJECT_MOBILErt ||
oType == OBJECT_INFO || oType == OBJECT_MOBILErc ||
oType == OBJECT_ENERGY || oType == OBJECT_MOBILErr ||
oType == OBJECT_LABO || oType == OBJECT_MOBILErs ||
oType == OBJECT_NUCLEAR || oType == OBJECT_MOBILEsa ||
oType == OBJECT_PARA || oType == OBJECT_MOBILEwt ||
oType == OBJECT_SAFE || oType == OBJECT_MOBILEtt ||
oType == OBJECT_HUSTON ) ) // building? oType == OBJECT_MOBILEft ||
{ oType == OBJECT_MOBILEit ||
pObj->ExplodeObject(ExplosionType::Bang, force/400.0f); oType == OBJECT_MOBILEdr ||
} oType == OBJECT_APOLLO2 ) // vehicle?
{
if ( force > 25.0f && assert(pObj->Implements(ObjectInterfaceType::Damageable));
(oType == OBJECT_MOBILEwa || dynamic_cast<CDamageableObject*>(pObj)->DamageObject(DamageType::Collision, force/200.0f);
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
} }
return false; return false;
@ -2794,118 +2787,99 @@ bool CPhysics::ExploOther(ObjectType iType,
int CPhysics::ExploHimself(ObjectType iType, ObjectType oType, float force) int CPhysics::ExploHimself(ObjectType iType, ObjectType oType, float force)
{ {
if (!m_object->Implements(ObjectInterfaceType::Damageable)) return 1;
if ( force > 10.0f && // TODO: CExplosiveObject? derrives from CFragileObject
(oType == OBJECT_TNT || float destructionForce = -1.0f; // minimal force required to destroy an object using this explosive, default: not explosive
oType == OBJECT_MOBILEtg ) ) 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; dynamic_cast<CDamageableObject*>(m_object)->DamageObject(DamageType::Explosive);
if ( iType == OBJECT_HUMAN ) type = Gfx::PT_DEADG;
else type = Gfx::PT_EXPLOT;
m_engine->GetPyroManager()->Create(type, m_object); // total destruction
return 2; return 2;
} }
if ( force > 0.0f && if ( force > 25.0f )
oType == OBJECT_BOMB )
{ {
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; if ( oType == OBJECT_DERRICK ||
} oType == OBJECT_FACTORY ||
else if ( iType == OBJECT_ANT || oType == OBJECT_STATION ||
iType == OBJECT_SPIDER || oType == OBJECT_CONVERT ||
iType == OBJECT_BEE ) oType == OBJECT_REPAIR ||
{ oType == OBJECT_DESTROYER||
type = Gfx::PT_EXPLOO; oType == OBJECT_TOWER ||
} oType == OBJECT_RESEARCH ||
else oType == OBJECT_RADAR ||
{ oType == OBJECT_INFO ||
type = Gfx::PT_EXPLOT; oType == OBJECT_ENERGY ||
} oType == OBJECT_LABO ||
m_engine->GetPyroManager()->Create(type, m_object); // total destruction oType == OBJECT_NUCLEAR ||
return 2; 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 && if ( dynamic_cast<CDamageableObject*>(m_object)->DamageObject(DamageType::Collision, force) ) return 2;
(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;
} }
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; return 1;

View File

@ -46,6 +46,7 @@
#include "object/auto/autobase.h" #include "object/auto/autobase.h"
#include "object/auto/autofactory.h" #include "object/auto/autofactory.h"
#include "object/interface/destroyable_object.h"
#include "object/interface/programmable_object.h" #include "object/interface/programmable_object.h"
#include "object/interface/task_executor_object.h" #include "object/interface/task_executor_object.h"
#include "object/interface/trace_drawing_object.h" #include "object/interface/trace_drawing_object.h"
@ -886,25 +887,19 @@ bool CScriptFunctions::rTakeOff(CBotVar* thisclass, CBotVar* var, CBotVar* resul
return true; return true;
} }
// Compilation of the instruction "delete(rank[, exploType[, force]])". // Compilation of the instruction "delete(rank[, exploType])".
CBotTypResult CScriptFunctions::cDelete(CBotVar* &var, void* user) CBotTypResult CScriptFunctions::cDelete(CBotVar* &var, void* user)
{ {
if ( var == 0 ) return CBotTypResult(CBotErrLowParam); if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); if ( var->GetType() != CBotTypInt ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext(); var = var->GetNext();
if ( var != 0 ) if ( var != 0 )
{ {
if ( var->GetType() != CBotTypInt ) return CBotTypResult(CBotErrBadNum); if ( var->GetType() != CBotTypInt ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext(); var = var->GetNext();
if ( var != 0 )
{
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
}
} }
if ( var != 0 ) return CBotTypResult(CBotErrOverParam); if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
@ -912,23 +907,18 @@ CBotTypResult CScriptFunctions::cDelete(CBotVar* &var, void* user)
return CBotTypResult(CBotTypFloat); return CBotTypResult(CBotTypFloat);
} }
// Instruction "delete(rank[, exploType[, force]])". // Instruction "delete(rank[, exploType])".
bool CScriptFunctions::rDelete(CBotVar* var, CBotVar* result, int& exception, void* user) bool CScriptFunctions::rDelete(CBotVar* var, CBotVar* result, int& exception, void* user)
{ {
int exploType = 0; int rank;
float force = 1.0f; DestructionType exploType = DestructionType::Explosion;
int rank = var->GetValInt(); rank = var->GetValInt();
var->GetNext(); var->GetNext();
if ( var != 0 ) if ( var != 0 )
{ {
exploType = var->GetValInt(); exploType = static_cast<DestructionType>(var->GetValInt());
var->GetNext();
if ( var != 0 )
{
force = var->GetValFloat();
}
} }
CObject* obj = CObjectManager::GetInstancePointer()->GetObjectById(rank); CObject* obj = CObjectManager::GetInstancePointer()->GetObjectById(rank);
@ -938,9 +928,9 @@ bool CScriptFunctions::rDelete(CBotVar* var, CBotVar* result, int& exception, vo
} }
else else
{ {
if ( exploType != 0 ) if ( exploType != DestructionType::NoEffect && obj->Implements(ObjectInterfaceType::Destroyable) )
{ {
obj->ExplodeObject(static_cast<ExplosionType>(exploType), force); dynamic_cast<CDestroyableObject*>(obj)->DestroyObject(static_cast<DestructionType>(exploType));
} }
else else
{ {
@ -3624,10 +3614,11 @@ void CScriptFunctions::Init()
CBotProgram::DefineNum("FilterEnemy", FILTER_ENEMY); CBotProgram::DefineNum("FilterEnemy", FILTER_ENEMY);
CBotProgram::DefineNum("FilterNeutral", FILTER_NEUTRAL); CBotProgram::DefineNum("FilterNeutral", FILTER_NEUTRAL);
CBotProgram::DefineNum("ExplosionNone", 0); CBotProgram::DefineNum("DestructionNone", static_cast<int>(DestructionType::NoEffect));
CBotProgram::DefineNum("ExplosionBang", static_cast<int>(ExplosionType::Bang)); CBotProgram::DefineNum("DestructionExplosion", static_cast<int>(DestructionType::Explosion));
CBotProgram::DefineNum("ExplosionBurn", static_cast<int>(ExplosionType::Burn)); CBotProgram::DefineNum("DestructionExplosionWater", static_cast<int>(DestructionType::ExplosionWater));
CBotProgram::DefineNum("ExplosionWater", static_cast<int>(ExplosionType::Water)); CBotProgram::DefineNum("DestructionBurn", static_cast<int>(DestructionType::Burn));
CBotProgram::DefineNum("DestructionDrowned", static_cast<int>(DestructionType::Drowned));
CBotProgram::DefineNum("ResultNotEnded", ERR_MISSION_NOTERM); CBotProgram::DefineNum("ResultNotEnded", ERR_MISSION_NOTERM);
CBotProgram::DefineNum("ResultLost", INFO_LOST); CBotProgram::DefineNum("ResultLost", INFO_LOST);