Compare commits

...

10 Commits

35 changed files with 3331 additions and 2677 deletions

View File

@ -246,11 +246,6 @@ set(BASE_SOURCES
graphics/engine/particle.h graphics/engine/particle.h
graphics/engine/planet.cpp graphics/engine/planet.cpp
graphics/engine/planet.h graphics/engine/planet.h
graphics/engine/pyro.cpp
graphics/engine/pyro.h
graphics/engine/pyro_manager.cpp
graphics/engine/pyro_manager.h
graphics/engine/pyro_type.h
graphics/engine/terrain.cpp graphics/engine/terrain.cpp
graphics/engine/terrain.h graphics/engine/terrain.h
graphics/engine/text.cpp graphics/engine/text.cpp
@ -283,6 +278,24 @@ set(BASE_SOURCES
graphics/opengl/glframebuffer.h graphics/opengl/glframebuffer.h
graphics/opengl/glutil.cpp graphics/opengl/glutil.cpp
graphics/opengl/glutil.h graphics/opengl/glutil.h
graphics/pyro/pyro.cpp
graphics/pyro/pyro.h
graphics/pyro/pyro_manager.cpp
graphics/pyro/pyro_manager.h
graphics/pyro/pyro_type_burn.cpp
graphics/pyro/pyro_type_dead.cpp
graphics/pyro/pyro_type_egg.cpp
graphics/pyro/pyro_type_fall.cpp
graphics/pyro/pyro_type_finding.cpp
graphics/pyro/pyro_type_flag_create.cpp
graphics/pyro/pyro_type_flag_delete.cpp
graphics/pyro/pyro_type_frag_explo_or_shot.cpp
graphics/pyro/pyro_type_fragv.cpp
graphics/pyro/pyro_type_reset.cpp
graphics/pyro/pyro_type_spider.cpp
graphics/pyro/pyro_type_squash.cpp
graphics/pyro/pyro_type_waypoint_hit.cpp
graphics/pyro/pyro_type_win_lost.cpp
level/build_type.h level/build_type.h
level/level_category.cpp level/level_category.cpp
level/level_category.h level/level_category.h

View File

@ -44,7 +44,6 @@
#include "graphics/engine/oldmodelmanager.h" #include "graphics/engine/oldmodelmanager.h"
#include "graphics/engine/particle.h" #include "graphics/engine/particle.h"
#include "graphics/engine/planet.h" #include "graphics/engine/planet.h"
#include "graphics/engine/pyro_manager.h"
#include "graphics/engine/terrain.h" #include "graphics/engine/terrain.h"
#include "graphics/engine/text.h" #include "graphics/engine/text.h"
#include "graphics/engine/water.h" #include "graphics/engine/water.h"
@ -52,6 +51,8 @@
#include "graphics/model/model_mesh.h" #include "graphics/model/model_mesh.h"
#include "graphics/model/model_shadow_spot.h" #include "graphics/model/model_shadow_spot.h"
#include "graphics/pyro/pyro_manager.h"
#include "level/robotmain.h" #include "level/robotmain.h"
#include "math/geometry.h" #include "math/geometry.h"

File diff suppressed because it is too large Load Diff

View File

@ -1,65 +0,0 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.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
*/
/**
* \file graphics/engine/pyro_type.h
* \brief PyroType enum
*/
#pragma once
namespace Gfx
{
/**
* \enum PyroType
* \brief Type of pyro effect
*/
enum PyroType
{
PT_NULL = 0,
PT_FRAGT = 1, //! < fragmentation of technical object
PT_FRAGO = 2, //! < fragmentation of organic object
PT_FRAGW = 4, //! < fragmentation of object under water
PT_EXPLOT = 5, //! < explosion of technical object
PT_EXPLOO = 6, //! < explosion of organic object
PT_EXPLOW = 8, //! < explosion of object under water
PT_SHOTT = 9, //! < hit technical object
PT_SHOTH = 10, //! < hit human
PT_SHOTM = 11, //! < hit queen
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
PT_SPIDER = 16, //! < spider explosion
PT_FALL = 17, //! < cargo falling
PT_WPCHECK = 18, //! < indicator reaches
PT_FLCREATE = 19, //! < flag create
PT_FLDELETE = 20, //! < flag destroy
PT_RESET = 21, //! < reset position of the object
PT_WIN = 22, //! < fireworks
PT_LOST = 23, //! < black smoke
PT_DEADG = 24, //! < shooting death
PT_DEADW = 25, //! < drowning death
PT_FINDING = 26, //! < object discovered
PT_FRAGV = 27, //! < fragmentation of plant object
PT_SQUASH = 28, //! < flattening plants
};
} // namespace Gfx

480
src/graphics/pyro/pyro.cpp Normal file
View File

@ -0,0 +1,480 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.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
*/
#include "graphics/pyro/pyro.h"
#include "app/app.h"
#include "common/logger.h"
#include "graphics/engine/lightman.h"
#include "graphics/engine/particle.h"
#include "graphics/engine/terrain.h"
#include "level/robotmain.h"
#include "math/geometry.h"
#include "object/object_manager.h"
#include "object/old_object.h"
#include "object/motion/motionhuman.h"
#include "sound/sound.h"
// Graphics module namespace
namespace Gfx
{
CPyro::CPyro(CObject *obj)
{
m_object = obj;
m_engine = CEngine::GetInstancePointer();
m_main = CRobotMain::GetInstancePointer();
m_terrain = m_main->GetTerrain();
m_camera = m_main->GetCamera();
m_particle = m_engine->GetParticle();
m_lightMan = m_engine->GetLightManager();
m_sound = CApplication::GetInstancePointer()->GetSound();
}
CPyro::~CPyro()
{
}
void CPyro::DeleteObject()
{
if ( m_lightRank != -1 )
{
m_lightMan->DeleteLight(m_lightRank);
m_lightRank = -1;
}
}
bool CPyro::Create()
{
ObjectType oType = m_object->GetType();
int objRank = m_object->GetObjectRank(0);
if (objRank == -1) return false;
Math::Vector min, max;
m_engine->GetObjectBBox(objRank, min, max);
Math::Vector pos = m_object->GetPosition();
for (const auto& crashSphere : m_object->GetAllCrashSpheres())
{
m_crashSpheres.push_back(crashSphere.sphere);
}
// Calculates the size of the effect.
if ( oType == OBJECT_ANT ||
oType == OBJECT_BEE ||
oType == OBJECT_WORM ||
oType == OBJECT_SPIDER )
{
m_size = 40.0f;
}
else
{
m_size = Math::Distance(min, max)*2.0f;
if ( m_size < 4.0f ) m_size = 4.0f;
if ( m_size > 80.0f ) m_size = 80.0f;
}
if ( oType == OBJECT_TNT ||
oType == OBJECT_BOMB )
{
m_size *= 2.0f;
}
m_pos = pos+(min+max)/2.0f;
m_progress = 0.0f;
m_speed = 1.0f/20.0f; m_time = 0.0f;
m_lastParticle = 0.0f;
m_lastParticleSmoke = 0.0f;
m_lightRank = -1;
if ( oType == OBJECT_TEEN28 ||
oType == OBJECT_TEEN31 )
{
m_pos.y = pos.y+1.0f;
}
// Seeking the position of the battery.
CObject* power = nullptr;
if (m_object->Implements(ObjectInterfaceType::Powered))
power = dynamic_cast<CPoweredObject&>(*m_object).GetPower();
if (power == nullptr)
{
m_power = false;
}
else
{
m_power = true;
pos = power->GetPosition();
pos.y += 1.0f;
Math::Matrix* mat = m_object->GetWorldMatrix(0);
m_posPower = Math::Transform(*mat, pos);
}
if ( oType == OBJECT_POWER ||
oType == OBJECT_ATOMIC ||
oType == OBJECT_URANIUM ||
oType == OBJECT_TNT ||
oType == OBJECT_BOMB )
{
m_power = true;
m_posPower = m_pos;
m_posPower.y += 1.0f;
m_pos = m_posPower;
}
if ( oType == OBJECT_STATION )
{
m_power = true;
Math::Matrix* mat = m_object->GetWorldMatrix(0);
m_posPower = Math::Transform(*mat, Math::Vector(-15.0f, 7.0f, 0.0f));
m_pos = m_posPower;
}
if ( oType == OBJECT_ENERGY )
{
m_power = true;
Math::Matrix* mat = m_object->GetWorldMatrix(0);
m_posPower = Math::Transform(*mat, Math::Vector(-7.0f, 6.0f, 0.0f));
m_pos = m_posPower;
}
if ( oType == OBJECT_NUCLEAR )
{
m_power = true;
m_posPower = m_pos;
}
if ( oType == OBJECT_PARA )
{
m_power = true;
m_posPower = m_pos;
}
AfterCreate();
return true;
}
void CPyro::AfterCreate()
{
}
bool CPyro::EventProcess(const Event &event)
{
if (event.type != EVENT_FRAME) return true;
if (m_engine->GetPause()) return true;
m_time += event.rTime;
m_progress += event.rTime*m_speed;
if (m_soundChannel != -1 && m_object != nullptr)
{
Math::Vector pos = m_object->GetPosition();
m_sound->Position(m_soundChannel, pos);
if (m_lightRank != -1)
{
pos.y += m_lightHeight;
m_lightMan->SetLightPos(m_lightRank, pos);
}
}
UpdateEffect();
if (m_lightRank != -1)
LightOperFrame();
return true;
}
void CPyro::UpdateEffect()
{
}
Error CPyro::IsEnded()
{
// End of the pyrotechnic effect?
if ( m_progress < 1.0f ) return ERR_CONTINUE;
return ERR_STOP;
}
void CPyro::AfterEnd()
{
}
void CPyro::CutObjectLink(CObject* obj)
{
if (m_object == obj)
m_object = nullptr;
}
void CPyro::CreateLight(Math::Vector pos, float height)
{
if (!m_engine->GetLightMode()) return;
m_lightHeight = height;
Gfx::Light light;
light.type = LIGHT_SPOT;
light.ambient = Gfx::Color(0.0f, 0.0f, 0.0f);
light.position = Math::Vector(pos.x, pos.y+height, pos.z);
light.direction = Math::Vector(0.0f, -1.0f, 0.0f); // against the bottom
light.spotIntensity = 1.0f;
light.attenuation0 = 1.0f;
light.attenuation1 = 0.0f;
light.attenuation2 = 0.0f;
light.spotAngle = Math::PI/4.0f;
m_lightRank = m_lightMan->CreateLight();
m_lightMan->SetLight(m_lightRank, light);
m_lightMan->SetLightIntensity(m_lightRank, 0.0f);
// Only illuminates the objects on the ground.
m_lightMan->SetLightIncludeType(m_lightRank, ENG_OBJTYPE_TERRAIN);
}
void CPyro::DeleteObject(bool primary, bool secondary)
{
if (m_object == nullptr) return;
ObjectType type = m_object->GetType();
if ( secondary &&
type != OBJECT_FACTORY &&
type != OBJECT_NUCLEAR &&
type != OBJECT_ENERGY )
{
if (m_object->Implements(ObjectInterfaceType::Powered))
{
CPoweredObject& poweredObject = dynamic_cast<CPoweredObject&>(*m_object);
CObject* sub = poweredObject.GetPower();
if (sub != nullptr)
{
CObjectManager::GetInstancePointer()->DeleteObject(sub);
poweredObject.SetPower(nullptr);
}
}
if (m_object->Implements(ObjectInterfaceType::Carrier))
{
CCarrierObject& carrierObject = dynamic_cast<CCarrierObject&>(*m_object);
CObject* sub = carrierObject.GetCargo();
if (sub != nullptr)
{
CObjectManager::GetInstancePointer()->DeleteObject(sub);
carrierObject.SetCargo(nullptr);
}
}
}
if (primary)
{
if (m_object->Implements(ObjectInterfaceType::Transportable))
{
// TODO: this should be handled in the object's destructor
CObject* transporter = dynamic_cast<CTransportableObject&>(*m_object).GetTransporter();
if (transporter != nullptr)
{
if (m_object->Implements(ObjectInterfaceType::Powered))
{
CObject* sub = dynamic_cast<CPoweredObject&>(*m_object).GetPower();
if (sub != nullptr) // is there a battery?
sub->SetScaleY(1.0f - m_progress); // complete flattening
}
}
if (transporter->Implements(ObjectInterfaceType::Carrier))
{
CCarrierObject& carrier = dynamic_cast<CCarrierObject&>(*transporter);
if (carrier.GetCargo() == m_object)
carrier.SetCargo(nullptr);
}
}
CObjectManager::GetInstancePointer()->DeleteObject(m_object);
m_object = nullptr;
}
}
void CPyro::CreateTriangle(CObject* obj, ObjectType oType, int part, float maxHParticleSpeed, float maxVParticleSpeed, float minParticleMass, float maxParticleMass, float overridePercent)
{
int objRank = obj->GetObjectRank(part);
if (objRank == -1) return;
int total = m_engine->GetObjectTotalTriangles(objRank);
float percent = 0.10f;
if (total < 50) percent = 0.25f;
if (total < 20) percent = 0.50f;
if ( overridePercent >= 0 )
{
percent = overridePercent;
}
if (oType == OBJECT_POWER ||
oType == OBJECT_ATOMIC ||
oType == OBJECT_URANIUM ||
oType == OBJECT_TNT ||
oType == OBJECT_BOMB ||
oType == OBJECT_TEEN28)
{
percent = 0.75f;
}
else if (oType == OBJECT_MOBILEtg)
{
percent = 0.50f;
}
std::vector<EngineTriangle> buffer;
total = m_engine->GetPartialTriangles(objRank, percent, 100, buffer);
for (int i = 0; i < total; i++)
{
Math::Vector p1, p2, p3;
p1.x = buffer[i].triangle[0].coord.x;
p1.y = buffer[i].triangle[0].coord.y;
p1.z = buffer[i].triangle[0].coord.z;
p2.x = buffer[i].triangle[1].coord.x;
p2.y = buffer[i].triangle[1].coord.y;
p2.z = buffer[i].triangle[1].coord.z;
p3.x = buffer[i].triangle[2].coord.x;
p3.y = buffer[i].triangle[2].coord.y;
p3.z = buffer[i].triangle[2].coord.z;
float h;
h = Math::Distance(p1, p2);
if ( h > 5.0f )
{
p2.x = p1.x+((p2.x-p1.x)*5.0f/h);
p2.y = p1.y+((p2.y-p1.y)*5.0f/h);
p2.z = p1.z+((p2.z-p1.z)*5.0f/h);
}
h = Math::Distance(p2, p3);
if ( h > 5.0f )
{
p3.x = p2.x+((p3.x-p2.x)*5.0f/h);
p3.y = p2.y+((p3.y-p2.y)*5.0f/h);
p3.z = p2.z+((p3.z-p2.z)*5.0f/h);
}
h = Math::Distance(p3, p1);
if ( h > 5.0f )
{
p1.x = p3.x+((p1.x-p3.x)*5.0f/h);
p1.y = p3.y+((p1.y-p3.y)*5.0f/h);
p1.z = p3.z+((p1.z-p3.z)*5.0f/h);
}
buffer[i].triangle[0].coord.x = p1.x;
buffer[i].triangle[0].coord.y = p1.y;
buffer[i].triangle[0].coord.z = p1.z;
buffer[i].triangle[1].coord.x = p2.x;
buffer[i].triangle[1].coord.y = p2.y;
buffer[i].triangle[1].coord.z = p2.z;
buffer[i].triangle[2].coord.x = p3.x;
buffer[i].triangle[2].coord.y = p3.y;
buffer[i].triangle[2].coord.z = p3.z;
Math::Vector offset;
offset.x = (buffer[i].triangle[0].coord.x+buffer[i].triangle[1].coord.x+buffer[i].triangle[2].coord.x)/3.0f;
offset.y = (buffer[i].triangle[0].coord.y+buffer[i].triangle[1].coord.y+buffer[i].triangle[2].coord.y)/3.0f;
offset.z = (buffer[i].triangle[0].coord.z+buffer[i].triangle[1].coord.z+buffer[i].triangle[2].coord.z)/3.0f;
buffer[i].triangle[0].coord.x -= offset.x;
buffer[i].triangle[1].coord.x -= offset.x;
buffer[i].triangle[2].coord.x -= offset.x;
buffer[i].triangle[0].coord.y -= offset.y;
buffer[i].triangle[1].coord.y -= offset.y;
buffer[i].triangle[2].coord.y -= offset.y;
buffer[i].triangle[0].coord.z -= offset.z;
buffer[i].triangle[1].coord.z -= offset.z;
buffer[i].triangle[2].coord.z -= offset.z;
Math::Vector speed;
float mass;
Math::Matrix* mat = obj->GetWorldMatrix(part);
Math::Vector pos = Math::Transform(*mat, offset);
speed.x = (Math::Rand()-0.5f)*2.0f*maxHParticleSpeed;
speed.z = (Math::Rand()-0.5f)*2.0f*maxHParticleSpeed;
speed.y = Math::Rand()*maxVParticleSpeed;
mass = Math::Rand()*(maxParticleMass-minParticleMass) + minParticleMass;
if ( oType == OBJECT_STONE ) speed *= 0.5f;
if ( oType == OBJECT_URANIUM ) speed *= 0.4f;
float duration = Math::Rand()*3.0f+3.0f;
m_particle->CreateFrag(pos, speed, &buffer[i], PARTIFRAG,
duration, mass, 0.5f);
}
}
void CPyro::LightOperFlush()
{
m_lightOper.clear();
}
void CPyro::LightOperAdd(float progress, float intensity, float r, float g, float b)
{
PyroLightOper lightOper;
lightOper.progress = progress;
lightOper.intensity = intensity;
lightOper.color.r = r;
lightOper.color.g = g;
lightOper.color.b = b;
m_lightOper.push_back(lightOper);
}
void CPyro::LightOperFrame()
{
for (std::size_t i = 1; i < m_lightOper.size(); i++)
{
if ( m_progress < m_lightOper[i].progress )
{
float progress = (m_progress-m_lightOper[i-1].progress) / (m_lightOper[i].progress-m_lightOper[i-1].progress);
float intensity = m_lightOper[i-1].intensity + (m_lightOper[i].intensity-m_lightOper[i-1].intensity)*progress;
Gfx::Color color;
color.r = m_lightOper[i-1].color.r + (m_lightOper[i].color.r-m_lightOper[i-1].color.r)*progress;
color.g = m_lightOper[i-1].color.g + (m_lightOper[i].color.g-m_lightOper[i-1].color.g)*progress;
color.b = m_lightOper[i-1].color.b + (m_lightOper[i].color.b-m_lightOper[i-1].color.b)*progress;
m_lightMan->SetLightIntensity(m_lightRank, intensity);
m_lightMan->SetLightColor(m_lightRank, color);
break;
}
}
}
} // namespace Gfx

View File

@ -18,7 +18,7 @@
*/ */
/** /**
* \file graphics/engine/pyro.h * \file graphics/pyro/pyro.h
* \brief Fire effect rendering - CPyro class * \brief Fire effect rendering - CPyro class
*/ */
@ -29,8 +29,6 @@
#include "graphics/core/color.h" #include "graphics/core/color.h"
#include "graphics/engine/pyro_type.h"
#include "math/sphere.h" #include "math/sphere.h"
#include "object/object_type.h" #include "object/object_type.h"
@ -65,67 +63,47 @@ protected:
friend class CPyroManager; friend class CPyroManager;
//! Creates pyrotechnic effect //! Creates pyrotechnic effect
bool Create(PyroType type, CObject* obj, float force); bool Create();
//! Destroys the object //! Destroys the object
void DeleteObject(); void DeleteObject();
virtual void AfterCreate();
virtual void UpdateEffect();
virtual void AfterEnd();
public: public:
CPyro(); // should only be called by CPyroManager CPyro(CObject *obj);
~CPyro(); virtual ~CPyro();
//! Indicates whether the pyrotechnic effect is complete //! Indicates whether the pyrotechnic effect is complete
Error IsEnded(); virtual Error IsEnded();
//! Indicates that the object binds to the effect no longer exists, without deleting it //! Indicates that the object binds to the effect no longer exists, without deleting it
void CutObjectLink(CObject* obj); void CutObjectLink(CObject* obj);
//! Management of an event //! Management of an event
bool EventProcess(const Event& event); virtual bool EventProcess(const Event& event);
protected: protected:
//! Displays the error or eventual information
//! Information can be linked to the destruction of an insect, a vehicle or building
void DisplayError(PyroType type, CObject* obj);
//! Creates light to accompany a pyrotechnic effect //! Creates light to accompany a pyrotechnic effect
void CreateLight(Math::Vector pos, float height); void CreateLight(Math::Vector pos, float height);
//! Removes the binding to a pyrotechnic effect //! Removes the binding to a pyrotechnic effect
void DeleteObject(bool primary, bool secondary); void DeleteObject(bool primary, bool secondary);
//! Creates an explosion with triangular form of particles //! Creates an explosion with triangular form of particles
void CreateTriangle(CObject* obj, ObjectType oType, int part); void CreateTriangle(CObject* obj, ObjectType oType, int part,
float maxHParticleSpeed = 15.0f,
//! Starts the explosion of a vehicle float maxVParticleSpeed = 30.0f,
void ExploStart(); float minParticleMass = 15.0f,
//! Ends the explosion of a vehicle float maxParticleMass = 25.0f,
void ExploTerminate(); float overridePercent = -1);
//! Starts a vehicle fire
void BurnStart();
//! Adds a part move
void BurnAddPart(int part, Math::Vector pos, Math::Vector angle);
//! Advances of a vehicle fire
void BurnProgress();
//! Indicates whether a part should be retained
bool BurnIsKeepPart(int part);
//! Ends the fire of an insect or a vehicle
void BurnTerminate();
//! Start of an object freight falling
void FallStart();
//! Seeks an object to explode by the falling ball of bees
CObject* FallSearchBeeExplo();
//! Fall of an object's freight
void FallProgress(float rTime);
//! Indicates whether the fall is over
Error FallIsEnded();
//! Empty the table of operations of animation of light //! Empty the table of operations of animation of light
void LightOperFlush(); void LightOperFlush();
//! Adds an animation operation of the light //! Adds an animation operation of the light
void LightOperAdd(float progress, float intensity, float r, float g, float b); void LightOperAdd(float progress, float intensity, float r, float g, float b);
//! Updates the associated light //! Updates the associated light
void LightOperFrame(float rTime); void LightOperFrame();
protected: protected:
CEngine* m_engine = nullptr; CEngine* m_engine = nullptr;
@ -140,8 +118,6 @@ protected:
Math::Vector m_pos; // center of the effect Math::Vector m_pos; // center of the effect
Math::Vector m_posPower; // center of the battery Math::Vector m_posPower; // center of the battery
bool m_power = false; // battery exists? bool m_power = false; // battery exists?
PyroType m_type = PT_NULL;
float m_force = 0.0f;
float m_size = 0.0f; float m_size = 0.0f;
float m_progress = 0.0f; float m_progress = 0.0f;
float m_speed = 0.0f; float m_speed = 0.0f;
@ -185,5 +161,185 @@ protected:
float m_resetAngle = 0.0f; float m_resetAngle = 0.0f;
}; };
class CFlagCreatePyro : public CPyro
{
public:
CFlagCreatePyro(CObject *pObj);
void AfterCreate() override;
void UpdateEffect() override;
void AfterEnd() override;
};
class CFlagDeletePyro : public CPyro
{
public:
CFlagDeletePyro(CObject *pObj);
void AfterCreate() override;
void UpdateEffect() override;
void AfterEnd() override;
};
class CWaypointHitPyro : public CPyro
{
public:
CWaypointHitPyro(CObject *obj);
void AfterCreate() override;
void UpdateEffect() override;
void AfterEnd() override;
};
class CFallPyro : public CPyro
{
public:
CFallPyro(CObject *obj);
//! Start of an object freight falling
void AfterCreate() override;
//! Seeks an object to explode by the falling ball of bees
CObject* FallSearchBeeExplo();
//! Fall of an object's freight
void FallProgress(float rTime);
//! Indicates whether the fall is over
Error IsEnded() override;
//! Makes a sound and unlocks the object after fall is done
void AfterEnd() override;
bool EventProcess(const Event&) override;
};
class CResetPyro : public CPyro
{
public:
CResetPyro(CObject *obj);
void AfterCreate() override;
void UpdateEffect() override;
void AfterEnd() override;
};
class CLostPyro : public CPyro
{
public:
CLostPyro(CObject *obj);
Error IsEnded() override;
void UpdateEffect() override;
};
class CWinPyro : public CPyro
{
public:
CWinPyro(CObject *obj);
Error IsEnded() override;
void UpdateEffect() override;
};
class CSpiderPyro : public CPyro
{
public:
CSpiderPyro(CObject *obj);
bool EventProcess(const Event& event) override;
void AfterCreate() override;
};
class CEggPyro : public CPyro
{
public:
CEggPyro(CObject *obj);
bool EventProcess(const Event& event) override;
void AfterCreate() override;
};
class CDeadGPyro : public CPyro
{
public:
CDeadGPyro(CObject *obj);
void AfterCreate() override;
};
class CDeadWPyro : public CPyro
{
public:
CDeadWPyro(CObject *obj);
void AfterCreate() override;
};
class CFindingPyro : public CPyro
{
public:
CFindingPyro(CObject *obj);
void AfterCreate() override;
void UpdateEffect() override;
};
class CSquashPyro : public CPyro
{
public:
CSquashPyro(CObject *obj);
void AfterCreate() override;
void UpdateEffect() override;
void AfterEnd() override;
};
class CFragVPyro : public CPyro
{
public:
CFragVPyro(CObject *obj);
bool EventProcess(const Event& event) override;
void AfterCreate() override;
};
class CBurnPyro : public CPyro
{
bool m_organicBurn;
public:
CBurnPyro(CObject *obj);
void AfterCreate() override;
void UpdateEffect() override;
//! Starts a vehicle fire
void BurnStart();
//! Adds a part move
void BurnAddPart(int part, Math::Vector pos, Math::Vector angle);
//! Advances of a vehicle fire
void BurnProgress();
//! Indicates whether a part should be retained
bool BurnIsKeepPart(int part);
//! Ends the fire of an insect or a vehicle
void AfterEnd() override;
};
/**
* \enum FragExploOrShotPyroType
* \brief Type of CFragExploOrShotPyro
*/
enum FragExploOrShotPyroType
{
PT_FRAGT, //! < fragmentation of technical object
PT_FRAGO, //! < fragmentation of organic object
PT_FRAGW, //! < fragmentation of object under water
PT_EXPLOT, //! < explosion of technical object
PT_EXPLOO, //! < explosion of organic object
PT_EXPLOW, //! < explosion of object under water
PT_SHOTT, //! < hit technical object
PT_SHOTH, //! < hit human
PT_SHOTM, //! < hit queen
PT_SHOTW, //! < hit under water (TODO: check if unused)
};
class CFragExploOrShotPyro : public CPyro
{
float m_force;
FragExploOrShotPyroType m_type;
public:
CFragExploOrShotPyro(FragExploOrShotPyroType type, CObject *obj, float force = 1.0f);
void AfterCreate() override;
bool EventProcess(const Event& event) override;
void UpdateEffect() override;
//! Starts the explosion of a vehicle
void ExploStart();
//! Ends the explosion of a vehicle
void AfterEnd() override;
};
} // namespace Gfx } // namespace Gfx

