colobot/colobot-base/graphics/engine/pyro.cpp

2445 lines
74 KiB
C++
Raw Normal View History

/*
* This file is part of the Colobot: Gold Edition source code
2023-08-06 21:15:48 +00:00
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
2015-08-22 14:40:02 +00:00
* 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/pyro.h"
#include "app/app.h"
#include "common/logger.h"
#include "graphics/core/triangle.h"
#include "graphics/engine/engine.h"
2012-10-02 22:30:17 +00:00
#include "graphics/engine/lightman.h"
#include "graphics/engine/particle.h"
#include "graphics/engine/terrain.h"
#include "level/robotmain.h"
2012-10-02 22:30:17 +00:00
#include "math/geometry.h"
#include "object/object_manager.h"
#include "object/old_object.h"
2022-01-29 16:16:57 +00:00
#include "object/interface/slotted_object.h"
2012-10-02 22:30:17 +00:00
#include "object/motion/motionhuman.h"
2015-08-17 12:06:31 +00:00
#include "object/subclass/shielder.h"
2015-08-31 19:47:55 +00:00
#include "sound/sound.h"
2012-09-19 21:50:28 +00:00
// Graphics module namespace
2015-08-02 09:40:47 +00:00
namespace Gfx
{
2012-09-19 21:50:28 +00:00
CPyro::CPyro()
{
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();
}
2012-09-19 21:50:28 +00:00
CPyro::~CPyro()
{
}
2012-10-02 22:30:17 +00:00
void CPyro::DeleteObject()
{
2012-10-02 22:30:17 +00:00
if ( m_lightRank != -1 )
{
m_lightMan->DeleteLight(m_lightRank);
m_lightRank = -1;
}
}
2012-10-02 22:30:17 +00:00
bool CPyro::Create(PyroType type, CObject* obj, float force)
{
2012-10-02 22:30:17 +00:00
m_object = obj;
m_force = force;
ObjectType oType = obj->GetType();
int objRank = obj->GetObjectRank(0);
if (objRank == -1) return false;
glm::vec3 min{}, max{};
2012-10-02 22:30:17 +00:00
m_engine->GetObjectBBox(objRank, min, max);
glm::vec3 pos = obj->GetPosition();
2012-10-02 22:30:17 +00:00
DisplayError(type, obj); // displays eventual messages
for (const auto& crashSphere : obj->GetAllCrashSpheres())
2012-10-02 22:30:17 +00:00
{
m_crashSpheres.push_back(crashSphere.sphere);
2012-10-02 22:30:17 +00:00
}
// 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 = glm::distance(min, max)*2.0f;
2012-10-02 22:30:17 +00:00
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_type = type;
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;
}
2012-10-02 22:30:17 +00:00
// Seeking the position of the battery.
2015-07-10 21:47:59 +00:00
2022-01-29 16:16:57 +00:00
CObject* power = GetObjectInPowerCellSlot(obj);
2015-07-10 21:47:59 +00:00
if (power == nullptr)
2012-10-02 22:30:17 +00:00
{
m_power = false;
}
else
{
m_power = true;
pos = power->GetPosition();
2012-10-02 22:30:17 +00:00
pos.y += 1.0f;
glm::mat4 mat = obj->GetWorldMatrix(0);
m_posPower = Math::Transform(mat, pos);
2012-10-02 22:30:17 +00:00
}
2015-07-10 21:47:59 +00:00
2012-10-02 22:30:17 +00:00
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;
glm::mat4 mat = obj->GetWorldMatrix(0);
m_posPower = Math::Transform(mat, glm::vec3(-15.0f, 7.0f, 0.0f));
2012-10-02 22:30:17 +00:00
m_pos = m_posPower;
}
if ( oType == OBJECT_ENERGY )
{
m_power = true;
glm::mat4 mat = obj->GetWorldMatrix(0);
m_posPower = Math::Transform(mat, glm::vec3(-7.0f, 6.0f, 0.0f));
2012-10-02 22:30:17 +00:00
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;
}
// Plays the sound of a pyrotechnic effect.
if ( type == PT_FRAGT ||
type == PT_FRAGW ||
type == PT_EXPLOT ||
type == PT_EXPLOW )
{
SoundType sound;
2012-10-02 22:30:17 +00:00
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 ( type == PT_FRAGO ||
type == PT_EXPLOO ||
type == PT_SPIDER ||
type == PT_SHOTM )
{
m_sound->Play(SOUND_EXPLOi, m_pos);
}
2019-07-21 23:15:11 +00:00
if ( type == PT_FRAGV )
{
m_sound->Play(SOUND_BOUMv, m_pos);
}
2012-10-02 22:30:17 +00:00
if ( type == PT_BURNT ||
type == PT_BURNO )
{
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 ( type == PT_BURNO )
{
m_sound->Play(SOUND_DEADi, m_pos);
m_sound->Play(SOUND_DEADi, m_engine->GetEyePt());
}
if ( type == PT_EGG )
{
m_sound->Play(SOUND_EGG, m_pos);
}
if ( type == PT_WPCHECK ||
type == PT_FLCREATE ||
type == PT_FLDELETE )
{
m_sound->Play(SOUND_WAYPOINT, m_pos);
}
if ( oType == OBJECT_HUMAN )
{
if ( type == PT_DEADG )
{
m_sound->Play(SOUND_DEADg, m_pos);
}
if ( type == PT_DEADW )
{
m_sound->Play(SOUND_DEADw, m_pos);
}
2015-08-10 21:20:36 +00:00
assert(m_object->Implements(ObjectInterfaceType::Controllable));
if ( type == PT_SHOTH && dynamic_cast<CControllableObject&>(*m_object).GetSelect() )
2012-10-02 22:30:17 +00:00
{
m_sound->Play(SOUND_AIE, m_pos);
m_sound->Play(SOUND_AIE, m_engine->GetEyePt());
}
}
if ( m_type == PT_FRAGT ||
m_type == PT_FRAGO ||
2019-07-21 23:15:11 +00:00
m_type == PT_FRAGW ||
m_type == PT_FRAGV )
2012-10-02 22:30:17 +00:00
{
m_engine->DeleteShadowSpot(m_object->GetObjectRank(0));
2012-10-02 22:30:17 +00:00
}
if ( m_type == PT_DEADG )
{
assert(m_object->Implements(ObjectInterfaceType::Destroyable));
dynamic_cast<CDestroyableObject&>(*m_object).SetDying(DeathType::Dead);
2012-10-02 22:30:17 +00:00
assert(obj->Implements(ObjectInterfaceType::Movable));
dynamic_cast<CMovableObject&>(*obj).GetMotion()->SetAction(MHS_DEADg, 1.0f);
2012-10-02 22:30:17 +00:00
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;
return true;
}
if ( m_type == PT_DEADW )
{
assert(m_object->Implements(ObjectInterfaceType::Destroyable));
dynamic_cast<CDestroyableObject&>(*m_object).SetDying(DeathType::Dead);
2012-10-02 22:30:17 +00:00
assert(obj->Implements(ObjectInterfaceType::Movable));
dynamic_cast<CMovableObject&>(*obj).GetMotion()->SetAction(MHS_DEADw, 1.0f);
2012-10-02 22:30:17 +00:00
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;
return true;
}
if ( m_type == PT_SHOTT ||
m_type == PT_SHOTM )
{
m_camera->StartEffect(CAM_EFFECT_SHOT, m_pos, force);
m_speed = 1.0f/1.0f;
return true;
}
if ( m_type == PT_SHOTH )
{
2015-08-10 21:20:36 +00:00
assert(m_object->Implements(ObjectInterfaceType::Controllable));
if ( m_camera->GetBlood() && dynamic_cast<CControllableObject&>(*m_object).GetSelect() )
2012-10-02 22:30:17 +00:00
{
m_camera->StartOver(CAM_OVER_EFFECT_BLOOD, m_pos, force);
}
m_speed = 1.0f/0.2f;
return true;
}
if ( m_type == PT_SHOTW )
{
m_speed = 1.0f/1.0f;
}
if ( m_type == PT_BURNT )
{
BurnStart();
}
if ( m_type == PT_WPCHECK )
{
m_speed = 1.0f/8.0f;
m_object->SetLock(true); // object more functional
2012-10-02 22:30:17 +00:00
}
if ( m_type == PT_FLCREATE )
{
m_speed = 1.0f/2.0f;
}
if ( m_type == PT_FLDELETE )
{
m_speed = 1.0f/2.0f;
m_object->SetLock(true); // object more functional
2012-10-02 22:30:17 +00:00
}
if ( m_type == PT_RESET )
{
m_speed = 1.0f/2.0f;
m_resetAngle = m_object->GetRotationY();
2012-10-02 22:30:17 +00:00
}
if ( m_type == PT_FINDING )
{
float limit = (m_size-1.0f)/4.0f;
if (limit > 8.0f) limit = 8.0f;
if (oType == OBJECT_APOLLO2) limit = 2.0f;
m_speed = 1.0f/limit;
}
if ( m_type == PT_SQUASH )
{
m_speed = 1.0f/2.0f;
m_object->SetLock(true);
}
2012-10-02 22:30:17 +00:00
if ( m_type == PT_EXPLOT ||
m_type == PT_EXPLOO ||
m_type == PT_EXPLOW )
{
CreateTriangle(obj, oType, 0);
m_engine->DeleteShadowSpot(m_object->GetObjectRank(0));
2012-10-02 22:30:17 +00:00
ExploStart();
}
if ( m_type == PT_FALL )
{
FallStart();
return true;
}
if ( m_type == PT_BURNT ||
m_type == PT_BURNO )
{
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);
return true;
}
if ( m_type == PT_SPIDER )
{
m_speed = 1.0f/15.0f;
pos = glm::vec3(-3.0f, 2.0f, 0.0f);
glm::mat4 mat = obj->GetWorldMatrix(0);
m_pos = Math::Transform(mat, pos);
2012-10-02 22:30:17 +00:00
m_engine->DeleteShadowSpot(m_object->GetObjectRank(0));
2012-10-02 22:30:17 +00:00
}
2019-07-21 23:15:11 +00:00
if ( m_type != PT_FRAGV &&
m_type != PT_EGG &&
m_type != PT_WIN &&
m_type != PT_LOST &&
m_type != PT_SQUASH)
2012-10-02 22:30:17 +00:00
{
float h = 40.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
h = m_size*2.0f;
}
else if ( m_type == PT_SPIDER )
{
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
}
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
}
else if ( m_type == PT_WPCHECK ||
m_type == PT_FLCREATE ||
m_type == PT_FLDELETE ||
m_type == PT_RESET ||
m_type == PT_FINDING )
{
LightOperAdd(0.00f, 1.0f, 4.0f, 4.0f, 2.0f); // yellow
LightOperAdd(1.00f, 0.0f, 4.0f, 4.0f, 2.0f); // yellow
}
else
{
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
}
CreateLight(m_pos, h);
if ( m_type != PT_SHOTW &&
m_type != PT_WPCHECK &&
m_type != PT_FLCREATE &&
m_type != PT_FLDELETE &&
m_type != PT_RESET &&
m_type != PT_FINDING &&
m_type != PT_SQUASH )
2012-10-02 22:30:17 +00:00
{
m_camera->StartEffect(CAM_EFFECT_EXPLO, m_pos, force);
}
}
if ( m_type == PT_SHOTW ) return true;
// Generates the triangles of the explosion.
if ( m_type == PT_FRAGT ||
m_type == PT_FRAGO ||
m_type == PT_FRAGW ||
2019-07-21 23:15:11 +00:00
m_type == PT_FRAGV ||
2012-10-02 22:30:17 +00:00
m_type == PT_SPIDER ||
m_type == PT_EGG ||
(m_type == PT_EXPLOT && oType == OBJECT_MOBILEtg) ||
(m_type == PT_EXPLOT && oType == OBJECT_TEEN28 ) ||
(m_type == PT_EXPLOT && oType == OBJECT_TEEN31 ) )
2012-10-02 22:30:17 +00:00
{
for (int part = 0; part < OBJECTMAXPART; part++)
{
CreateTriangle(obj, oType, 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++)
{
pos = m_posPower;
glm::vec3 speed{};
2012-10-02 22:30:17 +00:00
speed.x = (Math::Rand()-0.5f)*30.0f;
speed.z = (Math::Rand()-0.5f)*30.0f;
speed.y = Math::Rand()*30.0f;
glm::vec2 dim;
2012-10-02 22:30:17 +00:00
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)?
{
if (m_power)
{
pos = m_posPower;
}
else
{
pos = m_pos;
m_terrain->AdjustToFloor(pos);
pos.y += 1.0f;
}
glm::vec2 dim;
2012-10-02 22:30:17 +00:00
dim.x = m_size*0.4f;
dim.y = dim.x;
m_particle->CreateParticle(pos, glm::vec3(0.0f,0.0f,0.0f), dim, PARTISPHERE0, 2.0f, 0.0f, 0.0f);
2012-10-02 22:30:17 +00:00
}
}
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++)
{
pos = m_pos;
glm::vec3 speed{};
2012-10-02 22:30:17 +00:00
speed.x = (Math::Rand()-0.5f)*30.0f;
speed.z = (Math::Rand()-0.5f)*30.0f;
speed.y = Math::Rand()*50.0f;
glm::vec2 dim;
2012-10-02 22:30:17 +00:00
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++)
{
pos = m_pos;
glm::vec3 speed{};
2012-10-02 22:30:17 +00:00
speed.x = (Math::Rand()-0.5f)*30.0f;
speed.z = (Math::Rand()-0.5f)*30.0f;
speed.y = Math::Rand()*50.0f;
glm::vec2 dim;
2012-10-02 22:30:17 +00:00
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_SPIDER )
{
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;
glm::vec3 speed{};
2012-10-02 22:30:17 +00:00
speed.x = (Math::Rand()-0.5f)*24.0f;
speed.z = (Math::Rand()-0.5f)*24.0f;
speed.y = 10.0f+Math::Rand()*10.0f;
glm::vec2 dim;
2012-10-02 22:30:17 +00:00
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, obj);
}
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;
glm::vec3 speed{};
2012-10-02 22:30:17 +00:00
speed.x = (Math::Rand()-0.5f)*24.0f;
speed.z = (Math::Rand()-0.5f)*24.0f;
speed.y = 7.0f+Math::Rand()*7.0f;
glm::vec2 dim{};
2012-10-02 22:30:17 +00:00
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);
}
}
if ( type == PT_FRAGT ||
type == PT_FRAGW ||
type == PT_EXPLOT ||
type == PT_EXPLOW )
{
if (m_size > 10.0f || m_power)
{
pos = m_pos;
glm::vec3 speed(0.0f, 0.0f, 0.0f);
glm::vec2 dim;
2012-10-02 22:30:17 +00:00
dim.x = m_size;
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, PARTICHOC, 2.0f);
}
}
return true;
}
2012-09-19 21:50:28 +00:00
bool CPyro::EventProcess(const Event &event)
{
2012-10-02 22:30:17 +00:00
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)
2012-10-02 22:30:17 +00:00
{
glm::vec3 pos = m_object->GetPosition();
2012-10-02 22:30:17 +00:00
m_sound->Position(m_soundChannel, pos);
if (m_lightRank != -1)
{
pos.y += m_lightHeight;
m_lightMan->SetLightPos(m_lightRank, pos);
}
}
if ( m_type == PT_SHOTT &&
m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
{
m_lastParticle = m_time;
if (m_crashSpheres.size() > 0)
2012-10-02 22:30:17 +00:00
{
int i = rand() % m_crashSpheres.size();
glm::vec3 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;
glm::vec3 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;
glm::vec2 dim{};
dim.x = Math::Rand()*radius*0.5f+radius*0.75f*m_force;
2012-10-02 22:30:17 +00:00
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, PARTISMOKE1, 3.0f);
}
else
{
glm::vec3 pos = m_pos;
2012-10-02 22:30:17 +00:00
pos.x += (Math::Rand()-0.5f)*m_size*0.3f;
pos.z += (Math::Rand()-0.5f)*m_size*0.3f;
glm::vec3 speed{};
2012-10-02 22:30:17 +00:00
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;
glm::vec2 dim;
2012-10-02 22:30:17 +00:00
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);
}
}
2014-10-22 04:44:17 +00:00
if ( m_camera->GetBlood() && m_type == PT_SHOTH &&
2012-10-02 22:30:17 +00:00
m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
{
m_lastParticle = m_time;
for (int i = 0; i < 10; i++)
{
glm::vec3 pos = m_pos;
2012-10-02 22:30:17 +00:00
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;
glm::vec3 speed{};
2012-10-02 22:30:17 +00:00
speed.x = (Math::Rand()-0.5f)*5.0f;
speed.z = (Math::Rand()-0.5f)*5.0f;
speed.y = Math::Rand()*1.0f;
glm::vec2 dim;
2012-10-02 22:30:17 +00:00
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);
}
}
2014-10-22 04:44:17 +00:00
if ( m_camera->GetBlood() && m_type == PT_SHOTM &&
2012-10-02 22:30:17 +00:00
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++)
{
glm::vec3 pos = m_pos;
2012-10-02 22:30:17 +00:00
pos.x += (Math::Rand()-0.5f)*20.0f;
pos.z += (Math::Rand()-0.5f)*20.0f;
pos.y += 8.0f;
glm::vec3 speed{};
2012-10-02 22:30:17 +00:00
speed.x = (Math::Rand()-0.5f)*40.0f;
speed.z = (Math::Rand()-0.5f)*40.0f;
speed.y = Math::Rand()*40.0f;
glm::vec2 dim;
2012-10-02 22:30:17 +00:00
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)
2012-10-02 22:30:17 +00:00
{
int i = rand() % m_crashSpheres.size();
glm::vec3 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;
glm::vec3 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;
glm::vec2 dim;
2012-10-02 22:30:17 +00:00
dim.x = 1.0f*m_force;
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f);
}
else
{
glm::vec3 pos = m_pos;
2012-10-02 22:30:17 +00:00
pos.x += (Math::Rand()-0.5f)*m_size*0.3f;
pos.z += (Math::Rand()-0.5f)*m_size*0.3f;
glm::vec3 speed{};
2012-10-02 22:30:17 +00:00
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;
glm::vec2 dim;
2012-10-02 22:30:17 +00:00
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;
glm::vec3 pos = m_pos;
2012-10-02 22:30:17 +00:00
pos.y -= 2.0f;
pos.x += (Math::Rand()-0.5f)*4.0f;
pos.z += (Math::Rand()-0.5f)*4.0f;
glm::vec3 speed{};
2012-10-02 22:30:17 +00:00
speed.x = 0.0f;
speed.z = 0.0f;
speed.y = 10.0f+Math::Rand()*10.0f;
glm::vec2 dim;
2012-10-02 22:30:17 +00:00
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;
glm::vec3 pos = m_pos;
glm::vec3 speed{};
2012-10-02 22:30:17 +00:00
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;
glm::vec2 dim;
2012-10-02 22:30:17 +00:00
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;
glm::vec2 dim;
2012-10-02 22:30:17 +00:00
dim.x = Math::Rand()*m_size/3.0f+m_size/3.0f;
dim.y = dim.x;
glm::vec3 pos = m_pos;
2012-10-02 22:30:17 +00:00
pos.x += (Math::Rand()-0.5f)*m_size*0.5f;
pos.z += (Math::Rand()-0.5f)*m_size*0.5f;
m_terrain->AdjustToFloor(pos);
glm::vec3 speed{};
2012-10-02 22:30:17 +00:00
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;
2023-04-15 00:45:33 +00:00
else type = PARTISMOKE2;
2012-10-02 22:30:17 +00:00
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;
glm::vec3 pos = m_pos;
glm::vec3 speed{};
2012-10-02 22:30:17 +00:00
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;
glm::vec2 dim;
2012-10-02 22:30:17 +00:00
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;
glm::vec3 pos = m_pos;
glm::vec3 speed{};
2012-10-02 22:30:17 +00:00
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;
glm::vec2 dim;
2012-10-02 22:30:17 +00:00
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;
glm::vec3 pos = m_pos;
2012-10-02 22:30:17 +00:00
pos.y -= 2.0f;
pos.x += (Math::Rand()-0.5f)*4.0f;
pos.z += (Math::Rand()-0.5f)*4.0f;
glm::vec3 speed{};
2012-10-02 22:30:17 +00:00
speed.x = 0.0f;
speed.z = 0.0f;
speed.y = 4.0f+Math::Rand()*4.0f;
glm::vec2 dim;
2012-10-02 22:30:17 +00:00
dim.x = Math::Rand()*2.5f+2.0f;
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, PARTICRASH, 4.0f);
}
if ( m_type == PT_WPCHECK )
{
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;
glm::vec3 pos = m_pos;
2012-10-02 22:30:17 +00:00
pos.y += factor;
pos.x += (Math::Rand()-0.5f)*3.0f;
pos.z += (Math::Rand()-0.5f)*3.0f;
glm::vec3 speed;
2012-10-02 22:30:17 +00:00
speed.x = 0.0f;
speed.z = 0.0f;
speed.y = 5.0f+Math::Rand()*5.0f;
glm::vec2 dim;
2012-10-02 22:30:17 +00:00
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)
{
glm::vec3 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);
2012-10-02 22:30:17 +00:00
glm::vec3 pos = m_pos;
pos.y += factor;
m_object->SetPosition(pos);
2012-10-02 22:30:17 +00:00
if ( m_progress > 0.85f )
{
m_object->SetScale(1.0f-(m_progress-0.85f)/0.15f);
}
2012-10-02 22:30:17 +00:00
}
}
if ( m_type == PT_FLCREATE )
{
if ( m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
{
m_lastParticle = m_time;
glm::vec3 pos = m_pos;
2012-10-02 22:30:17 +00:00
m_terrain->AdjustToFloor(pos);
pos.x += (Math::Rand()-0.5f)*1.0f;
pos.z += (Math::Rand()-0.5f)*1.0f;
glm::vec3 speed;
2012-10-02 22:30:17 +00:00
speed.x = (Math::Rand()-0.5f)*2.0f;
speed.z = (Math::Rand()-0.5f)*2.0f;
speed.y = 2.0f+Math::Rand()*2.0f;
glm::vec2 dim;
2012-10-02 22:30:17 +00:00
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)
{
glm::vec3 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);
2012-10-02 22:30:17 +00:00
m_object->SetScale(m_progress);
}
2012-10-02 22:30:17 +00:00
}
if ( m_type == PT_FLDELETE )
{
if ( m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
{
m_lastParticle = m_time;
glm::vec3 pos = m_pos;
2012-10-02 22:30:17 +00:00
m_terrain->AdjustToFloor(pos);
pos.x += (Math::Rand()-0.5f)*1.0f;
pos.z += (Math::Rand()-0.5f)*1.0f;
glm::vec3 speed;
2012-10-02 22:30:17 +00:00
speed.x = (Math::Rand()-0.5f)*2.0f;
speed.z = (Math::Rand()-0.5f)*2.0f;
speed.y = 2.0f+Math::Rand()*2.0f;
glm::vec2 dim;
2012-10-02 22:30:17 +00:00
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)
{
glm::vec3 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);
2012-10-02 22:30:17 +00:00
m_object->SetScale(1.0f-m_progress);
}
2012-10-02 22:30:17 +00:00
}
if ( m_type == PT_RESET )
{
if ( m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
{
m_lastParticle = m_time;
glm::vec3 pos = m_pos;
2012-10-02 22:30:17 +00:00
pos.x += (Math::Rand()-0.5f)*5.0f;
pos.z += (Math::Rand()-0.5f)*5.0f;
glm::vec3 speed;
2012-10-02 22:30:17 +00:00
speed.x = 0.0f;
speed.z = 0.0f;
speed.y = 5.0f+Math::Rand()*5.0f;
glm::vec2 dim;
2012-10-02 22:30:17 +00:00
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)
{
2015-07-13 19:51:18 +00:00
float angle = m_resetAngle;
m_object->SetRotationY(angle-powf((1.0f-m_progress)*5.0f, 2.0f));
m_object->SetScale(m_progress);
}
2012-10-02 22:30:17 +00:00
}
if ( m_type == PT_FINDING )
{
if ( m_object != nullptr &&
2012-10-02 22:30:17 +00:00
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;
glm::vec3 pos = m_pos;
2012-10-02 22:30:17 +00:00
m_terrain->AdjustToFloor(pos);
pos.x += (Math::Rand()-0.5f)*factor;
pos.z += (Math::Rand()-0.5f)*factor;
glm::vec3 speed;
2012-10-02 22:30:17 +00:00
speed.x = (Math::Rand()-0.5f)*2.0f;
speed.z = (Math::Rand()-0.5f)*2.0f;
speed.y = 4.0f+Math::Rand()*4.0f;
glm::vec2 dim;
2012-10-02 22:30:17 +00:00
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);
}
}
if ( m_type == PT_SQUASH && m_object != nullptr )
{
m_object->SetScaleY(1.0f-sinf(m_progress)*0.5f);
}
2012-10-02 22:30:17 +00:00
if ( (m_type == PT_BURNT || m_type == PT_BURNO) &&
m_object != nullptr )
2012-10-02 22:30:17 +00:00
{
if ( m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
{
m_lastParticle = m_time;
float factor = m_size/25.0f; // 1 = standard size
glm::vec3 pos = m_object->GetPosition();
2012-10-02 22:30:17 +00:00
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;
glm::vec3 speed;
2012-10-02 22:30:17 +00:00
speed.x = 0.0f;
speed.z = 0.0f;
speed.y = 0.0f;
glm::vec2 dim;
2012-10-02 22:30:17 +00:00
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();
2012-10-02 22:30:17 +00:00
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();
2012-10-02 22:30:17 +00:00
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_type == PT_BURNT )
{
BurnProgress();
}
else
{
glm::vec3 speed;
2012-10-02 22:30:17 +00:00
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);
2012-10-02 22:30:17 +00:00
}
m_object->SetLinVibration(speed);
}
}
if ( m_type == PT_WIN &&
m_object != nullptr )
2012-10-02 22:30:17 +00:00
{
if ( m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
{
m_lastParticle = m_time;
glm::vec3 pos = m_object->GetPosition();
2012-10-02 22:30:17 +00:00
pos.y += 1.5f;
glm::vec3 speed;
2012-10-02 22:30:17 +00:00
speed.x = (Math::Rand()-0.5f)*10.0f;
speed.z = (Math::Rand()-0.5f)*10.0f;
speed.y = 8.0f+Math::Rand()*8.0f;
glm::vec2 dim;
2012-10-02 22:30:17 +00:00
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);
}
}
if ( m_type == PT_LOST &&
m_object != nullptr )
2012-10-02 22:30:17 +00:00
{
if ( m_lastParticle+m_engine->ParticleAdapt(0.10f) <= m_time )
{
m_lastParticle = m_time;
glm::vec3 pos = m_object->GetPosition();
2012-10-02 22:30:17 +00:00
pos.y -= 2.0f;
pos.x += (Math::Rand()-0.5f)*10.0f;
pos.z += (Math::Rand()-0.5f)*10.0f;
glm::vec3 speed;
2012-10-02 22:30:17 +00:00
speed.x = 0.0f;
speed.z = 0.0f;
speed.y = 1.0f+Math::Rand()*1.0f;
glm::vec2 dim;
2012-10-02 22:30:17 +00:00
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);
}
}
if (m_type == PT_FALL)
FallProgress(event.rTime);
if (m_lightRank != -1)
LightOperFrame(event.rTime);
return true;
}
2012-09-19 21:50:28 +00:00
Error CPyro::IsEnded()
{
2012-10-02 22:30:17 +00:00
// 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 ||
2019-07-21 23:15:11 +00:00
m_type == PT_FRAGV ||
2012-10-02 22:30:17 +00:00
m_type == PT_SPIDER ||
m_type == PT_EGG )
{
DeleteObject(true, true);
}
if ( m_type == PT_FALL ) // freight which grave?
{
return FallIsEnded();
}
if ( m_type == PT_WIN ||
m_type == PT_LOST )
{
return ERR_CONTINUE;
}
// End of the pyrotechnic effect?
if ( m_progress < 1.0f ) return ERR_CONTINUE;
if ( m_type == PT_EXPLOT ||
m_type == PT_EXPLOO ||
m_type == PT_EXPLOW ) // explosion?
{
ExploTerminate();
}
if ( m_type == PT_BURNT ||
m_type == PT_BURNO ) // burning?
{
BurnTerminate();
}
if ( m_type == PT_WPCHECK ||
m_type == PT_FLDELETE )
{
DeleteObject(true, true);
}
if ( m_type == PT_FLCREATE )
{
m_object->SetRotationX(0.0f);
m_object->SetRotationZ(0.0f);
m_object->SetScale(1.0f);
2012-10-02 22:30:17 +00:00
}
if ( m_type == PT_RESET )
{
m_object->SetRotationY(m_resetAngle);
m_object->SetScale(1.0f);
2012-10-02 22:30:17 +00:00
}
if ( m_type == PT_SQUASH )
{
m_object->SetType(OBJECT_PLANT19);
}
2012-10-02 22:30:17 +00:00
if ( m_lightRank != -1 )
{
m_lightMan->DeleteLight(m_lightRank);
m_lightRank = -1;
}
return ERR_STOP;
}
2012-10-02 22:30:17 +00:00
void CPyro::CutObjectLink(CObject* obj)
{
2012-10-02 22:30:17 +00:00
if (m_object == obj)
m_object = nullptr;
}
2012-10-02 22:30:17 +00:00
void CPyro::DisplayError(PyroType type, CObject* obj)
{
2012-10-02 22:30:17 +00:00
ObjectType oType = obj->GetType();
if ( type == PT_FRAGT ||
type == PT_FRAGO ||
type == PT_FRAGW ||
type == PT_EXPLOT ||
type == PT_EXPLOO ||
type == PT_EXPLOW ||
type == PT_BURNT ||
type == PT_BURNO )
{
Error err = ERR_OK;
if ( oType == OBJECT_MOTHER ) err = INFO_DELETEMOTHER;
if ( oType == OBJECT_ANT ) err = INFO_DELETEANT;
if ( oType == OBJECT_BEE ) err = INFO_DELETEBEE;
if ( oType == OBJECT_WORM ) err = INFO_DELETEWORM;
if ( oType == OBJECT_SPIDER ) err = INFO_DELETESPIDER;
if ( oType == OBJECT_MOBILEwa ||
oType == OBJECT_MOBILEta ||
oType == OBJECT_MOBILEfa ||
oType == OBJECT_MOBILEia ||
2017-11-16 17:43:45 +00:00
oType == OBJECT_MOBILEwb ||
oType == OBJECT_MOBILEtb ||
oType == OBJECT_MOBILEfb ||
oType == OBJECT_MOBILEib ||
2012-10-02 22:30:17 +00:00
oType == OBJECT_MOBILEwc ||
oType == OBJECT_MOBILEtc ||
oType == OBJECT_MOBILEfc ||
oType == OBJECT_MOBILEic ||
oType == OBJECT_MOBILEwi ||
oType == OBJECT_MOBILEti ||
oType == OBJECT_MOBILEfi ||
oType == OBJECT_MOBILEii ||
oType == OBJECT_MOBILEws ||
oType == OBJECT_MOBILEts ||
oType == OBJECT_MOBILEfs ||
oType == OBJECT_MOBILEis ||
oType == OBJECT_MOBILErt ||
oType == OBJECT_MOBILErc ||
oType == OBJECT_MOBILErr ||
oType == OBJECT_MOBILErs ||
oType == OBJECT_MOBILEsa ||
oType == OBJECT_MOBILEwt ||
oType == OBJECT_MOBILEtt ||
oType == OBJECT_MOBILEft ||
oType == OBJECT_MOBILEit ||
2018-12-23 06:04:06 +00:00
oType == OBJECT_MOBILErp ||
oType == OBJECT_MOBILEst ||
2012-10-02 22:30:17 +00:00
oType == OBJECT_MOBILEdr )
{
err = ERR_DELETEMOBILE;
}
if ( oType == OBJECT_DERRICK ||
oType == OBJECT_FACTORY ||
oType == OBJECT_STATION ||
oType == OBJECT_CONVERT ||
oType == OBJECT_REPAIR ||
oType == OBJECT_DESTROYER||
oType == OBJECT_TOWER ||
oType == OBJECT_RESEARCH ||
oType == OBJECT_RADAR ||
oType == OBJECT_INFO ||
oType == OBJECT_ENERGY ||
oType == OBJECT_LABO ||
oType == OBJECT_NUCLEAR ||
oType == OBJECT_PARA ||
oType == OBJECT_SAFE ||
oType == OBJECT_HUSTON ||
oType == OBJECT_START ||
oType == OBJECT_END )
{
err = ERR_DELETEBUILDING;
m_main->DisplayError(err, obj->GetPosition(), 5.0f);
2012-10-02 22:30:17 +00:00
return;
}
if ( err != ERR_OK )
{
2013-06-24 20:09:39 +00:00
m_main->DisplayError(err, obj);
2012-10-02 22:30:17 +00:00
}
}
}
void CPyro::CreateLight(glm::vec3 pos, float height)
{
2012-10-02 22:30:17 +00:00
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 = glm::vec3(pos.x, pos.y+height, pos.z);
light.direction = glm::vec3(0.0f, -1.0f, 0.0f); // against the bottom
2012-10-02 22:30:17 +00:00
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);
}
2012-09-19 21:50:28 +00:00
void CPyro::DeleteObject(bool primary, bool secondary)
{
2012-10-02 22:30:17 +00:00
if (m_object == nullptr) return;
ObjectType type = m_object->GetType();
if ( secondary &&
type != OBJECT_FACTORY &&
type != OBJECT_NUCLEAR &&
type != OBJECT_ENERGY )
{
2022-01-29 16:16:57 +00:00
if (m_object->Implements(ObjectInterfaceType::Slotted))
2012-10-02 22:30:17 +00:00
{
2022-01-29 16:16:57 +00:00
CSlottedObject* asSlotted = dynamic_cast<CSlottedObject*>(m_object);
for (int slot = asSlotted->GetNumSlots() - 1; slot >= 0; slot--)
2015-07-10 20:13:39 +00:00
{
2022-01-29 16:16:57 +00:00
if (CObject* sub = asSlotted->GetSlotContainedObject(slot))
{
CObjectManager::GetInstancePointer()->DeleteObject(sub);
asSlotted->SetSlotContainedObject(slot, nullptr);
}
2015-07-10 20:13:39 +00:00
}
2012-10-02 22:30:17 +00:00
}
}
if (primary)
{
2015-07-10 17:03:27 +00:00
if (m_object->Implements(ObjectInterfaceType::Transportable))
2012-10-02 22:30:17 +00:00
{
2015-07-10 17:03:27 +00:00
// TODO: this should be handled in the object's destructor
CObject* transporter = dynamic_cast<CTransportableObject&>(*m_object).GetTransporter();
2015-07-10 17:03:27 +00:00
if (transporter != nullptr)
{
2022-01-29 16:16:57 +00:00
assert(transporter->Implements(ObjectInterfaceType::Slotted));
CSlottedObject* asSlotted = dynamic_cast<CSlottedObject*>(transporter);
for (int slotNum = asSlotted->GetNumSlots() - 1; slotNum >= 0; slotNum--)
2015-07-10 20:13:39 +00:00
{
2022-01-29 16:16:57 +00:00
if (asSlotted->GetSlotContainedObject(slotNum) == m_object)
{
asSlotted->SetSlotContainedObject(slotNum, nullptr);
break;
}
2015-07-10 20:13:39 +00:00
}
2015-07-10 17:03:27 +00:00
}
2012-10-02 22:30:17 +00:00
}
CObjectManager::GetInstancePointer()->DeleteObject(m_object);
2012-10-02 22:30:17 +00:00
m_object = nullptr;
}
}
2012-10-02 22:30:17 +00:00
void CPyro::CreateTriangle(CObject* obj, ObjectType oType, int part)
{
2012-10-02 22:30:17 +00:00
int objRank = obj->GetObjectRank(part);
if (objRank == -1) return;
2013-01-27 10:43:53 +00:00
2012-10-02 22:30:17 +00:00
int total = m_engine->GetObjectTotalTriangles(objRank);
2013-01-27 10:43:53 +00:00
2012-10-02 22:30:17 +00:00
float percent = 0.10f;
if (total < 50) percent = 0.25f;
if (total < 20) percent = 0.50f;
2019-07-21 23:15:11 +00:00
2019-07-22 15:04:15 +00:00
if ( m_type == PT_FRAGV || m_type == PT_EGG )
2019-07-21 23:15:11 +00:00
{
percent = 0.30f;
}
2012-10-02 22:30:17 +00:00
2013-01-27 10:43:53 +00:00
if (oType == OBJECT_POWER ||
oType == OBJECT_ATOMIC ||
oType == OBJECT_URANIUM ||
oType == OBJECT_TNT ||
oType == OBJECT_BOMB ||
oType == OBJECT_TEEN28)
2013-01-27 10:43:53 +00:00
{
percent = 0.75f;
}
else if (oType == OBJECT_MOBILEtg)
{
percent = 0.50f;
}
2012-10-02 22:30:17 +00:00
std::vector<EngineTriangle> buffer;
total = m_engine->GetPartialTriangles(objRank, percent, 100, buffer);
2012-10-02 22:30:17 +00:00
for (int i = 0; i < total; i++)
{
glm::vec3 p1, p2, p3;
2012-10-02 22:30:17 +00:00
p1.x = buffer[i].triangle[0].position.x;
p1.y = buffer[i].triangle[0].position.y;
p1.z = buffer[i].triangle[0].position.z;
p2.x = buffer[i].triangle[1].position.x;
p2.y = buffer[i].triangle[1].position.y;
p2.z = buffer[i].triangle[1].position.z;
p3.x = buffer[i].triangle[2].position.x;
p3.y = buffer[i].triangle[2].position.y;
p3.z = buffer[i].triangle[2].position.z;
2012-10-02 22:30:17 +00:00
float h;
h = glm::distance(p1, p2);
2012-10-02 22:30:17 +00:00
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 = glm::distance(p2, p3);
2012-10-02 22:30:17 +00:00
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 = glm::distance(p3, p1);
2012-10-02 22:30:17 +00:00
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].position.x = p1.x;
buffer[i].triangle[0].position.y = p1.y;
buffer[i].triangle[0].position.z = p1.z;
buffer[i].triangle[1].position.x = p2.x;
buffer[i].triangle[1].position.y = p2.y;
buffer[i].triangle[1].position.z = p2.z;
buffer[i].triangle[2].position.x = p3.x;
buffer[i].triangle[2].position.y = p3.y;
buffer[i].triangle[2].position.z = p3.z;
2012-10-02 22:30:17 +00:00
glm::vec3 offset;
offset.x = (buffer[i].triangle[0].position.x+buffer[i].triangle[1].position.x+buffer[i].triangle[2].position.x)/3.0f;
offset.y = (buffer[i].triangle[0].position.y+buffer[i].triangle[1].position.y+buffer[i].triangle[2].position.y)/3.0f;
offset.z = (buffer[i].triangle[0].position.z+buffer[i].triangle[1].position.z+buffer[i].triangle[2].position.z)/3.0f;
2012-10-02 22:30:17 +00:00
buffer[i].triangle[0].position.x -= offset.x;
buffer[i].triangle[1].position.x -= offset.x;
buffer[i].triangle[2].position.x -= offset.x;
2012-10-02 22:30:17 +00:00
buffer[i].triangle[0].position.y -= offset.y;
buffer[i].triangle[1].position.y -= offset.y;
buffer[i].triangle[2].position.y -= offset.y;
2012-10-02 22:30:17 +00:00
buffer[i].triangle[0].position.z -= offset.z;
buffer[i].triangle[1].position.z -= offset.z;
buffer[i].triangle[2].position.z -= offset.z;
2012-10-02 22:30:17 +00:00
glm::vec3 speed;
2012-10-02 22:30:17 +00:00
float mass;
glm::mat4 mat = obj->GetWorldMatrix(part);
glm::vec3 pos = Math::Transform(mat, offset);
2019-07-22 15:04:15 +00:00
if ( m_type == PT_FRAGV || m_type == PT_EGG )
2012-10-02 22:30:17 +00:00
{
speed.x = (Math::Rand()-0.5f)*10.0f;
speed.z = (Math::Rand()-0.5f)*10.0f;
speed.y = Math::Rand()*15.0f;
mass = Math::Rand()*20.0f+20.0f;
}
else if ( m_type == PT_SPIDER )
{
speed.x = (Math::Rand()-0.5f)*10.0f;
speed.z = (Math::Rand()-0.5f)*10.0f;
speed.y = Math::Rand()*20.0f;
mass = Math::Rand()*10.0f+15.0f;
}
else
{
speed.x = (Math::Rand()-0.5f)*30.0f;
speed.z = (Math::Rand()-0.5f)*30.0f;
speed.y = Math::Rand()*30.0f;
mass = Math::Rand()*10.0f+15.0f;
}
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);
}
}
2012-09-19 21:50:28 +00:00
void CPyro::ExploStart()
{
2012-10-02 22:30:17 +00:00
m_burnType = m_object->GetType();
glm::vec3 oPos = m_object->GetPosition();
2012-10-02 22:30:17 +00:00
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
2012-10-02 22:30:17 +00:00
m_object->FlatParent();
if ( m_object->Implements(ObjectInterfaceType::Controllable) && dynamic_cast<CControllableObject&>(*m_object).GetSelect() )
2012-10-02 22:30:17 +00:00
{
dynamic_cast<CControllableObject&>(*m_object).SetSelect(false); // deselects the object
2012-10-02 22:30:17 +00:00
m_camera->SetType(CAM_TYPE_EXPLO);
m_main->DeselectAll();
}
m_main->RemoveFromSelectionHistory(m_object);
2012-10-02 22:30:17 +00:00
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");
}
2012-10-02 22:30:17 +00:00
// TODO: temporary hack (hopefully)
assert(m_object->Implements(ObjectInterfaceType::Old));
glm::vec3 pos = dynamic_cast<COldObject&>(*m_object).GetPartPosition(i);
2012-10-02 22:30:17 +00:00
glm::vec3 speed;
2012-10-02 22:30:17 +00:00
float weight;
if (i == 0) // main part?
{
weight = 0.0f;
speed.y = -1.0f;
speed.x = 0.0f;
speed.z = 0.0f;
}
else
{
glm::vec3 min, max;
2012-10-02 22:30:17 +00:00
m_engine->GetObjectBBox(objRank, min, max);
weight = glm::distance(min, max); // weight according to size!
2012-10-02 22:30:17 +00:00
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");
2012-10-02 22:30:17 +00:00
DeleteObject(false, true); // destroys the object transported + the battery
}
2012-09-19 21:50:28 +00:00
void CPyro::ExploTerminate()
{
2012-10-02 22:30:17 +00:00
DeleteObject(true, false); // removes the main object
}
2012-09-19 21:50:28 +00:00
void CPyro::BurnStart()
{
2012-10-02 22:30:17 +00:00
m_burnType = m_object->GetType();
glm::vec3 oPos = m_object->GetPosition();
2012-10-02 22:30:17 +00:00
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() )
2012-10-02 22:30:17 +00:00
{
dynamic_cast<CControllableObject&>(*m_object).SetSelect(false); // deselects the object
2012-10-02 22:30:17 +00:00
m_camera->SetType(CAM_TYPE_EXPLO);
m_main->DeselectAll();
}
m_main->RemoveFromSelectionHistory(m_object);
2012-10-02 22:30:17 +00:00
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");
}
2012-10-02 22:30:17 +00:00
}
m_engine->LoadTexture("textures/dirty04.png");
2012-10-02 22:30:17 +00:00
m_burnPartTotal = 0;
glm::vec3 pos, angle;
2012-10-02 22:30:17 +00:00
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 ||
2017-11-16 17:43:45 +00:00
m_burnType == OBJECT_MOBILEwb ||
2012-10-02 22:30:17 +00:00
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;
}
2012-10-02 22:30:17 +00:00
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
}
2020-05-15 18:29:48 +00:00
2017-11-16 17:43:45 +00:00
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
}
2012-10-02 22:30:17 +00:00
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 ||
2017-11-16 17:43:45 +00:00
m_burnType == OBJECT_MOBILEwb ||
2012-10-02 22:30:17 +00:00
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 ||
2017-11-16 17:43:45 +00:00
m_burnType == OBJECT_MOBILEtb ||
2012-10-02 22:30:17 +00:00
m_burnType == OBJECT_MOBILEtc ||
m_burnType == OBJECT_MOBILEti ||
m_burnType == OBJECT_MOBILEts ||
2018-12-23 06:04:06 +00:00
m_burnType == OBJECT_MOBILEtt ||
2012-10-02 22:30:17 +00:00
m_burnType == OBJECT_MOBILErt ||
m_burnType == OBJECT_MOBILErc ||
m_burnType == OBJECT_MOBILErr ||
m_burnType == OBJECT_MOBILErs ||
2018-12-23 06:04:06 +00:00
m_burnType == OBJECT_MOBILErp ||
2012-10-02 22:30:17 +00:00
m_burnType == OBJECT_MOBILEsa ||
2018-12-23 06:04:06 +00:00
m_burnType == OBJECT_MOBILEst ||
2012-10-02 22:30:17 +00:00
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 ||
2017-11-16 17:43:45 +00:00
m_burnType == OBJECT_MOBILEfb ||
2012-10-02 22:30:17 +00:00
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 ||
2017-11-16 17:43:45 +00:00
m_burnType == OBJECT_MOBILEib ||
2012-10-02 22:30:17 +00:00
m_burnType == OBJECT_MOBILEic ||
m_burnType == OBJECT_MOBILEii ||
2018-12-23 06:04:06 +00:00
m_burnType == OBJECT_MOBILEis ||
m_burnType == OBJECT_MOBILEit ) // legs?
2012-10-02 22:30:17 +00:00
{
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 CPyro::BurnAddPart(int part, glm::vec3 pos, glm::vec3 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);
2012-10-02 22:30:17 +00:00
m_burnPart[i].finalPos = m_burnPart[i].initialPos+pos;
m_burnPart[i].initialAngle = oldObj->GetPartRotation(part);
2012-10-02 22:30:17 +00:00
m_burnPart[i].finalAngle = m_burnPart[i].initialAngle+angle;
m_burnPartTotal++;
}
2012-09-19 21:50:28 +00:00
void CPyro::BurnProgress()
{
if ( m_burnType == OBJECT_TEEN31 ) // basket?
{
m_object->SetScaleY(1.0f-m_progress*0.5f); // slight flattening
}
2012-10-02 22:30:17 +00:00
for (int i = 0; i < m_burnPartTotal; i++)
{
glm::vec3 pos = m_burnPart[i].initialPos + m_progress*(m_burnPart[i].finalPos-m_burnPart[i].initialPos);
2012-10-02 22:30:17 +00:00
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);
2012-10-02 22:30:17 +00:00
pos = m_burnPart[i].initialAngle + m_progress*(m_burnPart[i].finalAngle-m_burnPart[i].initialAngle);
oldObj->SetPartRotation(m_burnPart[i].part, pos);
2012-10-02 22:30:17 +00:00
}
2022-01-29 16:16:57 +00:00
// TODO: should this apply to every slot?
if (CObject* sub = GetObjectInPowerCellSlot(m_object)) // is there a battery?
2015-07-10 21:47:59 +00:00
{
2022-01-29 16:16:57 +00:00
sub->SetScaleY(1.0f - m_progress); // complete flattening
2015-07-10 21:47:59 +00:00
}
}
2012-09-19 21:50:28 +00:00
bool CPyro::BurnIsKeepPart(int part)
{
2012-10-02 22:30:17 +00:00
int i = 0;
while (m_burnKeepPart[i] != -1)
{
if (part == m_burnKeepPart[i++]) return true; // must keep
}
return false; // must destroy
}
2012-09-19 21:50:28 +00:00
void CPyro::BurnTerminate()
{
if (m_object == nullptr)
return;
2012-10-02 22:30:17 +00:00
if (m_type == PT_BURNO) // 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
2012-10-02 22:30:17 +00:00
}
else
{
m_object->SetType(OBJECT_RUINmobilew1); // Wreck (recoverable by Recycler)
2012-10-02 22:30:17 +00:00
}
dynamic_cast<CDestroyableObject*>(m_object)->SetDying(DeathType::Alive);
m_object->SetLock(false);
}
2012-09-19 21:50:28 +00:00
void CPyro::FallStart()
{
m_object->SetLock(true); // usable
2012-10-02 22:30:17 +00:00
glm::vec3 pos = m_object->GetPosition();
2012-10-02 22:30:17 +00:00
m_fallFloor = m_terrain->GetFloorLevel(pos);
m_fallSpeed = 0.0f;
m_fallBulletTime = 0.0f;
m_fallEnding = false;
}
2012-09-19 21:50:28 +00:00
CObject* CPyro::FallSearchBeeExplo()
{
auto bulletCrashSphere = m_object->GetFirstCrashSphere();
2012-10-02 22:30:17 +00:00
for (CObject* obj : CObjectManager::GetInstancePointer()->GetAllObjects())
{
if (obj == m_object) continue;
if (obj->GetType() == OBJECT_BEE) continue;
if ( !obj->Implements(ObjectInterfaceType::Destroyable) ) continue;
2012-10-02 22:30:17 +00:00
2015-07-10 17:03:27 +00:00
if (IsObjectBeingTransported(obj)) continue;
2012-10-02 22:30:17 +00:00
glm::vec3 oPos = obj->GetPosition();
2012-10-02 22:30:17 +00:00
2015-08-17 12:06:31 +00:00
if (obj->GetType() == OBJECT_MOBILErs)
2012-10-02 22:30:17 +00:00
{
float shieldRadius = dynamic_cast<CShielder&>(*obj).GetActiveShieldRadius();
2015-08-17 12:06:31 +00:00
if ( shieldRadius > 0.0f )
{
float distance = glm::distance(oPos, bulletCrashSphere.sphere.pos);
2015-08-17 12:06:31 +00:00
if (distance <= shieldRadius)
return obj;
}
2012-10-02 22:30:17 +00:00
}
2015-08-13 16:54:44 +00:00
if ( obj->GetType() == OBJECT_BASE )
2012-10-02 22:30:17 +00:00
{
float distance = glm::distance(oPos, bulletCrashSphere.sphere.pos);
if (distance < 25.0f)
return obj;
2012-10-02 22:30:17 +00:00
}
// Test the center of the object, which is necessary for objects
// that have no sphere in the center (station).
float distance = glm::distance(oPos, bulletCrashSphere.sphere.pos)-4.0f;
if (distance < 5.0f)
return obj;
2012-10-02 22:30:17 +00:00
// Test with all spheres of the object.
for (const auto& objCrashSphere : obj->GetAllCrashSpheres())
2012-10-02 22:30:17 +00:00
{
if (Math::DistanceBetweenSpheres(objCrashSphere.sphere, bulletCrashSphere.sphere) <= 0.0f)
2012-10-02 22:30:17 +00:00
{
return obj;
2012-10-02 22:30:17 +00:00
}
}
}
return nullptr;
}
2012-09-19 21:50:28 +00:00
void CPyro::FallProgress(float rTime)
{
2012-10-02 22:30:17 +00:00
if (m_object == nullptr) return;
m_fallSpeed += rTime*50.0f; // v2 = v1 + a*dt
glm::vec3 pos;
pos = m_object->GetPosition();
2012-10-02 22:30:17 +00:00
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);
2012-10-02 22:30:17 +00:00
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?
{
2015-08-13 16:54:44 +00:00
assert(m_object->Implements(ObjectInterfaceType::Destroyable));
// TODO: implement "killer"?
dynamic_cast<CDestroyableObject&>(*m_object).DestroyObject(DestructionType::Explosion);
2012-10-02 22:30:17 +00:00
}
}
else
{
if (obj->GetType() == OBJECT_MOBILErs && dynamic_cast<CShielder&>(*obj).GetActiveShieldRadius() > 0.0f) // protected by shield?
2012-10-02 22:30:17 +00:00
{
m_particle->CreateParticle(pos, glm::vec3(0.0f, 0.0f, 0.0f),
{ 6.0f, 6.0f }, PARTIGUNDEL, 2.0f, 0.0f, 0.0f);
2012-10-02 22:30:17 +00:00
m_sound->Play(SOUND_GUNDEL);
DeleteObject(true, true); // removes the ball
}
else
{
2015-08-13 16:54:44 +00:00
assert(obj->Implements(ObjectInterfaceType::Damageable));
if (dynamic_cast<CDamageableObject&>(*obj).DamageObject(DamageType::FallingObject))
2012-10-02 22:30:17 +00:00
{
DeleteObject(true, true); // removes the ball
}
else
{
2015-08-13 16:54:44 +00:00
assert(m_object->Implements(ObjectInterfaceType::Destroyable));
// TODO: implement "killer"?
dynamic_cast<CDestroyableObject&>(*m_object).DestroyObject(DestructionType::Explosion);
2012-10-02 22:30:17 +00:00
}
}
}
if (floor || obj != nullptr)
{
m_fallEnding = true;
}
}
}
}
2012-09-19 21:50:28 +00:00
Error CPyro::FallIsEnded()
{
2015-08-17 20:40:52 +00:00
if (m_fallEnding || m_object == nullptr) return ERR_STOP;
2012-10-02 22:30:17 +00:00
glm::vec3 pos = m_object->GetPosition();
2012-10-02 22:30:17 +00:00
if (pos.y > m_fallFloor) return ERR_CONTINUE;
m_sound->Play(SOUND_BOUM, pos);
m_object->SetLock(false); // usable again
2012-10-02 22:30:17 +00:00
return ERR_STOP;
}
2012-09-19 21:50:28 +00:00
void CPyro::LightOperFlush()
{
m_lightOper.clear();
}
2012-09-19 21:50:28 +00:00
void CPyro::LightOperAdd(float progress, float intensity, float r, float g, float b)
{
PyroLightOper lightOper;
2012-10-02 22:30:17 +00:00
lightOper.progress = progress;
lightOper.intensity = intensity;
lightOper.color.r = r;
lightOper.color.g = g;
lightOper.color.b = b;
2012-10-02 22:30:17 +00:00
m_lightOper.push_back(lightOper);
}
2012-09-19 21:50:28 +00:00
void CPyro::LightOperFrame(float rTime)
{
for (std::size_t i = 1; i < m_lightOper.size(); i++)
2012-10-02 22:30:17 +00:00
{
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;
}
}
}
2012-09-19 21:50:28 +00:00
} // namespace Gfx