View File

@ -17,11 +17,13 @@
* along with this program. If not, see http://gnu.org/licenses * along with this program. If not, see http://gnu.org/licenses
*/ */
#include "graphics/engine/pyro_manager.h" #include "graphics/pyro/pyro_manager.h"
#include "common/make_unique.h" #include "common/make_unique.h"
#include "graphics/engine/pyro.h" #include "graphics/pyro/pyro.h"
#include <assert.h>
namespace Gfx namespace Gfx
{ {
@ -33,10 +35,9 @@ Gfx::CPyroManager::CPyroManager()
CPyroManager::~CPyroManager() CPyroManager::~CPyroManager()
{} {}
void Gfx::CPyroManager::Create(PyroType type, CObject* obj, float force) void Gfx::CPyroManager::Create(CPyroUPtr pyroUPtr)
{ {
auto pyroUPtr = MakeUnique<CPyro>(); pyroUPtr->Create();
pyroUPtr->Create(type, obj, force);
m_pyros.insert(std::move(pyroUPtr)); m_pyros.insert(std::move(pyroUPtr));
} }
@ -70,6 +71,7 @@ void Gfx::CPyroManager::EventProcess(const Event& event)
} }
else else
{ {
(*it)->AfterEnd();
(*it)->DeleteObject(); (*it)->DeleteObject();
it = m_pyros.erase(it); it = m_pyros.erase(it);
} }

View File

@ -18,14 +18,12 @@
*/ */
/** /**
* \file graphics/engine/pyro_manager.h * \file graphics/pyro/pyro_manager.h
* \brief Manager for CPyro objects * \brief Manager for CPyro objects
*/ */
#pragma once #pragma once
#include "graphics/engine/pyro_type.h"
#include <memory> #include <memory>
#include <set> #include <set>
@ -44,7 +42,7 @@ public:
CPyroManager(); CPyroManager();
~CPyroManager(); ~CPyroManager();
void Create(PyroType type, CObject* obj, float force=1.0f); void Create(CPyroUPtr pyroUPtr);
void DeleteAll(); void DeleteAll();
void CutObjectLink(CObject* obj); void CutObjectLink(CObject* obj);

View File

@ -0,0 +1,749 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.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
*/
#include "graphics/engine/particle.h"
#include "graphics/engine/terrain.h"
#include "graphics/pyro/pyro.h"
#include "graphics/pyro/pyro_manager.h"
#include "level/robotmain.h"
#include "object/object.h"
#include "object/old_object.h"
#include "sound/sound.h"
using namespace Gfx;
CBurnPyro::CBurnPyro(CObject *obj)
: CPyro(obj)
, m_organicBurn(obj->GetType() == OBJECT_MOTHER ||
obj->GetType() == OBJECT_ANT ||
obj->GetType() == OBJECT_SPIDER ||
obj->GetType() == OBJECT_BEE ||
obj->GetType() == OBJECT_WORM ||
obj->GetType() == OBJECT_BULLET)
{}
void CBurnPyro::AfterCreate()
{
m_soundChannel = m_sound->Play(SOUND_BURN, m_pos, 1.0f, 1.0f, true);
m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 12.0f, SOPER_CONTINUE);
m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 5.0f, SOPER_STOP);
if (m_organicBurn)
{
m_sound->Play(SOUND_DEADi, m_pos);
m_sound->Play(SOUND_DEADi, m_engine->GetEyePt());
}
else
{
BurnStart();
}
m_speed = 1.0f/15.0f;
LightOperAdd(0.00f, 0.0f, 2.0f, 1.0f, 0.0f); // red-orange
LightOperAdd(0.30f, 1.0f, -0.8f, -0.8f, -0.8f); // dark gray
LightOperAdd(0.80f, 1.0f, -0.8f, -0.8f, -0.8f); // dark gray
LightOperAdd(1.00f, 0.0f, -0.8f, -0.8f, -0.8f); // dark gray
CreateLight(m_pos, 40.0f);
}
void CBurnPyro::UpdateEffect()
{
if ( m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
{
m_lastParticle = m_time;
float factor = m_size/25.0f; // 1 = standard size
Math::Vector pos = m_object->GetPosition();
pos.y -= m_object->GetCharacter()->height;
pos.x += (Math::Rand()-0.5f)*(4.0f+8.0f*m_progress)*factor;
pos.z += (Math::Rand()-0.5f)*(4.0f+8.0f*m_progress)*factor;
Math::Vector speed;
speed.x = 0.0f;
speed.z = 0.0f;
speed.y = 0.0f;
Math::Point dim;
dim.x = (Math::Rand()*2.5f+1.0f)*factor;
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, PARTIFLAME, 2.0f, 0.0f, 0.2f);
pos = m_object->GetPosition();
pos.y -= m_object->GetCharacter()->height;
pos.x += (Math::Rand()-0.5f)*(2.0f+4.0f*m_progress)*factor;
pos.z += (Math::Rand()-0.5f)*(2.0f+4.0f*m_progress)*factor;
speed.x = 0.0f;
speed.z = 0.0f;
speed.y = (Math::Rand()*5.0f*m_progress+3.0f)*factor;
dim.x = (Math::Rand()*2.0f+1.0f)*factor;
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, PARTIFLAME, 2.0f, 0.0f, 0.2f);
pos = m_object->GetPosition();
pos.y -= 2.0f;
pos.x += (Math::Rand()-0.5f)*5.0f*factor;
pos.z += (Math::Rand()-0.5f)*5.0f*factor;
speed.x = 0.0f;
speed.z = 0.0f;
speed.y = (6.0f+Math::Rand()*6.0f+m_progress*6.0f)*factor;
dim.x = (Math::Rand()*1.5f+1.0f+m_progress*3.0f)*factor;
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, PARTISMOKE3, 4.0f);
}
if ( !m_organicBurn )
{
BurnProgress();
}
else
{
Math::Vector speed;
speed.y = 0.0f;
speed.x = (Math::Rand()-0.5f)*m_progress*1.0f;
speed.z = (Math::Rand()-0.5f)*m_progress*1.0f;
if ( m_progress > 0.8f )
{
float prog = (m_progress-0.8f)/0.2f; // 0..1
speed.y = -prog*6.0f; // sinks into the ground
m_object->SetScale(1.0f-prog*0.5f);
}
m_object->SetLinVibration(speed);
}
}
void CBurnPyro::BurnStart()
{
m_burnType = m_object->GetType();
Math::Vector oPos = m_object->GetPosition();
m_burnFall = m_terrain->GetHeightToFloor(oPos, true);
m_object->Simplify();
m_object->SetLock(true); // ruin not usable yet
if ( m_object->Implements(ObjectInterfaceType::Controllable) && dynamic_cast<CControllableObject&>(*m_object).GetSelect() )
{
dynamic_cast<CControllableObject&>(*m_object).SetSelect(false); // deselects the object
m_camera->SetType(CAM_TYPE_EXPLO);
m_main->DeselectAll();
}
m_main->RemoveFromSelectionHistory(m_object);
for (int i = 0; i < OBJECTMAXPART; i++)
{
int objRank = m_object->GetObjectRank(i);
if (objRank == -1) continue;
// TODO: refactor later to material change
int oldBaseObjRank = m_engine->GetObjectBaseRank(objRank);
if (oldBaseObjRank != -1)
{
int newBaseObjRank = m_engine->CreateBaseObject();
m_engine->CopyBaseObject(oldBaseObjRank, newBaseObjRank);
m_engine->SetObjectBaseRank(objRank, newBaseObjRank);
m_engine->ChangeSecondTexture(objRank, "dirty04.png");
}
}
m_engine->LoadTexture("textures/dirty04.png");
m_burnPartTotal = 0;
Math::Vector pos, angle;
if ( m_burnType == OBJECT_DERRICK ||
m_burnType == OBJECT_FACTORY ||
m_burnType == OBJECT_REPAIR ||
m_burnType == OBJECT_DESTROYER||
m_burnType == OBJECT_CONVERT ||
m_burnType == OBJECT_TOWER ||
m_burnType == OBJECT_RESEARCH ||
m_burnType == OBJECT_ENERGY ||
m_burnType == OBJECT_LABO )
{
pos.x = 0.0f;
pos.y = -(4.0f+Math::Rand()*4.0f);
pos.z = 0.0f;
angle.x = (Math::Rand()-0.5f)*0.4f;
angle.y = 0.0f;
angle.z = (Math::Rand()-0.5f)*0.4f;
}
else if ( m_burnType == OBJECT_STATION ||
m_burnType == OBJECT_RADAR ||
m_burnType == OBJECT_INFO )
{
pos.x = 0.0f;
pos.y = -(1.0f+Math::Rand()*1.0f);
pos.z = 0.0f;
angle.x = (Math::Rand()-0.5f)*0.2f;
angle.y = 0.0f;
angle.z = (Math::Rand()-0.5f)*0.2f;
}
else if ( m_burnType == OBJECT_NUCLEAR )
{
pos.x = 0.0f;
pos.y = -(10.0f+Math::Rand()*10.0f);
pos.z = 0.0f;
angle.x = (Math::Rand()-0.5f)*0.4f;
angle.y = 0.0f;
angle.z = (Math::Rand()-0.5f)*0.4f;
}
else if ( m_burnType == OBJECT_PARA )
{
pos.x = 0.0f;
pos.y = -(10.0f+Math::Rand()*10.0f);
pos.z = 0.0f;
angle.x = (Math::Rand()-0.5f)*0.4f;
angle.y = 0.0f;
angle.z = (Math::Rand()-0.5f)*0.4f;
}
else if ( m_burnType == OBJECT_SAFE )
{
pos.x = 0.0f;
pos.y = -(10.0f+Math::Rand()*10.0f);
pos.z = 0.0f;
angle.x = (Math::Rand()-0.5f)*0.4f;
angle.y = 0.0f;
angle.z = (Math::Rand()-0.5f)*0.4f;
}
else if ( m_burnType == OBJECT_HUSTON )
{
pos.x = 0.0f;
pos.y = -(10.0f+Math::Rand()*10.0f);
pos.z = 0.0f;
angle.x = (Math::Rand()-0.5f)*0.4f;
angle.y = 0.0f;
angle.z = (Math::Rand()-0.5f)*0.4f;
}
else if ( m_burnType == OBJECT_MOBILEwa ||
m_burnType == OBJECT_MOBILEwb ||
m_burnType == OBJECT_MOBILEwc ||
m_burnType == OBJECT_MOBILEwi ||
m_burnType == OBJECT_MOBILEws ||
m_burnType == OBJECT_MOBILEwt )
{
pos.x = 0.0f;
pos.y = -(0.5f+Math::Rand()*1.0f);
pos.z = 0.0f;
angle.x = (Math::Rand()-0.5f)*0.8f;
angle.y = 0.0f;
angle.z = (Math::Rand()-0.5f)*0.4f;
}
else if ( m_burnType == OBJECT_TEEN31 ) // basket?
{
pos.x = 0.0f;
pos.y = 0.0f;
pos.z = 0.0f;
angle.x = (Math::Rand()-0.5f)*0.8f;
angle.y = 0.0f;
angle.z = (Math::Rand()-0.5f)*0.2f;
}
else
{
pos.x = 0.0f;
pos.y = -(2.0f+Math::Rand()*2.0f);
pos.z = 0.0f;
angle.x = (Math::Rand()-0.5f)*0.8f;
angle.y = 0.0f;
angle.z = (Math::Rand()-0.5f)*0.8f;
}
BurnAddPart(0, pos, angle); // movement of the main part
m_burnKeepPart[0] = -1; // nothing to keep
if ( m_burnType == OBJECT_DERRICK )
{
pos.x = 0.0f;
pos.y = -40.0f;
pos.z = 0.0f;
angle.x = 0.0f;
angle.y = 0.0f;
angle.z = 0.0f;
BurnAddPart(1, pos, angle); // down the drill
}
if ( m_burnType == OBJECT_REPAIR )
{
pos.x = 0.0f;
pos.y = -12.0f;
pos.z = 0.0f;
angle.x = (Math::Rand()-0.5f)*0.2f;
angle.y = (Math::Rand()-0.5f)*0.2f;
angle.z = -90.0f*Math::PI/180.0f;
BurnAddPart(1, pos, angle); // down the sensor
}
if ( m_burnType == OBJECT_DESTROYER )
{
pos.x = 0.0f;
pos.y = -12.0f;
pos.z = 0.0f;
angle.x = (Math::Rand()-0.5f)*0.2f;
angle.y = (Math::Rand()-0.5f)*0.2f;
angle.z = -90.0f*Math::PI/180.0f;
BurnAddPart(1, pos, angle); // down the sensor
}
if ( m_burnType == OBJECT_CONVERT )
{
pos.x = 0.0f;
pos.y = -200.0f;
pos.z = 0.0f;
angle.x = (Math::Rand()-0.5f)*0.5f;
angle.y = (Math::Rand()-0.5f)*0.5f;
angle.z = 0.0f;
BurnAddPart(1, pos, angle); // down the cover
BurnAddPart(2, pos, angle);
BurnAddPart(3, pos, angle);
}
if ( m_burnType == OBJECT_TOWER )
{
pos.x = 0.0f;
pos.y = -7.0f;
pos.z = 0.0f;
angle.x = (Math::Rand()-0.5f)*0.4f;
angle.y = (Math::Rand()-0.5f)*0.4f;
angle.z = 0.0f;
BurnAddPart(1, pos, angle); // down the cannon
}
if ( m_burnType == OBJECT_RESEARCH )
{
pos.x = 0.0f;
pos.y = -7.0f;
pos.z = 0.0f;
angle.x = (Math::Rand()-0.5f)*0.2f;
angle.y = (Math::Rand()-0.5f)*0.2f;
angle.z = 0.0f;
BurnAddPart(1, pos, angle); // down the anemometer
}
if ( m_burnType == OBJECT_RADAR )
{
pos.x = 0.0f;
pos.y = -14.0f;
pos.z = 0.0f;
angle.x = (Math::Rand()-0.5f)*0.4f;
angle.y = (Math::Rand()-0.5f)*0.4f;
angle.z = 0.0f;
BurnAddPart(1, pos, angle); // down the radar
BurnAddPart(2, pos, angle);
}
if ( m_burnType == OBJECT_INFO )
{
pos.x = 0.0f;
pos.y = -14.0f;
pos.z = 0.0f;
angle.x = (Math::Rand()-0.5f)*0.4f;
angle.y = (Math::Rand()-0.5f)*0.4f;
angle.z = 0.0f;
BurnAddPart(1, pos, angle); // down the information terminal
BurnAddPart(2, pos, angle);
}
if ( m_burnType == OBJECT_LABO )
{
pos.x = 0.0f;
pos.y = -12.0f;
pos.z = 0.0f;
angle.x = 0.0f;
angle.y = 0.0f;
angle.z = 0.0f;
BurnAddPart(1, pos, angle); // down the arm
}
if ( m_burnType == OBJECT_NUCLEAR )
{
pos.x = 0.0f;
pos.y = 0.0f;
pos.z = 0.0f;
angle.x = 0.0f;
angle.y = 0.0f;
angle.z = -135.0f*Math::PI/180.0f;
BurnAddPart(1, pos, angle); // down the cover
}
if ( m_burnType == OBJECT_MOBILEfa ||
m_burnType == OBJECT_MOBILEta ||
m_burnType == OBJECT_MOBILEwa ||
m_burnType == OBJECT_MOBILEia )
{
pos.x = 2.0f;
pos.y = -5.0f;
pos.z = 0.0f;
angle.x = (Math::Rand()-0.5f)*0.2f;
angle.y = (Math::Rand()-0.5f)*0.2f;
angle.z = 40.0f*Math::PI/180.0f;
BurnAddPart(1, pos, angle); // down the arm
}
if ( m_burnType == OBJECT_MOBILEfs ||
m_burnType == OBJECT_MOBILEts ||
m_burnType == OBJECT_MOBILEws ||
m_burnType == OBJECT_MOBILEis )
{
pos.x = 0.0f;
pos.y = -7.0f;
pos.z = 0.0f;
angle.x = (Math::Rand()-0.5f)*0.2f;
angle.y = (Math::Rand()-0.5f)*0.2f;
angle.z = 50.0f*Math::PI/180.0f;
BurnAddPart(1, pos, angle); // down the sensor
}
if ( m_burnType == OBJECT_MOBILEfc ||
m_burnType == OBJECT_MOBILEtc ||
m_burnType == OBJECT_MOBILEwc ||
m_burnType == OBJECT_MOBILEic )
{
pos.x = -1.5f;
pos.y = -5.0f;
pos.z = 0.0f;
angle.x = (Math::Rand()-0.5f)*0.2f;
angle.y = (Math::Rand()-0.5f)*0.2f;
angle.z = -25.0f*Math::PI/180.0f;
BurnAddPart(1, pos, angle); // down the cannon
}
if ( m_burnType == OBJECT_MOBILEfi ||
m_burnType == OBJECT_MOBILEti ||
m_burnType == OBJECT_MOBILEwi ||
m_burnType == OBJECT_MOBILEii )
{
pos.x = -1.5f;
pos.y = -5.0f;
pos.z = 0.0f;
angle.x = (Math::Rand()-0.5f)*0.2f;
angle.y = (Math::Rand()-0.5f)*0.2f;
angle.z = -25.0f*Math::PI/180.0f;
BurnAddPart(1, pos, angle); // down the insect-cannon
}
if ( m_burnType == OBJECT_MOBILEfb ||
m_burnType == OBJECT_MOBILEtb ||
m_burnType == OBJECT_MOBILEwb ||
m_burnType == OBJECT_MOBILEib )
{
pos.x = -1.5f;
pos.y = -5.0f;
pos.z = 0.0f;
angle.x = (Math::Rand()-0.5f)*0.2f;
angle.y = (Math::Rand()-0.5f)*0.2f;
angle.z = -25.0f*Math::PI/180.0f;
BurnAddPart(1, pos, angle); // down the neutron gun
}
if ( m_burnType == OBJECT_MOBILErt ||
m_burnType == OBJECT_MOBILErc )
{
pos.x = 0.0f;
pos.y = -10.0f;
pos.z = 0.0f;
angle.x = 0.0f;
angle.y = 0.0f;
angle.z = 0.0f;
BurnAddPart(1, pos, angle); // down the holder
pos.x = 0.0f;
pos.y = -10.0f;
pos.z = 0.0f;
angle.x = 0.0f;
angle.y = 0.0f;
angle.z = 0.0f;
BurnAddPart(2, pos, angle); // down the pestle/cannon
}
if ( m_burnType == OBJECT_MOBILErr )
{
pos.x = 0.0f;
pos.y = -10.0f;
pos.z = 0.0f;
angle.x = 0.0f;
angle.y = 0.0f;
angle.z = 0.0f;
BurnAddPart(1, pos, angle); // down the holder
pos.x = 0.0f;
pos.y = 0.0f;
pos.z = 0.0f;
angle.x = 0.0f;
angle.y = 0.0f;
angle.z = -Math::PI/2.0f;
BurnAddPart(4, pos, angle);
pos.x = 0.0f;
pos.y = 0.0f;
pos.z = 0.0f;
angle.x = 0.0f;
angle.y = 0.0f;
angle.z = Math::PI/2.5f;
BurnAddPart(2, pos, angle);
}
if ( m_burnType == OBJECT_MOBILErs )
{
pos.x = 0.0f;
pos.y = -10.0f;
pos.z = 0.0f;
angle.x = 0.0f;
angle.y = 0.0f;
angle.z = 0.0f;
BurnAddPart(1, pos, angle); // down the holder
pos.x = 0.0f;
pos.y = -5.0f;
pos.z = 0.0f;
angle.x = 0.0f;
angle.y = 0.0f;
angle.z = 0.0f;
BurnAddPart(2, pos, angle);
pos.x = 0.0f;
pos.y = -5.0f;
pos.z = 0.0f;
angle.x = 0.0f;
angle.y = 0.0f;
angle.z = 0.0f;
BurnAddPart(3, pos, angle);
}
if ( m_burnType == OBJECT_MOBILEsa )
{
pos.x = 0.0f;
pos.y = -10.0f;
pos.z = 0.0f;
angle.x = 0.0f;
angle.y = 0.0f;
angle.z = 0.0f;
BurnAddPart(1, pos, angle); // down the holder
}
if ( m_burnType == OBJECT_MOBILEwa ||
m_burnType == OBJECT_MOBILEwb ||
m_burnType == OBJECT_MOBILEwc ||
m_burnType == OBJECT_MOBILEwi ||
m_burnType == OBJECT_MOBILEws ||
m_burnType == OBJECT_MOBILEwt ) // wheels?
{
int i = 0;
for (; i < 4; i++)
{
pos.x = 0.0f;
pos.y = Math::Rand()*0.5f;
pos.z = 0.0f;
angle.x = (Math::Rand()-0.5f)*Math::PI/2.0f;
angle.y = (Math::Rand()-0.5f)*Math::PI/2.0f;
angle.z = 0.0f;
BurnAddPart(6+i, pos, angle); // wheel
m_burnKeepPart[i] = 6+i; // we keep the wheels
}
m_burnKeepPart[i] = -1;
}
if ( m_burnType == OBJECT_MOBILEta ||
m_burnType == OBJECT_MOBILEtb ||
m_burnType == OBJECT_MOBILEtc ||
m_burnType == OBJECT_MOBILEti ||
m_burnType == OBJECT_MOBILEts ||
m_burnType == OBJECT_MOBILEtt ||
m_burnType == OBJECT_MOBILErt ||
m_burnType == OBJECT_MOBILErc ||
m_burnType == OBJECT_MOBILErr ||
m_burnType == OBJECT_MOBILErs ||
m_burnType == OBJECT_MOBILErp ||
m_burnType == OBJECT_MOBILEsa ||
m_burnType == OBJECT_MOBILEst ||
m_burnType == OBJECT_MOBILEdr ) // caterpillars?
{
pos.x = 0.0f;
pos.y = -4.0f;
pos.z = 2.0f;
angle.x = (Math::Rand()-0.5f)*20.0f*Math::PI/180.0f;
angle.y = (Math::Rand()-0.5f)*10.0f*Math::PI/180.0f;
angle.z = (Math::Rand()-0.5f)*30.0f*Math::PI/180.0f;
BurnAddPart(6, pos, angle); // down the right caterpillar
pos.x = 0.0f;
pos.y = -4.0f;
pos.z = -2.0f;
angle.x = (Math::Rand()-0.5f)*20.0f*Math::PI/180.0f;
angle.y = (Math::Rand()-0.5f)*10.0f*Math::PI/180.0f;
angle.z = (Math::Rand()-0.5f)*30.0f*Math::PI/180.0f;
BurnAddPart(7, pos, angle); // down the left caterpillar
}
if ( m_burnType == OBJECT_MOBILEfa ||
m_burnType == OBJECT_MOBILEfb ||
m_burnType == OBJECT_MOBILEfc ||
m_burnType == OBJECT_MOBILEfi ||
m_burnType == OBJECT_MOBILEfs ||
m_burnType == OBJECT_MOBILEft ) // flying?
{
int i = 0;
for (; i<3; i++)
{
pos.x = 0.0f;
pos.y = -3.0f;
pos.z = 0.0f;
angle.x = 0.0f;
angle.y = 0.0f;
angle.z = (Math::Rand()-0.5f)*Math::PI/2.0f;
BurnAddPart(6+i, pos, angle); // foot
}
m_burnKeepPart[i] = -1;
}
if ( m_burnType == OBJECT_MOBILEia ||
m_burnType == OBJECT_MOBILEib ||
m_burnType == OBJECT_MOBILEic ||
m_burnType == OBJECT_MOBILEii ||
m_burnType == OBJECT_MOBILEis ||
m_burnType == OBJECT_MOBILEit ) // legs?
{
for (int i = 0; i < 6; i++)
{
pos.x = 0.0f;
pos.y = -3.0f;
pos.z = 0.0f;
angle.x = 0.0f;
angle.y = (Math::Rand()-0.5f)*Math::PI/4.0f;
angle.z = (Math::Rand()-0.5f)*Math::PI/4.0f;
BurnAddPart(6+i, pos, angle); // leg
}
}
}
void CBurnPyro::BurnAddPart(int part, Math::Vector pos, Math::Vector angle)
{
// TODO: temporary hack (hopefully)
assert(m_object->Implements(ObjectInterfaceType::Old));
COldObject& oldObj = dynamic_cast<COldObject&>(*m_object);
int i = m_burnPartTotal;
m_burnPart[i].part = part;
m_burnPart[i].initialPos = oldObj.GetPartPosition(part);
m_burnPart[i].finalPos = m_burnPart[i].initialPos+pos;
m_burnPart[i].initialAngle = oldObj.GetPartRotation(part);
m_burnPart[i].finalAngle = m_burnPart[i].initialAngle+angle;
m_burnPartTotal++;
}
void CBurnPyro::BurnProgress()
{
if ( m_burnType == OBJECT_TEEN31 ) // basket?
{
m_object->SetScaleY(1.0f-m_progress*0.5f); // slight flattening
}
for (int i = 0; i < m_burnPartTotal; i++)
{
Math::Vector pos = m_burnPart[i].initialPos + m_progress*(m_burnPart[i].finalPos-m_burnPart[i].initialPos);
if ( i == 0 && m_burnFall > 0.0f )
{
float h = powf(m_progress, 2.0f)*1000.0f;
if ( h > m_burnFall ) h = m_burnFall;
pos.y -= h;
}
// TODO: temporary hack (hopefully)
assert(m_object->Implements(ObjectInterfaceType::Old));
COldObject& oldObj = dynamic_cast<COldObject&>(*m_object);
oldObj.SetPartPosition(m_burnPart[i].part, pos);
pos = m_burnPart[i].initialAngle + m_progress*(m_burnPart[i].finalAngle-m_burnPart[i].initialAngle);
oldObj.SetPartRotation(m_burnPart[i].part, pos);
}
if (m_object->Implements(ObjectInterfaceType::Powered))
{
CObject* sub = dynamic_cast<CPoweredObject&>(*m_object).GetPower();
if (sub != nullptr) // is there a battery?
sub->SetScaleY(1.0f - m_progress); // complete flattening
}
}
bool CBurnPyro::BurnIsKeepPart(int part)
{
int i = 0;
while (m_burnKeepPart[i] != -1)
{
if (part == m_burnKeepPart[i++]) return true; // must keep
}
return false; // must destroy
}
void CBurnPyro::AfterEnd()
{
if (m_object == nullptr)
return;
if (m_organicBurn) // organic object is burning?
{
DeleteObject(true, true); // removes the insect
return;
}
for (int i = 1; i < OBJECTMAXPART; i++)
{
int objRank = m_object->GetObjectRank(i);
if (objRank == -1) continue;
if (BurnIsKeepPart(i)) continue;
m_object->DeletePart(i);
}
DeleteObject(false, true); // destroys the object transported + the battery
if ( m_burnType == OBJECT_DERRICK ||
m_burnType == OBJECT_STATION ||
m_burnType == OBJECT_FACTORY ||
m_burnType == OBJECT_REPAIR ||
m_burnType == OBJECT_DESTROYER||
m_burnType == OBJECT_CONVERT ||
m_burnType == OBJECT_TOWER ||
m_burnType == OBJECT_RESEARCH ||
m_burnType == OBJECT_RADAR ||
m_burnType == OBJECT_INFO ||
m_burnType == OBJECT_ENERGY ||
m_burnType == OBJECT_LABO ||
m_burnType == OBJECT_NUCLEAR ||
m_burnType == OBJECT_PARA ||
m_burnType == OBJECT_SAFE ||
m_burnType == OBJECT_HUSTON ||
m_burnType == OBJECT_START ||
m_burnType == OBJECT_END )
{
m_object->SetType(OBJECT_RUINfactory); // Ruin
}
else
{
m_object->SetType(OBJECT_RUINmobilew1); // Wreck (recoverable by Recycler)
}
dynamic_cast<CDestroyableObject&>(*m_object).SetDying(DeathType::Alive);
m_object->SetLock(false);
}

View File

@ -0,0 +1,80 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.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
*/
#include "graphics/engine/camera.h"
#include "graphics/pyro/pyro.h"
#include "object/object.h"
#include "object/interface/destroyable_object.h"
#include "object/interface/movable_object.h"
#include "object/motion/motion.h"
#include "object/motion/motionhuman.h"
#include "sound/sound.h"
using namespace Gfx;
CDeadGPyro::CDeadGPyro(CObject *obj)
: CPyro(obj)
{}
void CDeadGPyro::AfterCreate()
{
if (m_object->GetType() == OBJECT_HUMAN)
{
m_sound->Play(SOUND_DEADg, m_pos);
}
assert(m_object->Implements(ObjectInterfaceType::Destroyable));
dynamic_cast<CDestroyableObject&>(*m_object).SetDying(DeathType::Dead);
assert(m_object->Implements(ObjectInterfaceType::Movable));
dynamic_cast<CMovableObject&>(*m_object).GetMotion()->SetAction(MHS_DEADg, 1.0f);
m_camera->StartCentering(m_object, Math::PI*0.5f, 99.9f, 0.0f, 1.5f);
m_camera->StartOver(CAM_OVER_EFFECT_FADEOUT_WHITE, m_pos, 1.0f);
m_speed = 1.0f/10.0f;
}
CDeadWPyro::CDeadWPyro(CObject *obj)
: CPyro(obj)
{}
void CDeadWPyro::AfterCreate()
{
if (m_object->GetType() == OBJECT_HUMAN)
{
m_sound->Play(SOUND_DEADw, m_pos);
}
assert(m_object->Implements(ObjectInterfaceType::Destroyable));
dynamic_cast<CDestroyableObject&>(*m_object).SetDying(DeathType::Dead);
assert(m_object->Implements(ObjectInterfaceType::Movable));
dynamic_cast<CMovableObject&>(*m_object).GetMotion()->SetAction(MHS_DEADw, 1.0f);
m_camera->StartCentering(m_object, Math::PI*0.5f, 99.9f, 0.0f, 3.0f);
m_camera->StartOver(CAM_OVER_EFFECT_FADEOUT_BLACK, m_pos, 1.0f);
m_speed = 1.0f/10.0f;
}

View File

@ -0,0 +1,53 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.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
*/
#include "graphics/pyro/pyro.h"
#include "object/old_object.h"
#include "sound/sound.h"
// old_object.h only needed for OBJECTMAXPART - TODO improve this
using namespace Gfx;
CEggPyro::CEggPyro(CObject *obj)
: CPyro(obj)
{}
bool CEggPyro::EventProcess(const Event& event)
{
// Destroys the object that exploded.
//It should not be destroyed at the end of the Create,
//because it is sometimes the object itself that makes the Create:
// pyro->Create(PT_FRAGT, this);
DeleteObject(true, true);
return CPyro::EventProcess(event);
}
void CEggPyro::AfterCreate()
{
m_sound->Play(SOUND_EGG, m_pos);
for (int part = 0; part < OBJECTMAXPART; part++)
{
CreateTriangle(m_object, m_object->GetType(), part, 5, 15, 20, 40, 0.30f);
}
}

View File

@ -0,0 +1,202 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.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
*/
#include "graphics/engine/particle.h"
#include "graphics/engine/terrain.h"
#include "graphics/pyro/pyro.h"
#include "graphics/pyro/pyro_manager.h"
#include "object/object.h"
#include "object/object_manager.h"
#include "object/old_object.h"
#include "object/subclass/shielder.h"
#include "sound/sound.h"
using namespace Gfx;
CFallPyro::CFallPyro(CObject *obj)
: CPyro(obj)
{}
void CFallPyro::AfterCreate()
{
m_object->SetLock(true); // usable
Math::Vector pos = m_object->GetPosition();
m_fallFloor = m_terrain->GetFloorLevel(pos);
m_fallSpeed = 0.0f;
m_fallBulletTime = 0.0f;
m_fallEnding = false;
}
CObject* CFallPyro::FallSearchBeeExplo()
{
auto bulletCrashSphere = m_object->GetFirstCrashSphere();
for (CObject* obj : CObjectManager::GetInstancePointer()->GetAllObjects())
{
if (obj == m_object) continue;
if (obj->GetType() == OBJECT_BEE) continue;
if ( !obj->Implements(ObjectInterfaceType::Destroyable) ) continue;
if (IsObjectBeingTransported(obj)) continue;
Math::Vector oPos = obj->GetPosition();
if (obj->GetType() == OBJECT_MOBILErs)
{
float shieldRadius = dynamic_cast<CShielder&>(*obj).GetActiveShieldRadius();
if ( shieldRadius > 0.0f )
{
float distance = Math::Distance(oPos, bulletCrashSphere.sphere.pos);
if (distance <= shieldRadius)
return obj;
}
}
if ( obj->GetType() == OBJECT_BASE )
{
float distance = Math::Distance(oPos, bulletCrashSphere.sphere.pos);
if (distance < 25.0f)
return obj;
}
// Test the center of the object, which is necessary for objects
// that have no sphere in the center (station).
float distance = Math::Distance(oPos, bulletCrashSphere.sphere.pos)-4.0f;
if (distance < 5.0f)
return obj;
// Test with all spheres of the object.
for (const auto& objCrashSphere : obj->GetAllCrashSpheres())
{
if (Math::DistanceBetweenSpheres(objCrashSphere.sphere, bulletCrashSphere.sphere) <= 0.0f)
{
return obj;
}
}
}
return nullptr;
}
void CFallPyro::FallProgress(float rTime)
{
if (m_object == nullptr) return;
m_fallSpeed += rTime*50.0f; // v2 = v1 + a*dt
Math::Vector pos;
pos = m_object->GetPosition();
pos.y -= m_fallSpeed*rTime; // dd -= v2*dt
bool floor = false;
if (pos.y <= m_fallFloor) // below the ground level?
{
pos.y = m_fallFloor;
floor = true;
}
m_object->SetPosition(pos);
if (m_object->GetType() == OBJECT_BULLET)
{
m_fallBulletTime += rTime;
if (m_fallBulletTime > 0.2f || floor)
{
m_fallBulletTime = 0.0f;
CObject* obj = FallSearchBeeExplo();
if (obj == nullptr)
{
if (floor) // reaches the ground?
{
assert(m_object->Implements(ObjectInterfaceType::Destroyable));
// TODO: implement "killer"?
dynamic_cast<CDestroyableObject&>(*m_object).DestroyObject(DestructionType::Explosion);
}
}
else
{
if (obj->GetType() == OBJECT_MOBILErs && dynamic_cast<CShielder&>(*obj).GetActiveShieldRadius() > 0.0f) // protected by shield?
{
m_particle->CreateParticle(pos, Math::Vector(0.0f, 0.0f, 0.0f),
Math::Point(6.0f, 6.0f), PARTIGUNDEL, 2.0f, 0.0f, 0.0f);
m_sound->Play(SOUND_GUNDEL);
DeleteObject(true, true); // removes the ball
}
else
{
assert(obj->Implements(ObjectInterfaceType::Damageable));
if (dynamic_cast<CDamageableObject&>(*obj).DamageObject(DamageType::FallingObject))
{
DeleteObject(true, true); // removes the ball
}
else
{
assert(m_object->Implements(ObjectInterfaceType::Destroyable));
// TODO: implement "killer"?
dynamic_cast<CDestroyableObject&>(*m_object).DestroyObject(DestructionType::Explosion);
}
}
}
if (floor || obj != nullptr)
{
m_fallEnding = true;
}
}
}
}
Error CFallPyro::IsEnded()
{
if (m_fallEnding || m_object == nullptr) return ERR_STOP;
Math::Vector pos = m_object->GetPosition();
if (pos.y > m_fallFloor) return ERR_CONTINUE;
return ERR_STOP;
}
void CFallPyro::AfterEnd()
{
if (m_object != nullptr)
{
m_sound->Play(SOUND_BOUM, m_object->GetPosition());
m_object->SetLock(false); // usable again
}
}
bool CFallPyro::EventProcess(const Event& event)
{
CPyro::EventProcess(event);
if ( event.type != EVENT_FRAME ) return true;
if ( m_engine->GetPause() ) return true;
// don't use UpdateEffect since we want to access event.rTime
FallProgress(event.rTime);
return true;
}

View File

@ -0,0 +1,72 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.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
*/
#include "graphics/engine/particle.h"
#include "graphics/engine/terrain.h"
#include "graphics/pyro/pyro.h"
#include "graphics/pyro/pyro_manager.h"
#include "object/object.h"
#include "sound/sound.h"
using namespace Gfx;
CFindingPyro::CFindingPyro(CObject *obj)
: CPyro(obj)
{}
void CFindingPyro::AfterCreate()
{
float limit = (m_size-1.0f)/4.0f;
if (limit > 8.0f) limit = 8.0f;
if (m_object->GetType() == OBJECT_APOLLO2) limit = 2.0f;
m_speed = 1.0f/limit;
LightOperAdd(0.00f, 1.0f, 4.0f, 4.0f, 2.0f); // yellow
LightOperAdd(1.00f, 0.0f, 4.0f, 4.0f, 2.0f); // yellow
CreateLight(m_pos, 40.0f);
}
void CFindingPyro::UpdateEffect()
{
if ( m_object != nullptr &&
m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
{
m_lastParticle = m_time;
float factor = m_size*0.3f;
if (m_object->GetType() == OBJECT_SAFE) factor *= 1.3f;
if (factor > 40.0f) factor = 40.0f;
Math::Vector pos = m_pos;
m_terrain->AdjustToFloor(pos);
pos.x += (Math::Rand()-0.5f)*factor;
pos.z += (Math::Rand()-0.5f)*factor;
Math::Vector speed;
speed.x = (Math::Rand()-0.5f)*2.0f;
speed.z = (Math::Rand()-0.5f)*2.0f;
speed.y = 4.0f+Math::Rand()*4.0f;
Math::Point dim;
dim.x = (Math::Rand()*3.0f+3.0f)*(1.0f-m_progress*0.9f);
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.5f);
}
}

View File

@ -0,0 +1,81 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.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
*/
#include "graphics/engine/particle.h"
#include "graphics/engine/terrain.h"
#include "graphics/pyro/pyro.h"
#include "graphics/pyro/pyro_manager.h"
#include "object/object.h"
#include "sound/sound.h"
using namespace Gfx;
CFlagCreatePyro::CFlagCreatePyro(CObject *pObj)
: CPyro(pObj)
{}
void CFlagCreatePyro::AfterCreate()
{
m_sound->Play(SOUND_WAYPOINT, m_pos);
LightOperAdd(0.00f, 1.0f, 4.0f, 4.0f, 2.0f); // yellow
LightOperAdd(1.00f, 0.0f, 4.0f, 4.0f, 2.0f); // yellow
CreateLight(m_pos, 40.0f);
m_speed = 1.0f/2.0f;
}
void CFlagCreatePyro::AfterEnd()
{
m_object->SetRotationX(0.0f);
m_object->SetRotationZ(0.0f);
m_object->SetScale(1.0f);
}
void CFlagCreatePyro::UpdateEffect()
{
if ( m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
{
m_lastParticle = m_time;
Math::Vector pos = m_pos;
m_terrain->AdjustToFloor(pos);
pos.x += (Math::Rand()-0.5f)*1.0f;
pos.z += (Math::Rand()-0.5f)*1.0f;
Math::Vector speed;
speed.x = (Math::Rand()-0.5f)*2.0f;
speed.z = (Math::Rand()-0.5f)*2.0f;
speed.y = 2.0f+Math::Rand()*2.0f;
Math::Point dim;
dim.x = (Math::Rand()*1.0f+1.0f)*(0.2f+m_progress*0.8f);
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.0f);
}
if(m_object != nullptr)
{
Math::Vector angle = m_object->GetRotation();
angle.x = sinf(m_progress*49.0f)*0.3f*(1.0f-m_progress);
angle.z = sinf(m_progress*47.0f)*0.2f*(1.0f-m_progress);
m_object->SetRotation(angle);
m_object->SetScale(m_progress);
}
}

View File

@ -0,0 +1,81 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.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
*/
#include "graphics/engine/particle.h"
#include "graphics/engine/terrain.h"
#include "graphics/pyro/pyro.h"
#include "graphics/pyro/pyro_manager.h"
#include "object/object.h"
#include "sound/sound.h"
using namespace Gfx;
CFlagDeletePyro::CFlagDeletePyro(CObject *pObj)
: CPyro(pObj)
{}
void CFlagDeletePyro::AfterCreate()
{
m_sound->Play(SOUND_WAYPOINT, m_pos);
LightOperAdd(0.00f, 1.0f, 4.0f, 4.0f, 2.0f); // yellow
LightOperAdd(1.00f, 0.0f, 4.0f, 4.0f, 2.0f); // yellow
CreateLight(m_pos, 40.0f);
m_speed = 1.0f/2.0f;
m_object->SetLock(true); // object more functional
}
void CFlagDeletePyro::AfterEnd()
{
DeleteObject(true, true);
}
void CFlagDeletePyro::UpdateEffect()
{
if ( m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
{
m_lastParticle = m_time;
Math::Vector pos = m_pos;
m_terrain->AdjustToFloor(pos);
pos.x += (Math::Rand()-0.5f)*1.0f;
pos.z += (Math::Rand()-0.5f)*1.0f;
Math::Vector speed;
speed.x = (Math::Rand()-0.5f)*2.0f;
speed.z = (Math::Rand()-0.5f)*2.0f;
speed.y = 2.0f+Math::Rand()*2.0f;
Math::Point dim;
dim.x = (Math::Rand()*1.0f+1.0f)*(0.2f+m_progress*0.8f);
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.5f);
}
if(m_object != nullptr)
{
Math::Vector angle = m_object->GetRotation();
angle.y = m_progress*20.0f;
angle.x = sinf(m_progress*49.0f)*0.3f;
angle.z = sinf(m_progress*47.0f)*0.2f;
m_object->SetRotation(angle);
m_object->SetScale(1.0f-m_progress);
}
}

View File

@ -0,0 +1,639 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.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
*/
#include "graphics/engine/particle.h"
#include "graphics/engine/terrain.h"
#include "graphics/pyro/pyro.h"
#include "graphics/pyro/pyro_manager.h"
#include "level/robotmain.h"
#include "object/object.h"
#include "object/old_object.h"
#include "sound/sound.h"
using namespace Gfx;
CFragExploOrShotPyro::CFragExploOrShotPyro(FragExploOrShotPyroType type, CObject *obj, float force)
: CPyro(obj),
m_force(force),
m_type(type)
{}
void CFragExploOrShotPyro::AfterCreate()
{
ObjectType oType = m_object->GetType();
// Plays the sound of a pyrotechnic effect.
if ( m_type == PT_FRAGT ||
m_type == PT_FRAGW ||
m_type == PT_EXPLOT ||
m_type == PT_EXPLOW )
{
SoundType sound;
if ( m_power )
{
sound = SOUND_EXPLOp;
}
else
{
sound = SOUND_EXPLO;
}
if ( oType == OBJECT_STONE ||
oType == OBJECT_METAL ||
oType == OBJECT_BULLET ||
oType == OBJECT_BBOX ||
oType == OBJECT_KEYa ||
oType == OBJECT_KEYb ||
oType == OBJECT_KEYc ||
oType == OBJECT_KEYd )
{
sound = SOUND_EXPLOl;
}
if ( oType == OBJECT_URANIUM ||
oType == OBJECT_POWER ||
oType == OBJECT_ATOMIC ||
oType == OBJECT_TNT ||
oType == OBJECT_BOMB )
{
sound = SOUND_EXPLOlp;
}
m_sound->Play(sound, m_pos);
}
if ( m_type == PT_FRAGO ||
m_type == PT_EXPLOO ||
m_type == PT_SHOTM )
{
m_sound->Play(SOUND_EXPLOi, m_pos);
}
if ( oType == OBJECT_HUMAN )
{
assert(m_object->Implements(ObjectInterfaceType::Controllable));
if ( m_type == PT_SHOTH && dynamic_cast<CControllableObject&>(*m_object).GetSelect() )
{
m_sound->Play(SOUND_AIE, m_pos);
m_sound->Play(SOUND_AIE, m_engine->GetEyePt());
}
}
if ( m_type == PT_FRAGT ||
m_type == PT_FRAGO ||
m_type == PT_FRAGW )
{
m_engine->DeleteShadowSpot(m_object->GetObjectRank(0));
}
if ( m_type == PT_SHOTT ||
m_type == PT_SHOTM )
{
m_camera->StartEffect(CAM_EFFECT_SHOT, m_pos, m_force);
m_speed = 1.0f/1.0f;
}
if ( m_type == PT_SHOTH )
{
assert(m_object->Implements(ObjectInterfaceType::Controllable));
if ( m_camera->GetBlood() && dynamic_cast<CControllableObject&>(*m_object).GetSelect() )
{
m_camera->StartOver(CAM_OVER_EFFECT_BLOOD, m_pos, m_force);
}
m_speed = 1.0f/0.2f;
}
if ( m_type == PT_SHOTW )
{
m_speed = 1.0f/1.0f;
}
if ( m_type == PT_EXPLOT ||
m_type == PT_EXPLOO ||
m_type == PT_EXPLOW )
{
CreateTriangle(m_object, m_object->GetType(), 0);
m_engine->DeleteShadowSpot(m_object->GetObjectRank(0));
ExploStart();
}
// Generates the triangles of the explosion.
if ( m_type == PT_FRAGT ||
m_type == PT_FRAGO ||
m_type == PT_FRAGW ||
(m_type == PT_EXPLOT && oType == OBJECT_MOBILEtg) ||
(m_type == PT_EXPLOT && oType == OBJECT_TEEN28 ) ||
(m_type == PT_EXPLOT && oType == OBJECT_TEEN31 ) )
{
for (int part = 0; part < OBJECTMAXPART; part++)
{
CreateTriangle(m_object, m_object->GetType(), part);
}
}
if ( m_type == PT_FRAGT ||
m_type == PT_EXPLOT )
{
if ( m_power )
{
int total = static_cast<int>(10.0f*m_engine->GetParticleDensity());
if ( oType == OBJECT_TNT ||
oType == OBJECT_BOMB ) total *= 3;
for (int i = 0; i < total; i++)
{
Math::Vector pos = m_posPower;
Math::Vector speed;
speed.x = (Math::Rand()-0.5f)*30.0f;
speed.z = (Math::Rand()-0.5f)*30.0f;
speed.y = Math::Rand()*30.0f;
Math::Point dim;
dim.x = 1.0f;
dim.y = dim.x;
float duration = Math::Rand()*3.0f+2.0f;
float mass = Math::Rand()*10.0f+15.0f;
m_particle->CreateTrack(pos, speed, dim, PARTITRACK1,
duration, mass, Math::Rand()+0.7f, 1.0f);
}
}
if (m_size > 10.0f) // large enough (freight excluded)?
{
Math::Vector pos;
if (m_power)
{
pos = m_posPower;
}
else
{
pos = m_pos;
m_terrain->AdjustToFloor(pos);
pos.y += 1.0f;
}
Math::Point dim;
dim.x = m_size*0.4f;
dim.y = dim.x;
m_particle->CreateParticle(pos, Math::Vector(0.0f,0.0f,0.0f), dim, PARTISPHERE0, 2.0f, 0.0f, 0.0f);
}
}
if ( m_type == PT_FRAGO ||
m_type == PT_EXPLOO )
{
int total = static_cast<int>(10.0f*m_engine->GetParticleDensity());
for (int i = 0; i < total; i++)
{
Math::Vector pos = m_pos;
Math::Vector speed;
speed.x = (Math::Rand()-0.5f)*30.0f;
speed.z = (Math::Rand()-0.5f)*30.0f;
speed.y = Math::Rand()*50.0f;
Math::Point dim;
dim.x = 1.0f;
dim.y = dim.x;
float duration = Math::Rand()*1.0f+0.8f;
float mass = Math::Rand()*10.0f+15.0f;
m_particle->CreateParticle(pos, speed, dim, PARTIORGANIC1,
duration, mass);
}
total = static_cast<int>(5.0f*m_engine->GetParticleDensity());
for (int i = 0; i < total; i++)
{
Math::Vector pos = m_pos;
Math::Vector speed;
speed.x = (Math::Rand()-0.5f)*30.0f;
speed.z = (Math::Rand()-0.5f)*30.0f;
speed.y = Math::Rand()*50.0f;
Math::Point dim;
dim.x = 1.0f;
dim.y = dim.x;
float duration = Math::Rand()*2.0f+1.4f;
float mass = Math::Rand()*10.0f+15.0f;
m_particle->CreateTrack(pos, speed, dim, PARTITRACK4,
duration, mass, duration*0.5f, dim.x*2.0f);
}
}
if ( m_type == PT_FRAGT ||
m_type == PT_FRAGW ||
m_type == PT_EXPLOT ||
m_type == PT_EXPLOW )
{
if (m_size > 10.0f || m_power)
{
Math::Vector pos = m_pos;
Math::Vector speed(0.0f, 0.0f, 0.0f);
Math::Point dim;
dim.x = m_size;
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, PARTICHOC, 2.0f);
}
}
if ( m_type == PT_FRAGO ||
m_type == PT_EXPLOO )
{
LightOperAdd(0.00f, 0.0f, -1.0f, -0.5f, -1.0f); // dark green
LightOperAdd(0.05f, 1.0f, -1.0f, -0.5f, -1.0f); // dark green
LightOperAdd(1.00f, 0.0f, -1.0f, -0.5f, -1.0f); // dark green
}
else if ( m_type == PT_FRAGT ||
m_type == PT_EXPLOT )
{
LightOperAdd(0.00f, 1.0f, 4.0f, 4.0f, 2.0f); // yellow
LightOperAdd(0.02f, 1.0f, 4.0f, 2.0f, 0.0f); // red-orange
LightOperAdd(0.16f, 1.0f, -0.8f, -0.8f, -0.8f); // dark gray
LightOperAdd(1.00f, 0.0f, -0.8f, -0.8f, -0.8f); // dark gray
}
else if ( m_type == PT_FRAGW ||
m_type == PT_EXPLOW ||
m_type == PT_SHOTW )
{
LightOperAdd(0.00f, 0.0f, -0.5f, -0.5f, -1.0f); // dark yellow
LightOperAdd(0.05f, 1.0f, -0.5f, -0.5f, -1.0f); // dark yellow
LightOperAdd(1.00f, 0.0f, -0.5f, -0.5f, -1.0f); // dark yellow
}
if (m_type == PT_SHOTW)
{
// PT_SHOTW might be unused? In the previous code structure, this was a default case
LightOperAdd(0.00f, 0.0f, -0.8f, -0.8f, -0.8f); // dark gray
LightOperAdd(0.05f, 1.0f, -0.8f, -0.8f, -0.8f); // dark gray
LightOperAdd(1.00f, 0.0f, -0.8f, -0.8f, -0.8f); // dark gray
}
if (m_type == PT_FRAGT ||
m_type == PT_FRAGO ||
m_type == PT_FRAGW ||
m_type == PT_EXPLOT ||
m_type == PT_EXPLOO ||
m_type == PT_EXPLOW ||
m_type == PT_SHOTW)
{
// PT_SHOTW might be unused? In the previous code structure, this was a default case
m_camera->StartEffect(CAM_EFFECT_EXPLO, m_pos, m_force);
}
if (m_type == PT_FRAGT || m_type == PT_EXPLOT)
{
CreateLight(m_pos, m_size*2.0f);
}
else if (m_type == PT_FRAGO || m_type == PT_EXPLOO || m_type == PT_FRAGW || m_type == PT_EXPLOW || m_type == PT_SHOTW)
{
// PT_SHOTW might be unused? In the previous code structure, this was a default case
CreateLight(m_pos, 40.0f);
}
}
bool CFragExploOrShotPyro::EventProcess(const Event& event)
{
// Destroys the object that exploded.
//It should not be destroyed at the end of the Create,
//because it is sometimes the object itself that makes the Create:
// pyro->Create(PT_FRAGT, this);
if ( m_type == PT_FRAGT ||
m_type == PT_FRAGO ||
m_type == PT_FRAGW )
{
DeleteObject(true, true);
}
return CPyro::EventProcess(event);
}
void CFragExploOrShotPyro::ExploStart()
{
m_burnType = m_object->GetType();
Math::Vector oPos = m_object->GetPosition();
m_burnFall = m_terrain->GetHeightToFloor(oPos, true);
m_object->Simplify();
m_object->SetLock(true); // ruin not usable yet
assert(m_object->Implements(ObjectInterfaceType::Destroyable));
dynamic_cast<CDestroyableObject&>(*m_object).SetDying(DeathType::Exploding); // being destroyed
m_object->FlatParent();
if ( m_object->Implements(ObjectInterfaceType::Controllable) && dynamic_cast<CControllableObject&>(*m_object).GetSelect() )
{
dynamic_cast<CControllableObject&>(*m_object).SetSelect(false); // deselects the object
m_camera->SetType(CAM_TYPE_EXPLO);
m_main->DeselectAll();
}
m_main->RemoveFromSelectionHistory(m_object);
for (int i = 0; i < OBJECTMAXPART; i++)
{
int objRank = m_object->GetObjectRank(i);
if (objRank == -1) continue;
// TODO: refactor later to material change
int oldBaseObjRank = m_engine->GetObjectBaseRank(objRank);
if (oldBaseObjRank != -1)
{
int newBaseObjRank = m_engine->CreateBaseObject();
m_engine->CopyBaseObject(oldBaseObjRank, newBaseObjRank);
m_engine->SetObjectBaseRank(objRank, newBaseObjRank);
m_engine->ChangeSecondTexture(objRank, "dirty04.png");
}
// TODO: temporary hack (hopefully)
assert(m_object->Implements(ObjectInterfaceType::Old));
Math::Vector pos = dynamic_cast<COldObject&>(*m_object).GetPartPosition(i);
Math::Vector speed;
float weight;
if (i == 0) // main part?
{
weight = 0.0f;
speed.y = -1.0f;
speed.x = 0.0f;
speed.z = 0.0f;
}
else
{
Math::Vector min, max;
m_engine->GetObjectBBox(objRank, min, max);
weight = Math::Distance(min, max); // weight according to size!
speed.y = 10.0f+Math::Rand()*20.0f;
speed.x = (Math::Rand()-0.5f)*20.0f;
speed.z = (Math::Rand()-0.5f)*20.0f;
}
int channel = m_particle->CreatePart(pos, speed, PARTIPART, 10.0f, 20.0f, weight, 0.5f);
if (channel != -1)
m_object->SetMasterParticle(i, channel);
}
m_engine->LoadTexture("textures/dirty04.png");
DeleteObject(false, true); // destroys the object transported + the battery
}
void CFragExploOrShotPyro::UpdateEffect()
{
if ( m_type == PT_SHOTT &&
m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
{
m_lastParticle = m_time;
if (m_crashSpheres.size() > 0)
{
int i = rand() % m_crashSpheres.size();
Math::Vector pos = m_crashSpheres[i].pos;
float radius = m_crashSpheres[i].radius;
pos.x += (Math::Rand()-0.5f)*radius*2.0f;
pos.z += (Math::Rand()-0.5f)*radius*2.0f;
Math::Vector speed;
speed.x = (Math::Rand()-0.5f)*radius*0.5f;
speed.z = (Math::Rand()-0.5f)*radius*0.5f;
speed.y = Math::Rand()*radius*1.0f;
Math::Point dim;
dim.x = Math::Rand()*radius*0.5f+radius*0.75f*m_force;
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, PARTISMOKE1, 3.0f);
}
else
{
Math::Vector pos = m_pos;
pos.x += (Math::Rand()-0.5f)*m_size*0.3f;
pos.z += (Math::Rand()-0.5f)*m_size*0.3f;
Math::Vector speed;
speed.x = (Math::Rand()-0.5f)*m_size*0.1f;
speed.z = (Math::Rand()-0.5f)*m_size*0.1f;
speed.y = Math::Rand()*m_size*0.2f;
Math::Point dim;
dim.x = Math::Rand()*m_size/10.0f+m_size/10.0f*m_force;
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, PARTISMOKE1, 3.0f);
}
}
if ( m_camera->GetBlood() && m_type == PT_SHOTH &&
m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
{
m_lastParticle = m_time;
for (int i = 0; i < 10; i++)
{
Math::Vector pos = m_pos;
pos.x += (Math::Rand()-0.5f)*m_size*0.2f;
pos.z += (Math::Rand()-0.5f)*m_size*0.2f;
pos.y += (Math::Rand()-0.5f)*m_size*0.5f;
Math::Vector speed;
speed.x = (Math::Rand()-0.5f)*5.0f;
speed.z = (Math::Rand()-0.5f)*5.0f;
speed.y = Math::Rand()*1.0f;
Math::Point dim;
dim.x = 1.0f;
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, PARTIBLOOD, Math::Rand()*3.0f+3.0f, Math::Rand()*10.0f+15.0f, 0.5f);
}
}
if ( m_camera->GetBlood() && m_type == PT_SHOTM &&
m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
{
m_lastParticle = m_time;
int r = static_cast<int>(10.0f*m_engine->GetParticleDensity());
for (int i = 0; i < r; i++)
{
Math::Vector pos = m_pos;
pos.x += (Math::Rand()-0.5f)*20.0f;
pos.z += (Math::Rand()-0.5f)*20.0f;
pos.y += 8.0f;
Math::Vector speed;
speed.x = (Math::Rand()-0.5f)*40.0f;
speed.z = (Math::Rand()-0.5f)*40.0f;
speed.y = Math::Rand()*40.0f;
Math::Point dim;
dim.x = Math::Rand()*8.0f+8.0f*m_force;
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, PARTIBLOODM, 2.0f, 50.0f, 0.0f);
}
}
if ( m_type == PT_SHOTW &&
m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
{
m_lastParticle = m_time;
if (m_crashSpheres.size() > 0)
{
int i = rand() % m_crashSpheres.size();
Math::Vector pos = m_crashSpheres[i].pos;
float radius = m_crashSpheres[i].radius;
pos.x += (Math::Rand()-0.5f)*radius*2.0f;
pos.z += (Math::Rand()-0.5f)*radius*2.0f;
Math::Vector speed;
speed.x = (Math::Rand()-0.5f)*radius*0.5f;
speed.z = (Math::Rand()-0.5f)*radius*0.5f;
speed.y = Math::Rand()*radius*1.0f;
Math::Point dim;
dim.x = 1.0f*m_force;
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f);
}
else
{
Math::Vector pos = m_pos;
pos.x += (Math::Rand()-0.5f)*m_size*0.3f;
pos.z += (Math::Rand()-0.5f)*m_size*0.3f;
Math::Vector speed;
speed.x = (Math::Rand()-0.5f)*m_size*0.1f;
speed.z = (Math::Rand()-0.5f)*m_size*0.1f;
speed.y = Math::Rand()*m_size*0.2f;
Math::Point dim;
dim.x = 1.0f*m_force;
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f);
}
}
if ( m_type == PT_SHOTW &&
m_lastParticleSmoke+m_engine->ParticleAdapt(0.10f) <= m_time )
{
m_lastParticleSmoke = m_time;
Math::Vector pos = m_pos;
pos.y -= 2.0f;
pos.x += (Math::Rand()-0.5f)*4.0f;
pos.z += (Math::Rand()-0.5f)*4.0f;
Math::Vector speed;
speed.x = 0.0f;
speed.z = 0.0f;
speed.y = 10.0f+Math::Rand()*10.0f;
Math::Point dim;
dim.x = Math::Rand()*2.5f+2.0f*m_force;
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, PARTICRASH, 4.0f);
}
if ( (m_type == PT_FRAGT || m_type == PT_EXPLOT) &&
m_progress < 0.05f &&
m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
{
m_lastParticle = m_time;
Math::Vector pos = m_pos;
Math::Vector speed;
speed.x = (Math::Rand()-0.5f)*m_size*1.0f;
speed.z = (Math::Rand()-0.5f)*m_size*1.0f;
speed.y = Math::Rand()*m_size*0.50f;
Math::Point dim;
dim.x = Math::Rand()*m_size/5.0f+m_size/5.0f;
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, PARTIEXPLOT);
}
if ( (m_type == PT_FRAGT || m_type == PT_EXPLOT) &&
m_progress < 0.10f &&
m_lastParticleSmoke+m_engine->ParticleAdapt(0.10f) <= m_time )
{
m_lastParticleSmoke = m_time;
Math::Point dim;
dim.x = Math::Rand()*m_size/3.0f+m_size/3.0f;
dim.y = dim.x;
Math::Vector pos = m_pos;
pos.x += (Math::Rand()-0.5f)*m_size*0.5f;
pos.z += (Math::Rand()-0.5f)*m_size*0.5f;
m_terrain->AdjustToFloor(pos);
Math::Vector speed;
speed.x = 0.0f;
speed.z = 0.0f;
speed.y = -dim.x/2.0f/4.0f;
pos.y += dim.x/2.0f;
ParticleType type;
int r = rand()%2;
if (r == 0) type = PARTISMOKE1;
if (r == 1) type = PARTISMOKE2;
m_particle->CreateParticle(pos, speed, dim, type, 6.0f);
}
if ( (m_type == PT_FRAGO || m_type == PT_EXPLOO) &&
m_progress < 0.03f &&
m_lastParticle+m_engine->ParticleAdapt(0.1f) <= m_time )
{
m_lastParticle = m_time;
Math::Vector pos = m_pos;
Math::Vector speed;
speed.x = (Math::Rand()-0.5f)*m_size*2.0f;
speed.z = (Math::Rand()-0.5f)*m_size*2.0f;
speed.y = Math::Rand()*m_size*1.0f;
Math::Point dim;
dim.x = Math::Rand()*m_size/2.0f+m_size/2.0f;
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, PARTIEXPLOO);
}
if ( (m_type == PT_FRAGW || m_type == PT_EXPLOW) &&
m_progress < 0.05f &&
m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
{
m_lastParticle = m_time;
Math::Vector pos = m_pos;
Math::Vector speed;
speed.x = (Math::Rand()-0.5f)*m_size*1.0f;
speed.z = (Math::Rand()-0.5f)*m_size*1.0f;
speed.y = Math::Rand()*m_size*0.50f;
Math::Point dim;
dim.x = 1.0f;
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f);
}
if ( (m_type == PT_FRAGW || m_type == PT_EXPLOW) &&
m_progress < 0.25f &&
m_lastParticleSmoke+m_engine->ParticleAdapt(0.05f) <= m_time )
{
m_lastParticleSmoke = m_time;
Math::Vector pos = m_pos;
pos.y -= 2.0f;
pos.x += (Math::Rand()-0.5f)*4.0f;
pos.z += (Math::Rand()-0.5f)*4.0f;
Math::Vector speed;
speed.x = 0.0f;
speed.z = 0.0f;
speed.y = 4.0f+Math::Rand()*4.0f;
Math::Point dim;
dim.x = Math::Rand()*2.5f+2.0f;
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, PARTICRASH, 4.0f);
}
}
void CFragExploOrShotPyro::AfterEnd()
{
if ( m_type == PT_EXPLOT ||
m_type == PT_EXPLOO ||
m_type == PT_EXPLOW ) // explosion?
{
DeleteObject(true, false); // removes the main object
}
}

View File

@ -0,0 +1,54 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.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
*/
#include "graphics/pyro/pyro.h"
#include "object/old_object.h"
#include "sound/sound.h"
// old_object.h only needed for OBJECTMAXPART - TODO improve this
using namespace Gfx;
CFragVPyro::CFragVPyro(CObject *obj)
: CPyro(obj)
{}
bool CFragVPyro::EventProcess(const Event& event)
{
// Destroys the object that exploded.
//It should not be destroyed at the end of the Create,
//because it is sometimes the object itself that makes the Create:
// pyro->Create(PT_FRAGT, this);
DeleteObject(true, true);
return CPyro::EventProcess(event);
}
void CFragVPyro::AfterCreate()
{
m_sound->Play(SOUND_BOUMv, m_pos);
m_engine->DeleteShadowSpot(m_object->GetObjectRank(0));
for (int part = 0; part < OBJECTMAXPART; part++)
{
CreateTriangle(m_object, m_object->GetType(), part, 5, 15, 20, 40, 0.30f);
}
}

View File

@ -0,0 +1,86 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.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
*/
#include "graphics/engine/particle.h"
#include "graphics/pyro/pyro.h"
#include "graphics/pyro/pyro_manager.h"
#include "object/object.h"
using namespace Gfx;
CResetPyro::CResetPyro(CObject *obj)
: CPyro(obj)
{}
void CResetPyro::AfterCreate()
{
m_speed = 1.0f/2.0f;
m_resetAngle = m_object->GetRotationY();
LightOperAdd(0.00f, 1.0f, 4.0f, 4.0f, 2.0f); // yellow
LightOperAdd(1.00f, 0.0f, 4.0f, 4.0f, 2.0f); // yellow
CreateLight(m_pos, 40.0f);
}
void CResetPyro::UpdateEffect()
{
if ( m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
{
m_lastParticle = m_time;
Math::Vector pos = m_pos;
pos.x += (Math::Rand()-0.5f)*5.0f;
pos.z += (Math::Rand()-0.5f)*5.0f;
Math::Vector speed;
speed.x = 0.0f;
speed.z = 0.0f;
speed.y = 5.0f+Math::Rand()*5.0f;
Math::Point dim;
dim.x = Math::Rand()*2.0f+2.0f;
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, PARTIGLINTb, 2.0f);
pos = m_pos;
speed.x = (Math::Rand()-0.5f)*20.0f;
speed.z = (Math::Rand()-0.5f)*20.0f;
speed.y = Math::Rand()*10.0f;
speed *= 0.5f+m_progress*0.5f;
dim.x = 0.6f;
dim.y = dim.x;
pos.y += dim.y;
float duration = Math::Rand()*1.5f+1.5f;
m_particle->CreateTrack(pos, speed, dim, PARTITRACK6,
duration, 0.0f,
duration*0.9f, 0.7f);
}
if(m_object != nullptr)
{
float angle = m_resetAngle;
m_object->SetRotationY(angle-powf((1.0f-m_progress)*5.0f, 2.0f));
m_object->SetScale(m_progress);
}
}
void CResetPyro::AfterEnd()
{
m_object->SetRotationY(m_resetAngle);
m_object->SetScale(1.0f);
}

View File

@ -0,0 +1,108 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.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
*/
#include "graphics/engine/particle.h"
#include "graphics/pyro/pyro.h"
#include "graphics/pyro/pyro_manager.h"
#include "level/robotmain.h"
#include "math/geometry.h"
#include "object/object.h"
#include "object/old_object.h"
#include "sound/sound.h"
using namespace Gfx;
CSpiderPyro::CSpiderPyro(CObject *obj)
: CPyro(obj)
{}
bool CSpiderPyro::EventProcess(const Event& event)
{
// Destroys the object that exploded.
//It should not be destroyed at the end of the Create,
//because it is sometimes the object itself that makes the Create:
// pyro->Create(PT_FRAGT, this);
DeleteObject(true, true);
return CPyro::EventProcess(event);
}
void CSpiderPyro::AfterCreate()
{
m_sound->Play(SOUND_EXPLOi, m_pos);
m_speed = 1.0f/15.0f;
Math::Vector pos(-3.0f, 2.0f, 0.0f);
Math::Matrix* mat = m_object->GetWorldMatrix(0);
m_pos = Math::Transform(*mat, pos);
m_engine->DeleteShadowSpot(m_object->GetObjectRank(0));
LightOperAdd(0.00f, 0.0f, -0.5f, -1.0f, -1.0f); // dark red
LightOperAdd(0.05f, 1.0f, -0.5f, -1.0f, -1.0f); // dark red
LightOperAdd(1.00f, 0.0f, -0.5f, -1.0f, -1.0f); // dark red
CreateLight(m_pos, 40.0f);
for (int part = 0; part < OBJECTMAXPART; part++)
{
CreateTriangle(m_object, m_object->GetType(), part, 5, 20, 15, 25);
}
for (int i = 0; i < 50; i++)
{
pos = m_pos;
pos.x += (Math::Rand()-0.5f)*3.0f;
pos.z += (Math::Rand()-0.5f)*3.0f;
pos.y += (Math::Rand()-0.5f)*2.0f;
Math::Vector speed;
speed.x = (Math::Rand()-0.5f)*24.0f;
speed.z = (Math::Rand()-0.5f)*24.0f;
speed.y = 10.0f+Math::Rand()*10.0f;
Math::Point dim;
dim.x = 1.0f;
dim.y = dim.x;
int channel = m_particle->CreateParticle(pos, speed, dim, PARTIGUN3, 2.0f+Math::Rand()*2.0f, 10.0f);
m_particle->SetObjectFather(channel, m_object);
}
int total = static_cast<int>(10.0f*m_engine->GetParticleDensity());
for (int i = 0; i < total; i++)
{
pos = m_pos;
pos.x += (Math::Rand()-0.5f)*3.0f;
pos.z += (Math::Rand()-0.5f)*3.0f;
pos.y += (Math::Rand()-0.5f)*2.0f;
Math::Vector speed;
speed.x = (Math::Rand()-0.5f)*24.0f;
speed.z = (Math::Rand()-0.5f)*24.0f;
speed.y = 7.0f+Math::Rand()*7.0f;
Math::Point dim;
dim.x = 1.0f;
dim.y = dim.x;
m_particle->CreateTrack(pos, speed, dim, PARTITRACK3,
2.0f+Math::Rand()*2.0f, 10.0f, 2.0f, 0.6f);
}
m_camera->StartEffect(CAM_EFFECT_EXPLO, m_pos, 1.0f);
}

View File

@ -0,0 +1,53 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.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
*/
#include "graphics/engine/particle.h"
#include "graphics/pyro/pyro.h"
#include "graphics/pyro/pyro_manager.h"
#include "object/object.h"
using namespace Gfx;
CSquashPyro::CSquashPyro(CObject *obj)
: CPyro(obj)
{}
void CSquashPyro::AfterCreate()
{
m_speed = 1.0f/2.0f;
m_object->SetLock(true);
}
void CSquashPyro::UpdateEffect()
{
if ( m_object != nullptr )
{
m_object->SetScaleY(1.0f-sinf(m_progress)*0.5f);
}
}
void CSquashPyro::AfterEnd()
{
if ( m_object != nullptr )
{
m_object->SetType(OBJECT_PLANT19);
}
}

View File

@ -0,0 +1,94 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.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
*/
#include "graphics/engine/particle.h"
#include "graphics/pyro/pyro.h"
#include "graphics/pyro/pyro_manager.h"
#include "object/object.h"
#include "sound/sound.h"
using namespace Gfx;
CWaypointHitPyro::CWaypointHitPyro(CObject *obj)
: CPyro(obj)
{}
void CWaypointHitPyro::AfterCreate()
{
m_sound->Play(SOUND_WAYPOINT, m_pos);
LightOperAdd(0.00f, 1.0f, 4.0f, 4.0f, 2.0f); // yellow
LightOperAdd(1.00f, 0.0f, 4.0f, 4.0f, 2.0f); // yellow
CreateLight(m_pos, 40.0f);
m_speed = 1.0f/8.0f;
m_object->SetLock(true); // object more functional
}
void CWaypointHitPyro::AfterEnd()
{
DeleteObject(true, true);
}
void CWaypointHitPyro::UpdateEffect()
{
float factor;
if (m_progress < 0.25f)
factor = 0.0f;
else
factor = powf((m_progress-0.25f)/0.75f, 2.0f)*30.0f;
if ( m_progress < 0.85f &&
m_lastParticle+m_engine->ParticleAdapt(0.10f) <= m_time )
{
m_lastParticle = m_time;
Math::Vector pos = m_pos;
pos.y += factor;
pos.x += (Math::Rand()-0.5f)*3.0f;
pos.z += (Math::Rand()-0.5f)*3.0f;
Math::Vector speed;
speed.x = 0.0f;
speed.z = 0.0f;
speed.y = 5.0f+Math::Rand()*5.0f;
Math::Point dim;
dim.x = Math::Rand()*1.5f+1.5f;
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, PARTIGLINT, 2.0f);
}
if(m_object != nullptr)
{
Math::Vector angle = m_object->GetRotation();
angle.y = m_progress*20.0f;
angle.x = sinf(m_progress*49.0f)*0.3f;
angle.z = sinf(m_progress*47.0f)*0.2f;
m_object->SetRotation(angle);
Math::Vector pos = m_pos;
pos.y += factor;
m_object->SetPosition(pos);
if ( m_progress > 0.85f )
{
m_object->SetScale(1.0f-(m_progress-0.85f)/0.15f);
}
}
}

View File

@ -0,0 +1,96 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.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
*/
#include "graphics/engine/particle.h"
#include "graphics/pyro/pyro.h"
#include "graphics/pyro/pyro_manager.h"
#include "object/object.h"
#include "sound/sound.h"
using namespace Gfx;
CWinPyro::CWinPyro(CObject *obj)
: CPyro(obj)
{}
CLostPyro::CLostPyro(CObject *obj)
: CPyro(obj)
{}
void CWinPyro::UpdateEffect()
{
if ( m_object == nullptr )
return;
if ( m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
{
m_lastParticle = m_time;
Math::Vector pos = m_object->GetPosition();
pos.y += 1.5f;
Math::Vector speed;
speed.x = (Math::Rand()-0.5f)*10.0f;
speed.z = (Math::Rand()-0.5f)*10.0f;
speed.y = 8.0f+Math::Rand()*8.0f;
Math::Point dim;
dim.x = Math::Rand()*0.2f+0.2f;
dim.y = dim.x;
m_particle->CreateTrack(pos, speed, dim,
static_cast<ParticleType>(PARTITRACK7+rand()%4),
3.0f, 20.0f, 1.0f, 0.4f);
}
}
void CLostPyro::UpdateEffect()
{
if ( m_object == nullptr )
return;
if ( m_lastParticle+m_engine->ParticleAdapt(0.10f) <= m_time )
{
m_lastParticle = m_time;
Math::Vector pos = m_object->GetPosition();
pos.y -= 2.0f;
pos.x += (Math::Rand()-0.5f)*10.0f;
pos.z += (Math::Rand()-0.5f)*10.0f;
Math::Vector speed;
speed.x = 0.0f;
speed.z = 0.0f;
speed.y = 1.0f+Math::Rand()*1.0f;
Math::Point dim;
dim.x = Math::Rand()*1.0f+1.0f;
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, PARTISMOKE1, 8.0f, 0.0f, 0.0f);
}
}
Error CWinPyro::IsEnded()
{
return ERR_CONTINUE;
}
Error CLostPyro::IsEnded()
{
return ERR_CONTINUE;
}

View File

@ -1000,44 +1000,6 @@ CScoreboard::SortType CLevelParserParam::AsSortType(CScoreboard::SortType def)
return AsSortType(); return AsSortType();
} }
Gfx::PyroType CLevelParserParam::ToPyroType(std::string value)
{
if (value == "FRAGt" ) return Gfx::PT_FRAGT;
if (value == "FRAGo" ) return Gfx::PT_FRAGO;
if (value == "FRAGw" ) return Gfx::PT_FRAGW;
if (value == "EXPLOt") return Gfx::PT_EXPLOT;
if (value == "EXPLOo") return Gfx::PT_EXPLOO;
if (value == "EXPLOw") return Gfx::PT_EXPLOW;
if (value == "SHOTt" ) return Gfx::PT_SHOTT;
if (value == "SHOTh" ) return Gfx::PT_SHOTH;
if (value == "SHOTm" ) return Gfx::PT_SHOTM;
if (value == "SHOTw" ) return Gfx::PT_SHOTW;
if (value == "EGG" ) return Gfx::PT_EGG;
if (value == "BURNt" ) return Gfx::PT_BURNT;
if (value == "BURNo" ) return Gfx::PT_BURNO;
if (value == "SPIDER") return Gfx::PT_SPIDER;
if (value == "FALL" ) return Gfx::PT_FALL;
if (value == "RESET" ) return Gfx::PT_RESET;
if (value == "WIN" ) return Gfx::PT_WIN;
if (value == "LOST" ) return Gfx::PT_LOST;
return static_cast<Gfx::PyroType>(Cast<int>(value, "pyrotype"));
}
Gfx::PyroType CLevelParserParam::AsPyroType()
{
if (m_empty)
throw CLevelParserExceptionMissingParam(this);
return ToPyroType(m_value);
}
Gfx::PyroType CLevelParserParam::AsPyroType(Gfx::PyroType def)
{
if (m_empty)
return def;
return AsPyroType();
}
Gfx::CameraType CLevelParserParam::ToCameraType(std::string value) Gfx::CameraType CLevelParserParam::ToCameraType(std::string value)
{ {
if (value == "BACK" ) return Gfx::CAM_TYPE_BACK; if (value == "BACK" ) return Gfx::CAM_TYPE_BACK;

View File

@ -28,7 +28,6 @@
#include "graphics/engine/camera.h" #include "graphics/engine/camera.h"
#include "graphics/engine/planet_type.h" #include "graphics/engine/planet_type.h"
#include "graphics/engine/pyro_type.h"
#include "graphics/engine/water.h" #include "graphics/engine/water.h"
#include "level/scoreboard.h" #include "level/scoreboard.h"
@ -88,7 +87,6 @@ public:
int AsBuildFlag(); int AsBuildFlag();
int AsResearchFlag(); int AsResearchFlag();
CScoreboard::SortType AsSortType(); CScoreboard::SortType AsSortType();
Gfx::PyroType AsPyroType();
Gfx::CameraType AsCameraType(); Gfx::CameraType AsCameraType();
MissionType AsMissionType(); MissionType AsMissionType();
const CLevelParserParamVec& AsArray(); const CLevelParserParamVec& AsArray();
@ -112,7 +110,6 @@ public:
int AsBuildFlag(int def); int AsBuildFlag(int def);
int AsResearchFlag(int def); int AsResearchFlag(int def);
CScoreboard::SortType AsSortType(CScoreboard::SortType def); CScoreboard::SortType AsSortType(CScoreboard::SortType def);
Gfx::PyroType AsPyroType(Gfx::PyroType def);
Gfx::CameraType AsCameraType(Gfx::CameraType def); Gfx::CameraType AsCameraType(Gfx::CameraType def);
MissionType AsMissionType(MissionType def); MissionType AsMissionType(MissionType def);
//@} //@}
@ -144,7 +141,6 @@ private:
int ToBuildFlag(std::string value); int ToBuildFlag(std::string value);
int ToResearchFlag(std::string value); int ToResearchFlag(std::string value);
CScoreboard::SortType ToSortType(std::string value); CScoreboard::SortType ToSortType(std::string value);
Gfx::PyroType ToPyroType(std::string value);
Gfx::CameraType ToCameraType(std::string value); Gfx::CameraType ToCameraType(std::string value);
MissionType ToMissionType(std::string value); MissionType ToMissionType(std::string value);

View File

@ -45,13 +45,15 @@
#include "graphics/engine/oldmodelmanager.h" #include "graphics/engine/oldmodelmanager.h"
#include "graphics/engine/particle.h" #include "graphics/engine/particle.h"
#include "graphics/engine/planet.h" #include "graphics/engine/planet.h"
#include "graphics/engine/pyro_manager.h"
#include "graphics/engine/terrain.h" #include "graphics/engine/terrain.h"
#include "graphics/engine/text.h" #include "graphics/engine/text.h"
#include "graphics/engine/water.h" #include "graphics/engine/water.h"
#include "graphics/model/model_manager.h" #include "graphics/model/model_manager.h"
#include "graphics/pyro/pyro.h"
#include "graphics/pyro/pyro_manager.h"
#include "level/mainmovie.h" #include "level/mainmovie.h"
#include "level/player_profile.h" #include "level/player_profile.h"
#include "level/scene_conditions.h" #include "level/scene_conditions.h"
@ -2044,7 +2046,8 @@ bool CRobotMain::DestroySelectedObject()
if (obj == nullptr) return false; if (obj == nullptr) return false;
assert(obj->Implements(ObjectInterfaceType::Controllable)); assert(obj->Implements(ObjectInterfaceType::Controllable));
m_engine->GetPyroManager()->Create(Gfx::PT_FRAGT, obj); m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CFragExploOrShotPyro>(Gfx::PT_FRAGT, obj));
NotifyObjectDestroyed(obj);
dynamic_cast<CControllableObject&>(*obj).SetSelect(false); // deselects the object dynamic_cast<CControllableObject&>(*obj).SetSelect(false); // deselects the object
m_camera->SetType(Gfx::CAM_TYPE_EXPLO); m_camera->SetType(Gfx::CAM_TYPE_EXPLO);
@ -2402,7 +2405,7 @@ bool CRobotMain::EventFrame(const Event &event)
obj->SetProxyActivate(false); obj->SetProxyActivate(false);
CreateShortcuts(); CreateShortcuts();
m_sound->Play(SOUND_FINDING); m_sound->Play(SOUND_FINDING);
m_engine->GetPyroManager()->Create(Gfx::PT_FINDING, obj, 0.0f); m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CFindingPyro>(obj));
DisplayError(INFO_FINDING, obj); DisplayError(INFO_FINDING, obj);
} }
} }
@ -5040,7 +5043,7 @@ void CRobotMain::ResetCreate()
{ {
if (obj->GetAnimateOnReset()) if (obj->GetAnimateOnReset())
{ {
m_engine->GetPyroManager()->Create(Gfx::PT_RESET, obj); m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CResetPyro>(obj));
} }
} }
} }
@ -5671,6 +5674,86 @@ void CRobotMain::ClearInterface()
m_tooltipName.clear(); // really removes the tooltip m_tooltipName.clear(); // really removes the tooltip
} }
void CRobotMain::NotifyObjectDestroyed(CObject* pObj)
{
switch (pObj->GetType())
{
case OBJECT_MOTHER:
DisplayError(INFO_DELETEMOTHER, pObj);
break;
case OBJECT_ANT:
DisplayError(INFO_DELETEANT, pObj);
break;
case OBJECT_BEE:
DisplayError(INFO_DELETEBEE, pObj);
break;
case OBJECT_WORM:
DisplayError(INFO_DELETEWORM, pObj);
break;
case OBJECT_SPIDER:
DisplayError(INFO_DELETESPIDER, pObj);
break;
case OBJECT_MOBILEwa:
case OBJECT_MOBILEta:
case OBJECT_MOBILEfa:
case OBJECT_MOBILEia:
case OBJECT_MOBILEwb:
case OBJECT_MOBILEtb:
case OBJECT_MOBILEfb:
case OBJECT_MOBILEib:
case OBJECT_MOBILEwc:
case OBJECT_MOBILEtc:
case OBJECT_MOBILEfc:
case OBJECT_MOBILEic:
case OBJECT_MOBILEwi:
case OBJECT_MOBILEti:
case OBJECT_MOBILEfi:
case OBJECT_MOBILEii:
case OBJECT_MOBILEws:
case OBJECT_MOBILEts:
case OBJECT_MOBILEfs:
case OBJECT_MOBILEis:
case OBJECT_MOBILErt:
case OBJECT_MOBILErc:
case OBJECT_MOBILErr:
case OBJECT_MOBILErs:
case OBJECT_MOBILEsa:
case OBJECT_MOBILEwt:
case OBJECT_MOBILEtt:
case OBJECT_MOBILEft:
case OBJECT_MOBILEit:
case OBJECT_MOBILErp:
case OBJECT_MOBILEst:
case OBJECT_MOBILEdr:
DisplayError(ERR_DELETEMOBILE, pObj);
break;
case OBJECT_DERRICK:
case OBJECT_FACTORY:
case OBJECT_STATION:
case OBJECT_REPAIR:
case OBJECT_DESTROYER:
case OBJECT_TOWER:
case OBJECT_RESEARCH:
case OBJECT_RADAR:
case OBJECT_INFO:
case OBJECT_ENERGY:
case OBJECT_LABO:
case OBJECT_NUCLEAR:
case OBJECT_PARA:
case OBJECT_SAFE:
case OBJECT_HUSTON:
case OBJECT_START:
case OBJECT_END:
DisplayError(ERR_DELETEBUILDING, pObj);
break;
default:
break;
}
}
void CRobotMain::DisplayError(Error err, CObject* pObj, float time) void CRobotMain::DisplayError(Error err, CObject* pObj, float time)
{ {
m_displayText->DisplayError(err, pObj, time); m_displayText->DisplayError(err, pObj, time);

View File

@ -341,6 +341,8 @@ public:
//! Find the currently selected object //! Find the currently selected object
CObject* GetSelect(); CObject* GetSelect();
//! Display an appropriate message banner for an object's destruction ("Bot destroyed" / "Building destroyed")
void NotifyObjectDestroyed(CObject* pObj);
void DisplayError(Error err, CObject* pObj, float time=10.0f); void DisplayError(Error err, CObject* pObj, float time=10.0f);
void DisplayError(Error err, Math::Vector goal, float height=15.0f, float dist=60.0f, float time=10.0f); void DisplayError(Error err, Math::Vector goal, float height=15.0f, float dist=60.0f, float time=10.0f);

View File

@ -22,7 +22,7 @@
#include "common/make_unique.h" #include "common/make_unique.h"
#include "graphics/engine/pyro_manager.h" #include "graphics/pyro/pyro_manager.h"
#include "level/robotmain.h" #include "level/robotmain.h"

View File

@ -22,7 +22,8 @@
#include "common/make_unique.h" #include "common/make_unique.h"
#include "graphics/engine/pyro_manager.h" #include "graphics/pyro/pyro.h"
#include "graphics/pyro/pyro_manager.h"
#include "level/parser/parserline.h" #include "level/parser/parserline.h"
#include "level/parser/parserparam.h" #include "level/parser/parserparam.h"
@ -249,7 +250,7 @@ Error CAutoEgg::IsEnded()
{ {
if ( m_progress < 1.0f ) return ERR_CONTINUE; if ( m_progress < 1.0f ) return ERR_CONTINUE;
m_engine->GetPyroManager()->Create(Gfx::PT_EGG, m_object); // exploding egg m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CEggPyro>(m_object)); // exploding egg
alien->SetScale(1.0f); // this is a big boy now alien->SetScale(1.0f); // this is a big boy now

View File

@ -30,9 +30,11 @@
#include "graphics/engine/lightman.h" #include "graphics/engine/lightman.h"
#include "graphics/engine/lightning.h" #include "graphics/engine/lightning.h"
#include "graphics/engine/particle.h" #include "graphics/engine/particle.h"
#include "graphics/engine/pyro_manager.h"
#include "graphics/engine/terrain.h" #include "graphics/engine/terrain.h"
#include "graphics/pyro/pyro.h"
#include "graphics/pyro/pyro_manager.h"
#include "level/robotmain.h" #include "level/robotmain.h"
#include "level/scoreboard.h" #include "level/scoreboard.h"
@ -450,15 +452,15 @@ bool COldObject::DamageObject(DamageType type, float force, CObject* killer)
if ( m_type == OBJECT_HUMAN ) if ( m_type == OBJECT_HUMAN )
{ {
m_engine->GetPyroManager()->Create(Gfx::PT_SHOTH, this, loss); m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CFragExploOrShotPyro>(Gfx::PT_SHOTH, this, loss));
} }
else if ( m_type == OBJECT_MOTHER ) else if ( m_type == OBJECT_MOTHER )
{ {
m_engine->GetPyroManager()->Create(Gfx::PT_SHOTM, this, loss); m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CFragExploOrShotPyro>(Gfx::PT_SHOTM, this, loss));
} }
else else
{ {
m_engine->GetPyroManager()->Create(Gfx::PT_SHOTT, this, loss); m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CFragExploOrShotPyro>(Gfx::PT_SHOTT, this, loss));
} }
return false; return false;
} }
@ -478,7 +480,6 @@ void COldObject::DestroyObject(DestructionType type, CObject* killer)
SetDamaging(false); SetDamaging(false);
} }
Gfx::PyroType pyroType = Gfx::PT_NULL;
if ( type == DestructionType::Explosion ) // explosion? if ( type == DestructionType::Explosion ) // explosion?
{ {
if ( m_type == OBJECT_ANT || if ( m_type == OBJECT_ANT ||
@ -486,17 +487,20 @@ void COldObject::DestroyObject(DestructionType type, CObject* killer)
m_type == OBJECT_BEE || m_type == OBJECT_BEE ||
m_type == OBJECT_WORM ) m_type == OBJECT_WORM )
{ {
pyroType = Gfx::PT_EXPLOO; m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CFragExploOrShotPyro>(Gfx::PT_EXPLOO, this, 1.0f));
m_main->NotifyObjectDestroyed(this);
} }
else if ( m_type == OBJECT_MOTHER || else if ( m_type == OBJECT_MOTHER ||
m_type == OBJECT_NEST || m_type == OBJECT_NEST ||
m_type == OBJECT_BULLET ) m_type == OBJECT_BULLET )
{ {
pyroType = Gfx::PT_FRAGO; m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CFragExploOrShotPyro>(Gfx::PT_FRAGO, this, 1.0f));
SetDying(DeathType::Exploding);
m_main->NotifyObjectDestroyed(this);
} }
else if ( m_type == OBJECT_HUMAN ) else if ( m_type == OBJECT_HUMAN )
{ {
pyroType = Gfx::PT_DEADG; m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CDeadGPyro>(this));
} }
else if ( m_type == OBJECT_BASE || else if ( m_type == OBJECT_BASE ||
m_type == OBJECT_DERRICK || m_type == OBJECT_DERRICK ||
@ -524,65 +528,60 @@ void COldObject::DestroyObject(DestructionType type, CObject* killer)
m_type == OBJECT_RUINradar || m_type == OBJECT_RUINradar ||
m_type == OBJECT_RUINconvert ) // building? m_type == OBJECT_RUINconvert ) // building?
{ {
pyroType = Gfx::PT_FRAGT; m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CFragExploOrShotPyro>(Gfx::PT_FRAGT, this, 1.0f));
SetDying(DeathType::Exploding);
m_main->NotifyObjectDestroyed(this);
} }
else if ( m_type == OBJECT_MOBILEtg ) else if ( m_type == OBJECT_MOBILEtg )
{ {
pyroType = Gfx::PT_FRAGT; m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CFragExploOrShotPyro>(Gfx::PT_FRAGT, this, 1.0f));
SetDying(DeathType::Exploding);
m_main->NotifyObjectDestroyed(this);
} }
else else
{ {
pyroType = Gfx::PT_EXPLOT; m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CFragExploOrShotPyro>(Gfx::PT_EXPLOT, this, 1.0f));
m_main->NotifyObjectDestroyed(this);
} }
} }
else if ( type == DestructionType::ExplosionWater ) else if ( type == DestructionType::ExplosionWater )
{ {
pyroType = Gfx::PT_FRAGW; m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CFragExploOrShotPyro>(Gfx::PT_FRAGW, this, 1.0f));
SetDying(DeathType::Exploding);
m_main->NotifyObjectDestroyed(this);
} }
else if ( type == DestructionType::Burn ) // burning? else if ( type == DestructionType::Burn ) // burning?
{ {
if ( m_type == OBJECT_MOTHER || if ( m_type == OBJECT_HUMAN )
m_type == OBJECT_ANT ||
m_type == OBJECT_SPIDER ||
m_type == OBJECT_BEE ||
m_type == OBJECT_WORM ||
m_type == OBJECT_BULLET )
{ {
pyroType = Gfx::PT_BURNO; m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CDeadGPyro>(this));
SetDying(DeathType::Burning);
}
else if ( m_type == OBJECT_HUMAN )
{
pyroType = Gfx::PT_DEADG;
} }
else else
{ {
pyroType = Gfx::PT_BURNT; m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CBurnPyro>(this));
SetDying(DeathType::Burning); SetDying(DeathType::Burning);
m_main->NotifyObjectDestroyed(this);
} }
SetVirusMode(false); SetVirusMode(false);
} }
else if ( type == DestructionType::Drowned ) else if ( type == DestructionType::Drowned )
{ {
pyroType = Gfx::PT_DEADW; m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CDeadWPyro>(this));
} }
else if ( type == DestructionType::Win ) else if ( type == DestructionType::Win )
{ {
pyroType = Gfx::PT_WPCHECK; m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CWaypointHitPyro>(this));
} }
else if ( type == DestructionType::Squash ) else if ( type == DestructionType::Squash )
{ {
pyroType = Gfx::PT_SQUASH; m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CSquashPyro>(this));
DeleteAllCrashSpheres(); DeleteAllCrashSpheres();
} }
assert(pyroType != Gfx::PT_NULL); else
if (pyroType == Gfx::PT_FRAGT ||
pyroType == Gfx::PT_FRAGO ||
pyroType == Gfx::PT_FRAGW)
{ {
SetDying(DeathType::Exploding); // should be unreachable
assert(false);
} }
m_engine->GetPyroManager()->Create(pyroType, this);
if ( Implements(ObjectInterfaceType::Programmable) ) if ( Implements(ObjectInterfaceType::Programmable) )
{ {
@ -1155,7 +1154,20 @@ void COldObject::Read(CLevelParserLine* line)
SetCameraLock(line->GetParam("cameraLock")->AsBool(false)); SetCameraLock(line->GetParam("cameraLock")->AsBool(false));
if (line->GetParam("pyro")->IsDefined()) if (line->GetParam("pyro")->IsDefined())
m_engine->GetPyroManager()->Create(line->GetParam("pyro")->AsPyroType(), this); {
if(line->GetParam("pyro")->GetValue() == "WIN")
{
m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CWinPyro>(this));
}
else if(line->GetParam("pyro")->GetValue() == "LOST")
{
m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CLostPyro>(this));
}
else
{
throw CLevelParserExceptionBadParam(line->GetParam("pyro"), "pyrotype");
}
}
SetBulletWall(line->GetParam("bulletWall")->AsBool(IsBulletWallByDefault(m_type))); SetBulletWall(line->GetParam("bulletWall")->AsBool(IsBulletWallByDefault(m_type)));

View File

@ -23,9 +23,11 @@
#include "common/global.h" #include "common/global.h"
#include "graphics/engine/particle.h" #include "graphics/engine/particle.h"
#include "graphics/engine/pyro_manager.h"
#include "graphics/engine/terrain.h" #include "graphics/engine/terrain.h"
#include "graphics/pyro/pyro.h"
#include "graphics/pyro/pyro_manager.h"
#include "level/robotmain.h" #include "level/robotmain.h"
#include "math/geometry.h" #include "math/geometry.h"
@ -89,6 +91,6 @@ void CTaskDeleteMark::DeleteMark()
if (obj != nullptr) if (obj != nullptr)
{ {
m_engine->GetPyroManager()->Create(Gfx::PT_WPCHECK, obj); m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CWaypointHitPyro>(obj));
} }
} }

View File

@ -20,9 +20,11 @@
#include "object/task/taskflag.h" #include "object/task/taskflag.h"
#include "graphics/engine/particle.h" #include "graphics/engine/particle.h"
#include "graphics/engine/pyro_manager.h"
#include "graphics/engine/water.h" #include "graphics/engine/water.h"
#include "graphics/pyro/pyro.h"
#include "graphics/pyro/pyro_manager.h"
#include "math/geometry.h" #include "math/geometry.h"
#include "object/object_manager.h" #include "object/object_manager.h"
@ -283,7 +285,7 @@ Error CTaskFlag::CreateFlag(int rank)
//pNew->SetScale(0.0f); //pNew->SetScale(0.0f);
m_sound->Play(SOUND_WAYPOINT, pos); m_sound->Play(SOUND_WAYPOINT, pos);
m_engine->GetPyroManager()->Create(Gfx::PT_FLCREATE, pNew); m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CFlagCreatePyro>(pNew));
return ERR_OK; return ERR_OK;
} }
@ -321,7 +323,7 @@ Error CTaskFlag::DeleteFlag()
m_sound->Play(SOUND_WAYPOINT, iPos); m_sound->Play(SOUND_WAYPOINT, iPos);
m_engine->GetPyroManager()->Create(Gfx::PT_FLDELETE, pObj); m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CFlagDeletePyro>(pObj));
return ERR_OK; return ERR_OK;
} }

View File

@ -20,9 +20,11 @@
#include "object/task/taskmanip.h" #include "object/task/taskmanip.h"
#include "graphics/engine/pyro_manager.h"
#include "graphics/engine/terrain.h" #include "graphics/engine/terrain.h"
#include "graphics/pyro/pyro.h"
#include "graphics/pyro/pyro_manager.h"
#include "level/robotmain.h" #include "level/robotmain.h"
#include "math/geometry.h" #include "math/geometry.h"
@ -323,7 +325,7 @@ Error CTaskManip::Start(TaskManipOrder order, TaskManipArm arm)
pos.y += 2.0f; pos.y += 2.0f;
m_object->SetPosition(pos); // against the top of jump m_object->SetPosition(pos); // against the top of jump
m_engine->GetPyroManager()->Create(Gfx::PT_FALL, other); // the ball falls m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CFallPyro>(other)); // the ball falls
} }
m_bBee = true; m_bBee = true;

View File

@ -21,7 +21,11 @@
#include "object/task/taskspiderexplo.h" #include "object/task/taskspiderexplo.h"
#include "graphics/engine/engine.h" #include "graphics/engine/engine.h"
#include "graphics/engine/pyro_manager.h"
#include "graphics/pyro/pyro.h"
#include "graphics/pyro/pyro_manager.h"
#include "level/robotmain.h"
#include "object/old_object.h" #include "object/old_object.h"
@ -97,7 +101,8 @@ Error CTaskSpiderExplo::IsEnded()
if ( m_time < 1.0f ) return ERR_CONTINUE; if ( m_time < 1.0f ) return ERR_CONTINUE;
m_engine->GetPyroManager()->Create(Gfx::PT_SPIDER, m_object); // the spider explodes (suicide) m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CSpiderPyro>(m_object)); // the spider explodes (suicide)
m_main->NotifyObjectDestroyed(m_object);
Abort(); Abort();
return ERR_STOP; return ERR_STOP;

View File

@ -20,9 +20,11 @@
#include "object/task/taskterraform.h" #include "object/task/taskterraform.h"
#include "graphics/engine/particle.h" #include "graphics/engine/particle.h"
#include "graphics/engine/pyro_manager.h"
#include "graphics/engine/terrain.h" #include "graphics/engine/terrain.h"
#include "graphics/pyro/pyro.h"
#include "graphics/pyro/pyro_manager.h"
#include "level/robotmain.h" #include "level/robotmain.h"
#include "math/geometry.h" #include "math/geometry.h"
@ -419,13 +421,15 @@ bool CTaskTerraform::Terraform()
type == OBJECT_EGG ) // Alien Organic? type == OBJECT_EGG ) // Alien Organic?
{ {
if ( dist > 5.0f ) continue; if ( dist > 5.0f ) continue;
m_engine->GetPyroManager()->Create(Gfx::PT_FRAGO, pObj); m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CFragExploOrShotPyro>(Gfx::PT_FRAGO, pObj, 1.0f));
m_main->NotifyObjectDestroyed(pObj);
} }
else if ( type == OBJECT_TNT || else if ( type == OBJECT_TNT ||
type == OBJECT_BOMB ) // Explosives? type == OBJECT_BOMB ) // Explosives?
{ {
if ( dist > 5.0f ) continue; if ( dist > 5.0f ) continue;
m_engine->GetPyroManager()->Create(Gfx::PT_EXPLOT, pObj); m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CFragExploOrShotPyro>(Gfx::PT_EXPLOT, pObj, 1.0f));
m_main->NotifyObjectDestroyed(pObj);
dynamic_cast<CDamageableObject&>(*m_object).DamageObject(DamageType::Explosive, 0.9f); dynamic_cast<CDamageableObject&>(*m_object).DamageObject(DamageType::Explosive, 0.9f);
} }
else if ( type == OBJECT_PLANT0 || else if ( type == OBJECT_PLANT0 ||
@ -443,13 +447,14 @@ bool CTaskTerraform::Terraform()
type == OBJECT_PLANT19 ) // Plants? type == OBJECT_PLANT19 ) // Plants?
{ {
if ( dist > 7.5f ) continue; if ( dist > 7.5f ) continue;
m_engine->GetPyroManager()->Create(Gfx::PT_FRAGV, pObj); m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CFragVPyro>(pObj));
} }
else // Other? else // Other?
{ {
if ( dist > 5.0f ) continue; if ( dist > 5.0f ) continue;
m_engine->GetPyroManager()->Create(Gfx::PT_FRAGT, pObj); m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CFragExploOrShotPyro>(Gfx::PT_FRAGT, pObj, 1.0f));
m_main->NotifyObjectDestroyed(pObj);
} }
} }
else else
@ -472,12 +477,12 @@ bool CTaskTerraform::Terraform()
dynamic_cast<CBaseAlien&>(*pObj).SetFixed(true); // not moving dynamic_cast<CBaseAlien&>(*pObj).SetFixed(true); // not moving
if ( dist > 5.0f ) continue; if ( dist > 5.0f ) continue;
m_engine->GetPyroManager()->Create(Gfx::PT_EXPLOO, pObj); m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CFragExploOrShotPyro>(Gfx::PT_EXPLOO, pObj, 1.0f));
} }
else if ( type == OBJECT_BEE || type == OBJECT_WORM ) else if ( type == OBJECT_BEE || type == OBJECT_WORM )
{ {
if ( dist > 5.0f ) continue; if ( dist > 5.0f ) continue;
m_engine->GetPyroManager()->Create(Gfx::PT_EXPLOO, pObj); m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CFragExploOrShotPyro>(Gfx::PT_EXPLOO, pObj, 1.0f));
} }
} }
} }

View File

@ -29,10 +29,12 @@
#include "graphics/engine/camera.h" #include "graphics/engine/camera.h"
#include "graphics/engine/engine.h" #include "graphics/engine/engine.h"
#include "graphics/engine/lightman.h" #include "graphics/engine/lightman.h"
#include "graphics/engine/pyro_manager.h"
#include "graphics/engine/terrain.h" #include "graphics/engine/terrain.h"
#include "graphics/engine/water.h" #include "graphics/engine/water.h"
#include "graphics/pyro/pyro.h"
#include "graphics/pyro/pyro_manager.h"
#include "level/robotmain.h" #include "level/robotmain.h"
#include "level/parser/parserline.h" #include "level/parser/parserline.h"
@ -2545,7 +2547,7 @@ int CPhysics::ObjectAdapt(const Math::Vector &pos, const Math::Vector &angle)
if ( distance < 4.0f ) if ( distance < 4.0f )
{ {
m_sound->Play(SOUND_WAYPOINT, m_object->GetPosition()); m_sound->Play(SOUND_WAYPOINT, m_object->GetPosition());
m_engine->GetPyroManager()->Create(Gfx::PT_WPCHECK, pObj); m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CWaypointHitPyro>(pObj));
} }
} }
@ -2556,7 +2558,7 @@ int CPhysics::ObjectAdapt(const Math::Vector &pos, const Math::Vector &angle)
if ( distance < 10.0f*1.5f ) if ( distance < 10.0f*1.5f )
{ {
m_sound->Play(SOUND_WAYPOINT, m_object->GetPosition()); m_sound->Play(SOUND_WAYPOINT, m_object->GetPosition());
m_engine->GetPyroManager()->Create(Gfx::PT_WPCHECK, pObj); m_engine->GetPyroManager()->Create(MakeUnique<Gfx::CWaypointHitPyro>(pObj));
} }
} }