diff options
Diffstat (limited to 'src/old/pyro.cpp')
-rw-r--r-- | src/old/pyro.cpp | 4972 |
1 files changed, 2486 insertions, 2486 deletions
diff --git a/src/old/pyro.cpp b/src/old/pyro.cpp index fc61e62..96fc776 100644 --- a/src/old/pyro.cpp +++ b/src/old/pyro.cpp @@ -1,2486 +1,2486 @@ -// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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://www.gnu.org/licenses/.
-
-// pyro.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "math/const.h"
-#include "math/geometry.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "old/math3d.h"
-#include "object/robotmain.h"
-#include "old/terrain.h"
-#include "old/camera.h"
-#include "old/particule.h"
-#include "old/light.h"
-#include "object/object.h"
-#include "object/motion/motion.h"
-#include "object/motion/motionhuman.h"
-#include "ui/displaytext.h"
-#include "old/sound.h"
-#include "old/pyro.h"
-
-
-
-
-// Object's constructor.
-
-CPyro::CPyro(CInstanceManager* iMan)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_PYRO, this, 100);
-
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
- m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
- m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
- m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT);
- m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
- m_object = 0;
-
- m_progress = 0.0f;
- m_speed = 0.0f;
- m_lightRank = -1;
- m_soundChannel = -1;
- LightOperFlush();
-}
-
-// Object's destructor.
-
-CPyro::~CPyro()
-{
- m_iMan->DeleteInstance(CLASS_PYRO, this);
-}
-
-
-// Destroys the object.
-
-void CPyro::DeleteObject(bool bAll)
-{
- if ( m_lightRank != -1 )
- {
- m_light->DeleteLight(m_lightRank);
- m_lightRank = -1;
- }
-}
-
-
-// Creates pyrotechnic effect.
-
-bool CPyro::Create(PyroType type, CObject* pObj, float force)
-{
- Math::Matrix* mat;
- CObject* power;
- CMotion* motion;
- Math::Vector min, max, pos, speed;
- Math::Point dim;
- ObjectType oType;
- Sound sound;
- float duration, mass, h, limit;
- int part, objRank, total, i, channel;
-
- m_object = pObj;
- m_force = force;
-
- oType = pObj->RetType();
- objRank = pObj->RetObjectRank(0);
- if ( objRank == -1 ) return false;
- m_engine->GetBBox(objRank, min, max);
- pos = pObj->RetPosition(0);
-
- DisplayError(type, pObj); // displays eventual messages
-
- // Copies all spheres of the object.
- for ( i=0 ; i<50 ; i++ )
- {
- if ( !pObj->GetCrashSphere(i, m_crashSpherePos[i], m_crashSphereRadius[i]) ) break;
- }
- m_crashSphereUsed = i;
-
- // 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_type = type;
- m_progress = 0.0f;
- m_speed = 1.0f/20.0f;
- m_time = 0.0f;
- m_lastParticule = 0.0f;
- m_lastParticuleSmoke = 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.
- power = pObj->RetPower();
- if ( power == 0 )
- {
- m_bPower = false;
- }
- else
- {
- m_bPower = true;
- pos = power->RetPosition(0);
- pos.y += 1.0f;
- mat = pObj->RetWorldMatrix(0);
- m_posPower = Math::Transform(*mat, pos);
- }
- if ( oType == OBJECT_POWER ||
- oType == OBJECT_ATOMIC ||
- oType == OBJECT_URANIUM ||
- oType == OBJECT_TNT ||
- oType == OBJECT_BOMB )
- {
- m_bPower = true;
- m_posPower = m_pos;
- m_posPower.y += 1.0f;
- m_pos = m_posPower;
- }
- if ( oType == OBJECT_STATION )
- {
- m_bPower = true;
- mat = pObj->RetWorldMatrix(0);
- m_posPower = Math::Transform(*mat, Math::Vector(-15.0f, 7.0f, 0.0f));
- m_pos = m_posPower;
- }
- if ( oType == OBJECT_ENERGY )
- {
- m_bPower = true;
- mat = pObj->RetWorldMatrix(0);
- m_posPower = Math::Transform(*mat, Math::Vector(-7.0f, 6.0f, 0.0f));
- m_pos = m_posPower;
- }
- if ( oType == OBJECT_NUCLEAR )
- {
- m_bPower = true;
- m_posPower = m_pos;
- }
- if ( oType == OBJECT_PARA )
- {
- m_bPower = true;
- m_posPower = m_pos;
- }
- if ( oType == OBJECT_SCRAP4 ||
- oType == OBJECT_SCRAP5 ) // plastic material?
- {
- m_bPower = 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 )
- {
- if ( m_bPower )
- {
- 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);
- }
- 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->RetEyePt());
- }
- 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);
- }
- if ( type == PT_SHOTH && m_object->RetSelect() )
- {
- m_sound->Play(SOUND_AIE, m_pos);
- m_sound->Play(SOUND_AIE, m_engine->RetEyePt());
- }
- }
-
- if ( m_type == PT_FRAGT ||
- m_type == PT_FRAGO ||
- m_type == PT_FRAGW )
- {
- m_engine->ShadowDelete(m_object->RetObjectRank(0));
- }
-
- if ( m_type == PT_DEADG )
- {
- m_object->SetDead(true);
-
- motion = m_object->RetMotion();
- if ( motion != 0 )
- {
- motion->SetAction(MHS_DEADg, 1.0f);
- }
- m_camera->StartCentering(m_object, Math::PI*0.5f, 99.9f, 0.0f, 1.5f);
- m_camera->StartOver(OE_FADEOUTw, m_pos, 1.0f);
- m_speed = 1.0f/10.0f;
- return true;
- }
- if ( m_type == PT_DEADW )
- {
- m_object->SetDead(true);
-
- motion = m_object->RetMotion();
- if ( motion != 0 )
- {
- motion->SetAction(MHS_DEADw, 4.0f);
- }
- m_camera->StartCentering(m_object, Math::PI*0.5f, 99.9f, 0.0f, 3.0f);
- m_camera->StartOver(OE_FADEOUTb, m_pos, 1.0f);
- m_speed = 1.0f/10.0f;
- return true;
- }
-
- if ( m_type == PT_SHOTT ||
- m_type == PT_SHOTM )
- {
- m_camera->StartEffect(CE_SHOT, m_pos, force);
- m_speed = 1.0f/1.0f;
- return true;
- }
- if ( m_type == PT_SHOTH )
- {
- if ( m_object->RetSelect() )
- {
- m_camera->StartOver(OE_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->SetEnable(false); // object more functional
- }
- if ( m_type == PT_FLCREATE )
- {
- m_speed = 1.0f/2.0f;
- }
- if ( m_type == PT_FLDELETE )
- {
- m_speed = 1.0f/2.0f;
- m_object->SetEnable(false); // object more functional
- }
- if ( m_type == PT_RESET )
- {
- m_speed = 1.0f/2.0f;
- m_object->SetPosition(0, m_object->RetResetPosition());
- m_object->SetAngle(0, m_object->RetResetAngle());
- m_object->SetZoom(0, 0.0f);
- }
- if ( m_type == PT_FINDING )
- {
- 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_EXPLOT ||
- m_type == PT_EXPLOO ||
- m_type == PT_EXPLOW )
- {
- CreateTriangle(pObj, oType, 0);
- m_engine->ShadowDelete(m_object->RetObjectRank(0));
- 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 = Math::Vector(-3.0f, 2.0f, 0.0f);
- mat = pObj->RetWorldMatrix(0);
- m_pos = Math::Transform(*mat, pos);
-
- m_engine->ShadowDelete(m_object->RetObjectRank(0));
- }
-
- if ( m_type != PT_EGG &&
- m_type != PT_WIN &&
- m_type != PT_LOST )
- {
- 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_camera->StartEffect(CE_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 ||
- 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 ) )
- {
- for ( part=0 ; part<OBJECTMAXPART ; part++ )
- {
- CreateTriangle(pObj, oType, part);
- }
- }
-
- if ( m_type == PT_FRAGT ||
- m_type == PT_EXPLOT )
- {
- if ( m_bPower )
- {
- total = (int)(10.0f*m_engine->RetParticuleDensity());
- if ( oType == OBJECT_TNT ||
- oType == OBJECT_BOMB ) total *= 3;
- for ( i=0 ; i<total ; i++ )
- {
- pos = m_posPower;
- speed.x = (Math::Rand()-0.5f)*30.0f;
- speed.z = (Math::Rand()-0.5f)*30.0f;
- speed.y = Math::Rand()*30.0f;
- dim.x = 1.0f;
- dim.y = dim.x;
- duration = Math::Rand()*3.0f+2.0f;
- mass = Math::Rand()*10.0f+15.0f;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK1,
- duration, mass, Math::Rand()+0.7f, 1.0f);
- }
- }
-
- if ( m_size > 10.0f ) // large enough (freight excluded)?
- {
- if ( m_bPower )
- {
- pos = m_posPower;
- }
- else
- {
- pos = m_pos;
- m_terrain->MoveOnFloor(pos);
- pos.y += 1.0f;
- }
- dim.x = m_size*0.4f;
- dim.y = dim.x;
- m_particule->CreateParticule(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 )
- {
- total = (int)(10.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<total ; i++ )
- {
- pos = m_pos;
- speed.x = (Math::Rand()-0.5f)*30.0f;
- speed.z = (Math::Rand()-0.5f)*30.0f;
- speed.y = Math::Rand()*50.0f;
- dim.x = 1.0f;
- dim.y = dim.x;
- duration = Math::Rand()*1.0f+0.8f;
- mass = Math::Rand()*10.0f+15.0f;
- m_particule->CreateParticule(pos, speed, dim, PARTIORGANIC1,
- duration, mass);
- }
- total = (int)(5.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<total ; i++ )
- {
- pos = m_pos;
- speed.x = (Math::Rand()-0.5f)*30.0f;
- speed.z = (Math::Rand()-0.5f)*30.0f;
- speed.y = Math::Rand()*50.0f;
- dim.x = 1.0f;
- dim.y = dim.x;
- duration = Math::Rand()*2.0f+1.4f;
- mass = Math::Rand()*10.0f+15.0f;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK4,
- duration, mass, duration*0.5f, dim.x*2.0f);
- }
- }
-
- if ( m_type == PT_SPIDER )
- {
- for ( 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;
- speed.x = (Math::Rand()-0.5f)*24.0f;
- speed.z = (Math::Rand()-0.5f)*24.0f;
- speed.y = 10.0f+Math::Rand()*10.0f;
- dim.x = 1.0f;
- dim.y = dim.x;
- channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN3, 2.0f+Math::Rand()*2.0f, 10.0f);
- m_particule->SetObjectFather(channel, pObj);
- }
- total = (int)(10.0f*m_engine->RetParticuleDensity());
- for ( 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;
- speed.x = (Math::Rand()-0.5f)*24.0f;
- speed.z = (Math::Rand()-0.5f)*24.0f;
- speed.y = 7.0f+Math::Rand()*7.0f;
- dim.x = 1.0f;
- dim.y = dim.x;
- m_particule->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_bPower )
- {
- pos = m_pos;
-//? m_terrain->MoveOnFloor(pos);
-//? pos.y += 2.0f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = m_size;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICHOC, 2.0f);
- }
- }
-
- return true;
-}
-
-// Creates an explosion with triangular form of particles.
-
-void CPyro::CreateTriangle(CObject* pObj, ObjectType oType, int part)
-{
- D3DTriangle buffer[100];
- Math::Matrix* mat;
- Math::Vector offset, pos, speed;
- float percent, min, max, h, duration, mass;
- int objRank, total, i;
-
- objRank = pObj->RetObjectRank(part);
- if ( objRank == -1 ) return;
-
- min = 0.0f;
- max = m_engine->RetLimitLOD(0);
- total = m_engine->RetTotalTriangles(objRank);
- percent = 0.10f;
- if ( total < 50 ) percent = 0.25f;
- if ( total < 20 ) percent = 0.50f;
- if ( m_type == PT_EGG ) percent = 0.30f;
- if ( oType == OBJECT_POWER ||
- oType == OBJECT_ATOMIC ||
- oType == OBJECT_URANIUM ||
- oType == OBJECT_TNT ||
- oType == OBJECT_BOMB ) percent = 0.75f;
- if ( oType == OBJECT_MOBILEtg ) percent = 0.50f;
- if ( oType == OBJECT_TEEN28 ) percent = 0.75f;
- if ( oType == OBJECT_MOTHER ) max = 1000000.0f;
- if ( oType == OBJECT_TEEN28 ) max = 1000000.0f;
- if ( oType == OBJECT_TEEN31 ) max = 1000000.0f;
- total = m_engine->GetTriangles(objRank, min, max, buffer, 100, percent);
-
- for ( i=0 ; i<total ; i++ )
- {
- Math::Vector p1, p2, p3;
-
- p1.x = buffer[i].triangle[0].x;
- p1.y = buffer[i].triangle[0].y;
- p1.z = buffer[i].triangle[0].z;
- p2.x = buffer[i].triangle[1].x;
- p2.y = buffer[i].triangle[1].y;
- p2.z = buffer[i].triangle[1].z;
- p3.x = buffer[i].triangle[2].x;
- p3.y = buffer[i].triangle[2].y;
- p3.z = buffer[i].triangle[2].z;
-
- 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].x = p1.x;
- buffer[i].triangle[0].y = p1.y;
- buffer[i].triangle[0].z = p1.z;
- buffer[i].triangle[1].x = p2.x;
- buffer[i].triangle[1].y = p2.y;
- buffer[i].triangle[1].z = p2.z;
- buffer[i].triangle[2].x = p3.x;
- buffer[i].triangle[2].y = p3.y;
- buffer[i].triangle[2].z = p3.z;
-
- offset.x = (buffer[i].triangle[0].x+buffer[i].triangle[1].x+buffer[i].triangle[2].x)/3.0f;
- offset.y = (buffer[i].triangle[0].y+buffer[i].triangle[1].y+buffer[i].triangle[2].y)/3.0f;
- offset.z = (buffer[i].triangle[0].z+buffer[i].triangle[1].z+buffer[i].triangle[2].z)/3.0f;
-
- buffer[i].triangle[0].x -= offset.x;
- buffer[i].triangle[1].x -= offset.x;
- buffer[i].triangle[2].x -= offset.x;
-
- buffer[i].triangle[0].y -= offset.y;
- buffer[i].triangle[1].y -= offset.y;
- buffer[i].triangle[2].y -= offset.y;
-
- buffer[i].triangle[0].z -= offset.z;
- buffer[i].triangle[1].z -= offset.z;
- buffer[i].triangle[2].z -= offset.z;
-
- mat = pObj->RetWorldMatrix(part);
- pos = Math::Transform(*mat, offset);
- if ( m_type == PT_EGG )
- {
- 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;
- duration = Math::Rand()*3.0f+3.0f;
- m_particule->CreateFrag(pos, speed, &buffer[i], PARTIFRAG,
- duration, mass, 0.5f);
- }
-}
-
-// Displays the error or eventual information,
-// linked to the destruction of an insect, a vehicle or building.
-
-void CPyro::DisplayError(PyroType type, CObject* pObj)
-{
- ObjectType oType;
- Error err;
-
- oType = pObj->RetType();
-
- 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 )
- {
- 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 ||
- oType == OBJECT_MOBILEwc ||
- oType == OBJECT_MOBILEtc ||
- oType == OBJECT_MOBILEfc ||
- oType == OBJECT_MOBILEic ||
- oType == OBJECT_MOBILEwi ||
- oType == OBJECT_MOBILEti ||
- oType == OBJECT_MOBILEfi ||
- oType == OBJECT_MOBILEii ||
- oType == OBJECT_MOBILEws ||
- oType == OBJECT_MOBILEts ||
- oType == OBJECT_MOBILEfs ||
- oType == OBJECT_MOBILEis ||
- oType == OBJECT_MOBILErt ||
- oType == OBJECT_MOBILErc ||
- oType == OBJECT_MOBILErr ||
- oType == OBJECT_MOBILErs ||
- oType == OBJECT_MOBILEsa ||
- oType == OBJECT_MOBILEwt ||
- oType == OBJECT_MOBILEtt ||
- oType == OBJECT_MOBILEft ||
- oType == OBJECT_MOBILEit ||
- oType == OBJECT_MOBILEdr )
- {
- 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_displayText->DisplayError(err, pObj->RetPosition(0), 5.0f);
- return;
- }
-
- if ( err != ERR_OK )
- {
- m_displayText->DisplayError(err, pObj);
- }
- }
-}
-
-
-// Management of an event.
-
-bool CPyro::EventProcess(const Event &event)
-{
- ParticuleType type;
- Math::Vector pos, speed, angle;
- Math::Point dim;
- float prog, factor, duration;
- int i, r;
-
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_engine->RetPause() ) return true;
-
- m_time += event.rTime;
- m_progress += event.rTime*m_speed;
-
- if ( m_soundChannel != -1 && m_object != 0 )
- {
- pos = m_object->RetPosition(0);
- m_sound->Position(m_soundChannel, pos);
-
- if ( m_lightRank != -1 )
- {
- pos.y += m_lightHeight;
- m_light->SetLightPos(m_lightRank, pos);
- }
- }
-
- if ( m_type == PT_SHOTT &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- if ( m_crashSphereUsed > 0 )
- {
- i = rand()%m_crashSphereUsed;
- pos = m_crashSpherePos[i];
- pos.x += (Math::Rand()-0.5f)*m_crashSphereRadius[i]*2.0f;
- pos.z += (Math::Rand()-0.5f)*m_crashSphereRadius[i]*2.0f;
- speed.x = (Math::Rand()-0.5f)*m_crashSphereRadius[i]*0.5f;
- speed.z = (Math::Rand()-0.5f)*m_crashSphereRadius[i]*0.5f;
- speed.y = Math::Rand()*m_crashSphereRadius[i]*1.0f;
- dim.x = Math::Rand()*m_crashSphereRadius[i]*0.5f+m_crashSphereRadius[i]*0.75f*m_force;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 3.0f);
- }
- else
- {
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*m_size*0.3f;
- pos.z += (Math::Rand()-0.5f)*m_size*0.3f;
- 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;
- dim.x = Math::Rand()*m_size/10.0f+m_size/10.0f*m_force;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 3.0f);
- }
- }
-
- if ( m_type == PT_SHOTH &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- for ( i=0 ; i<10 ; i++ )
- {
- 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;
- speed.x = (Math::Rand()-0.5f)*5.0f;
- speed.z = (Math::Rand()-0.5f)*5.0f;
- speed.y = Math::Rand()*1.0f;
- dim.x = 1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLOOD, Math::Rand()*3.0f+3.0f, Math::Rand()*10.0f+15.0f, 0.5f);
- }
- }
-
- if ( m_type == PT_SHOTM &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- r = (int)(10.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<r ; i++ )
- {
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*20.0f;
- pos.z += (Math::Rand()-0.5f)*20.0f;
- pos.y += 8.0f;
- speed.x = (Math::Rand()-0.5f)*40.0f;
- speed.z = (Math::Rand()-0.5f)*40.0f;
- speed.y = Math::Rand()*40.0f;
- dim.x = Math::Rand()*8.0f+8.0f*m_force;
- dim.y = dim.x;
-
- m_particule->CreateParticule(pos, speed, dim, PARTIBLOODM, 2.0f, 50.0f, 0.0f);
- }
- }
-
- if ( m_type == PT_SHOTW &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- if ( m_crashSphereUsed > 0 )
- {
- i = rand()%m_crashSphereUsed;
- pos = m_crashSpherePos[i];
- pos.x += (Math::Rand()-0.5f)*m_crashSphereRadius[i]*2.0f;
- pos.z += (Math::Rand()-0.5f)*m_crashSphereRadius[i]*2.0f;
- speed.x = (Math::Rand()-0.5f)*m_crashSphereRadius[i]*0.5f;
- speed.z = (Math::Rand()-0.5f)*m_crashSphereRadius[i]*0.5f;
- speed.y = Math::Rand()*m_crashSphereRadius[i]*1.0f;
- dim.x = 1.0f*m_force;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f);
- }
- else
- {
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*m_size*0.3f;
- pos.z += (Math::Rand()-0.5f)*m_size*0.3f;
- 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;
- dim.x = 1.0f*m_force;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f);
- }
- }
-
- if ( m_type == PT_SHOTW &&
- m_lastParticuleSmoke+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticuleSmoke = m_time;
-
- pos = m_pos;
- pos.y -= 2.0f;
- pos.x += (Math::Rand()-0.5f)*4.0f;
- pos.z += (Math::Rand()-0.5f)*4.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 10.0f+Math::Rand()*10.0f;
- dim.x = Math::Rand()*2.5f+2.0f*m_force;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 4.0f);
- }
-
- if ( (m_type == PT_FRAGT || m_type == PT_EXPLOT) &&
- m_progress < 0.05f &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_pos;
- 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;
- dim.x = Math::Rand()*m_size/5.0f+m_size/5.0f;
- dim.y = dim.x;
-
- m_particule->CreateParticule(pos, speed, dim, PARTIEXPLOT);
- }
-
- if ( (m_type == PT_FRAGT || m_type == PT_EXPLOT) &&
- m_progress < 0.10f &&
- m_lastParticuleSmoke+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticuleSmoke = m_time;
-
- dim.x = Math::Rand()*m_size/3.0f+m_size/3.0f;
- dim.y = dim.x;
- 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->MoveOnFloor(pos);
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = -dim.x/2.0f/4.0f;
- pos.y += dim.x/2.0f;
-
- r = rand()%2;
- if ( r == 0 ) type = PARTISMOKE1;
- if ( r == 1 ) type = PARTISMOKE2;
- m_particule->CreateParticule(pos, speed, dim, type, 6.0f);
- }
-
- if ( (m_type == PT_FRAGO || m_type == PT_EXPLOO) &&
- m_progress < 0.03f &&
- m_lastParticule+m_engine->ParticuleAdapt(0.1f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_pos;
- 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;
- dim.x = Math::Rand()*m_size/2.0f+m_size/2.0f;
- dim.y = dim.x;
-
- m_particule->CreateParticule(pos, speed, dim, PARTIEXPLOO);
- }
-
- if ( (m_type == PT_FRAGW || m_type == PT_EXPLOW) &&
- m_progress < 0.05f &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_pos;
- 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;
- dim.x = 1.0f;
- dim.y = dim.x;
-
- m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f);
- }
-
- if ( (m_type == PT_FRAGW || m_type == PT_EXPLOW) &&
- m_progress < 0.25f &&
- m_lastParticuleSmoke+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticuleSmoke = m_time;
-
- pos = m_pos;
- pos.y -= 2.0f;
- pos.x += (Math::Rand()-0.5f)*4.0f;
- pos.z += (Math::Rand()-0.5f)*4.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 4.0f+Math::Rand()*4.0f;
- dim.x = Math::Rand()*2.5f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 4.0f);
- }
-
- if ( m_type == PT_WPCHECK )
- {
- 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_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_pos;
- pos.y += factor;
- pos.x += (Math::Rand()-0.5f)*3.0f;
- pos.z += (Math::Rand()-0.5f)*3.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 5.0f+Math::Rand()*5.0f;
- dim.x = Math::Rand()*1.5f+1.5f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f);
-//? m_particule->CreateParticule(pos, speed, dim, (ParticuleType)(PARTILENS1+rand()%4), 2.0f);
- }
-
- angle = m_object->RetAngle(0);
- 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->SetAngle(0, angle);
-
- pos = m_pos;
- pos.y += factor;
- m_object->SetPosition(0, pos);
-
- if ( m_progress > 0.85f )
- {
- m_object->SetZoom(0, 1.0f-(m_progress-0.85f)/0.15f);
- }
- }
-
- if ( m_type == PT_FLCREATE )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_pos;
- m_terrain->MoveOnFloor(pos);
- pos.x += (Math::Rand()-0.5f)*1.0f;
- pos.z += (Math::Rand()-0.5f)*1.0f;
- speed.x = (Math::Rand()-0.5f)*2.0f;
- speed.z = (Math::Rand()-0.5f)*2.0f;
- speed.y = 2.0f+Math::Rand()*2.0f;
- dim.x = (Math::Rand()*1.0f+1.0f)*(0.2f+m_progress*0.8f);
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.0f);
- }
-
- angle = m_object->RetAngle(0);
-//? angle.y = powf(m_progress, 0.2f)*20.0f;
- 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->SetAngle(0, angle);
-
- m_object->SetZoom(0, m_progress);
- }
-
- if ( m_type == PT_FLDELETE )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_pos;
- m_terrain->MoveOnFloor(pos);
- pos.x += (Math::Rand()-0.5f)*1.0f;
- pos.z += (Math::Rand()-0.5f)*1.0f;
- speed.x = (Math::Rand()-0.5f)*2.0f;
- speed.z = (Math::Rand()-0.5f)*2.0f;
- speed.y = 2.0f+Math::Rand()*2.0f;
- dim.x = (Math::Rand()*1.0f+1.0f)*(0.2f+m_progress*0.8f);
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.5f);
- }
-
- angle = m_object->RetAngle(0);
- 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->SetAngle(0, angle);
-
- m_object->SetZoom(0, 1.0f-m_progress);
- }
-
- if ( m_type == PT_RESET )
- {
-#if 0
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_pos;
- speed.x = (Math::Rand()-0.5f)*6.0f;
- speed.z = (Math::Rand()-0.5f)*6.0f;
- speed.y = Math::Rand()*12.0f;
- dim.x = (Math::Rand()*2.5f+2.5f)*(1.0f-m_progress*0.9f);
- dim.y = dim.x;
- pos.y += dim.y;
- m_particule->CreateParticule(pos, speed, dim,
- (ParticuleType)(PARTILENS1+rand()%4),
- Math::Rand()*2.5f+2.5f,
- Math::Rand()*5.0f+5.0f, 0.0f);
- }
-#else
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 5.0f+Math::Rand()*5.0f;
- dim.x = Math::Rand()*2.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(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;
- duration = Math::Rand()*1.5f+1.5f;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK6,
- duration, 0.0f,
- duration*0.9f, 0.7f);
- }
-#endif
-
- angle = m_object->RetResetAngle();
- m_object->SetAngleY(0, angle.y-powf((1.0f-m_progress)*5.0f, 2.0f));
- m_object->SetZoom(0, m_progress);
- }
-
- if ( m_type == PT_FINDING )
- {
- if ( m_object != 0 &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- factor = m_size*0.3f;
- if ( m_object->RetType() == OBJECT_SAFE ) factor *= 1.3f;
- if ( factor > 40.0f ) factor = 40.0f;
- pos = m_pos;
- m_terrain->MoveOnFloor(pos);
- pos.x += (Math::Rand()-0.5f)*factor;
- pos.z += (Math::Rand()-0.5f)*factor;
- speed.x = (Math::Rand()-0.5f)*2.0f;
- speed.z = (Math::Rand()-0.5f)*2.0f;
- speed.y = 4.0f+Math::Rand()*4.0f;
- dim.x = (Math::Rand()*3.0f+3.0f)*(1.0f-m_progress*0.9f);
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.5f);
- }
- }
-
- if ( (m_type == PT_BURNT || m_type == PT_BURNO) &&
- m_object != 0 )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- factor = m_size/25.0f; // 1 = standard size
-
- pos = m_object->RetPosition(0);
- pos.y -= m_object->RetCharacter()->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;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 0.0f;
- dim.x = (Math::Rand()*2.5f+1.0f)*factor;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIFLAME, 2.0f, 0.0f, 0.2f);
-
- pos = m_object->RetPosition(0);
- pos.y -= m_object->RetCharacter()->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_particule->CreateParticule(pos, speed, dim, PARTIFLAME, 2.0f, 0.0f, 0.2f);
-
- pos = m_object->RetPosition(0);
- 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_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f);
- }
-
- if ( m_type == PT_BURNT )
- {
- BurnProgress();
- }
- else
- {
- 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 )
- {
- prog = (m_progress-0.8f)/0.2f; // 0..1
- speed.y = -prog*6.0f; // sinks into the ground
- m_object->SetZoom(0, 1.0f-prog*0.5f);
- }
- m_object->SetLinVibration(speed);
- }
- }
-
- if ( m_type == PT_WIN )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- pos.y += 1.5f;
- speed.x = (Math::Rand()-0.5f)*10.0f;
- speed.z = (Math::Rand()-0.5f)*10.0f;
- speed.y = 8.0f+Math::Rand()*8.0f;
- dim.x = Math::Rand()*0.2f+0.2f;
- dim.y = dim.x;
- m_particule->CreateTrack(pos, speed, dim,
- (ParticuleType)(PARTITRACK7+rand()%4),
- 3.0f, 20.0f, 1.0f, 0.4f);
- }
- }
-
- if ( m_type == PT_LOST )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- pos.y -= 2.0f;
- pos.x += (Math::Rand()-0.5f)*10.0f;
- pos.z += (Math::Rand()-0.5f)*10.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 1.0f+Math::Rand()*1.0f;
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(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;
-}
-
-// Indicates that the object binds to the effect no longer exists, without deleting it.
-
-void CPyro::CutObjectLink(CObject* pObj)
-{
- if ( m_object == pObj )
- {
- m_object = 0;
- }
-}
-
-// Indicates whether the pyrotechnic effect is complete.
-
-Error CPyro::IsEnded()
-{
- // 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 ||
- 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->SetAngleX(0, 0.0f);
- m_object->SetAngleZ(0, 0.0f);
- m_object->SetZoom(0, 1.0f);
- }
-
- if ( m_type == PT_RESET )
- {
- m_object->SetPosition(0, m_object->RetResetPosition());
- m_object->SetAngle(0, m_object->RetResetAngle());
- m_object->SetZoom(0, 1.0f);
- }
-
- if ( m_lightRank != -1 )
- {
- m_light->DeleteLight(m_lightRank);
- m_lightRank = -1;
- }
-
- return ERR_STOP;
-}
-
-// Removes the binding to a pyrotechnic effect.
-
-void CPyro::DeleteObject(bool bPrimary, bool bSecondary)
-{
- CObject *sub, *truck;
- Math::Vector pos;
- ObjectType type;
-
- if ( m_object == 0 ) return;
-
- if ( m_object->RetResetCap() == RESET_MOVE ) // resettable object?
- {
- m_object->SetEnable(false); // object cache and inactive
- pos = m_object->RetPosition(0);
- pos.y = -100.0f;
- m_object->SetPosition(0, pos);
- return;
- }
-
- type = m_object->RetType();
- if ( bSecondary &&
- type != OBJECT_FACTORY &&
- type != OBJECT_NUCLEAR &&
- type != OBJECT_ENERGY )
- {
- sub = m_object->RetPower();
- if ( sub != 0 )
- {
- sub->DeleteObject(); // removes the battery
- delete sub;
- m_object->SetPower(0);
- }
-
- sub = m_object->RetFret();
- if ( sub != 0 )
- {
- sub->DeleteObject(); // removes the object transported
- delete sub;
- m_object->SetFret(0);
- }
- }
-
- if ( bPrimary )
- {
- truck = m_object->RetTruck();
- if ( truck != 0 ) // object carries?
- {
- if ( truck->RetPower() == m_object )
- {
- truck->SetPower(0);
- }
- if ( truck->RetFret() == m_object )
- {
- truck->SetFret(0);
- }
- }
-
- sub = m_object;
- sub->DeleteObject(); // removes the object (*)
- delete sub;
- m_object = 0;
- }
-}
-
-// (*) CObject :: DeleteObject can reset m_object through CPyro :: CutObjectLink!
-
-
-// Empty the table of operations of animation of light.
-
-void CPyro::LightOperFlush()
-{
- m_lightOperTotal = 0;
-}
-
-// Adds an animation operation of the light.
-
-void CPyro::LightOperAdd(float progress, float intensity,
- float r, float g, float b)
-{
- int i;
-
- i = m_lightOperTotal;
-
- m_lightOper[i].progress = progress;
- m_lightOper[i].intensity = intensity;
- m_lightOper[i].color.r = r;
- m_lightOper[i].color.g = g;
- m_lightOper[i].color.b = b;
-
- m_lightOperTotal ++;
-}
-
-// Makes evolve the associated light.
-
-void CPyro::LightOperFrame(float rTime)
-{
- D3DCOLORVALUE color;
- float progress, intensity;
- int i;
-
- for ( i=0 ; i<m_lightOperTotal ; i++ )
- {
- if ( m_progress < m_lightOper[i].progress )
- {
- progress = (m_progress-m_lightOper[i-1].progress) / (m_lightOper[i].progress-m_lightOper[i-1].progress);
-
- intensity = m_lightOper[i-1].intensity + (m_lightOper[i].intensity-m_lightOper[i-1].intensity)*progress;
- 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_light->SetLightIntensity(m_lightRank, intensity);
- m_light->SetLightColor(m_lightRank, color);
- break;
- }
- }
-}
-
-
-// Creates light to accompany a pyrotechnic effect.
-
-bool CPyro::CreateLight(Math::Vector pos, float height)
-{
- D3DLIGHT7 light;
-
- if ( !m_engine->RetLightMode() ) return true;
-
- m_lightHeight = height;
-
- ZeroMemory( &light, sizeof(light) );
- light.dltType = D3DLIGHT_SPOT;
- light.dvPosition.x = pos.x;
- light.dvPosition.y = pos.y+height;
- light.dvPosition.z = pos.z;
- light.dvDirection.x = 0.0f;
- light.dvDirection.y = -1.0f; // against the bottom
- light.dvDirection.z = 0.0f;
- light.dvRange = D3DLIGHT_RANGE_MAX;
- light.dvFalloff = 1.0f;
- light.dvAttenuation0 = 1.0f;
- light.dvAttenuation1 = 0.0f;
- light.dvAttenuation2 = 0.0f;
- light.dvTheta = 0.0f;
- light.dvPhi = Math::PI/4.0f;
-
- m_lightRank = m_light->CreateLight();
- if ( m_lightRank == -1 ) return false;
-
- m_light->SetLight(m_lightRank, light);
- m_light->SetLightIntensity(m_lightRank, 0.0f);
-
- // Only illuminates the objects on the ground.
- m_light->SetLightIncluType(m_lightRank, TYPETERRAIN);
-
- return true;
-}
-
-
-// Starts the explosion of a vehicle.
-
-void CPyro::ExploStart()
-{
- Math::Vector pos, angle, speed, min, max;
- float weight;
- int i, objRank, channel;
-
- m_burnType = m_object->RetType();
-
- pos = m_object->RetPosition(0);
- m_burnFall = m_terrain->RetFloorHeight(pos, true);
-
- m_object->Simplify();
- m_object->SetLock(true); // ruin not usable yet
- m_object->SetExplo(true); // being destroyed
- m_object->FlatParent();
-
- if ( m_object->RetSelect() )
- {
- m_object->SetSelect(false); // deselects the object
- m_camera->SetType(CAMERA_EXPLO);
- m_main->DeselectAll();
- }
- m_object->DeleteDeselList(m_object);
-
- for ( i=0 ; i<OBJECTMAXPART ; i++ )
- {
- objRank = m_object->RetObjectRank(i);
- if ( objRank == -1 ) continue;
- m_engine->ChangeSecondTexture(objRank, "dirty04.tga");
-
- pos = m_object->RetPosition(i);
-
- if ( i == 0 ) // main part?
- {
- weight = 0.0f;
-
- speed.y = -1.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- }
- else
- {
- m_engine->GetBBox(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;
- }
-
- channel = m_particule->CreatePart(pos, speed, PARTIPART, 10.0f, 20.0f, weight, 0.5f);
- if ( channel != -1 )
- {
- m_object->SetMasterParticule(i, channel);
- }
- }
- m_engine->LoadTexture("dirty04.tga", 1);
-
- DeleteObject(false, true); // destroys the object transported + the battery
-}
-
-// Ends the explosion of a vehicle.
-
-void CPyro::ExploTerminate()
-{
- DeleteObject(true, false); // removes the main object
-}
-
-
-// Starts a vehicle fire.
-
-void CPyro::BurnStart()
-{
- Math::Vector pos, angle;
- int i, objRank;
-
- m_burnType = m_object->RetType();
-
- pos = m_object->RetPosition(0);
- m_burnFall = m_terrain->RetFloorHeight(pos, true);
-
- m_object->Simplify();
- m_object->SetLock(true); // ruin not usable yet
-
- if ( m_object->RetSelect() )
- {
- m_object->SetSelect(false); // deselects the object
- m_camera->SetType(CAMERA_EXPLO);
- m_main->DeselectAll();
- }
- m_object->DeleteDeselList(m_object);
-
- for ( i=0 ; i<OBJECTMAXPART ; i++ )
- {
- objRank = m_object->RetObjectRank(i);
- if ( objRank == -1 ) continue;
- m_engine->ChangeSecondTexture(objRank, "dirty04.tga");
- }
- m_engine->LoadTexture("dirty04.tga", 1);
-
- m_burnPartTotal = 0;
-
- 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_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_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_MOBILEwc ||
- m_burnType == OBJECT_MOBILEwi ||
- m_burnType == OBJECT_MOBILEws ||
- m_burnType == OBJECT_MOBILEwt ) // wheels?
- {
- for ( i=0 ; 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_MOBILEtc ||
- m_burnType == OBJECT_MOBILEti ||
- m_burnType == OBJECT_MOBILEts ||
- m_burnType == OBJECT_MOBILErt ||
- m_burnType == OBJECT_MOBILErc ||
- m_burnType == OBJECT_MOBILErr ||
- m_burnType == OBJECT_MOBILErs ||
- m_burnType == OBJECT_MOBILEsa ||
- 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_MOBILEfc ||
- m_burnType == OBJECT_MOBILEfi ||
- m_burnType == OBJECT_MOBILEfs ||
- m_burnType == OBJECT_MOBILEft ) // flying?
- {
- for ( i=0 ; 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_MOBILEic ||
- m_burnType == OBJECT_MOBILEii ||
- m_burnType == OBJECT_MOBILEis ) // legs?
- {
- for ( 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
- }
- }
-}
-
-// Adds a part move.
-
-void CPyro::BurnAddPart(int part, Math::Vector pos, Math::Vector angle)
-{
- int i;
-
- i = m_burnPartTotal;
- m_burnPart[i].part = part;
- m_burnPart[i].initialPos = m_object->RetPosition(part);
- m_burnPart[i].finalPos = m_burnPart[i].initialPos+pos;
- m_burnPart[i].initialAngle = m_object->RetAngle(part);
- m_burnPart[i].finalAngle = m_burnPart[i].initialAngle+angle;
-
- m_burnPartTotal ++;
-}
-
-// Advances of a vehicle fire.
-
-void CPyro::BurnProgress()
-{
- CObject* sub;
- Math::Vector pos;
- float h;
- int i;
-
- if ( m_burnType == OBJECT_TEEN31 ) // basket?
- {
- m_object->SetZoomY(0, 1.0f-m_progress*0.5f); // slight flattening
- }
-
- for ( i=0 ; i<m_burnPartTotal ; i++ )
- {
- pos = m_burnPart[i].initialPos + m_progress*(m_burnPart[i].finalPos-m_burnPart[i].initialPos);
- if ( i == 0 && m_burnFall > 0.0f )
- {
- h = powf(m_progress, 2.0f)*1000.0f;
- if ( h > m_burnFall ) h = m_burnFall;
- pos.y -= h;
- }
- m_object->SetPosition(m_burnPart[i].part, pos);
-
- pos = m_burnPart[i].initialAngle + m_progress*(m_burnPart[i].finalAngle-m_burnPart[i].initialAngle);
- m_object->SetAngle(m_burnPart[i].part, pos);
- }
-
- sub = m_object->RetPower();
- if ( sub != 0 ) // is there a battery?
- {
- sub->SetZoomY(0, 1.0f-m_progress); // complete flattening
- }
-}
-
-// Indicates whether a part should be retained.
-
-bool CPyro::BurnIsKeepPart(int part)
-{
- int i;
-
- i = 0;
- while ( m_burnKeepPart[i] != -1 )
- {
- if ( part == m_burnKeepPart[i++] ) return true; // must keep
- }
- return false; // must destroy
-}
-
-// Ends the fire of an insect or a vehicle.
-
-void CPyro::BurnTerminate()
-{
- int i, objRank;
-
- if ( m_type == PT_BURNO ) // organic object is burning?
- {
- DeleteObject(true, true); // removes the insect
- return;
- }
-
- for ( i=1 ; i<OBJECTMAXPART ; i++ )
- {
- objRank = m_object->RetObjectRank(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); // others become a ruin
- m_object->SetLock(false);
- }
- else
- {
- m_object->SetType(OBJECT_RUINmobilew1); // others become a ruin
- m_object->SetLock(false);
- }
-
- m_object->SetBurn(false); // ruin usable (c-e-d. recoverable)
-}
-
-
-// Start of an object freight falling.
-
-void CPyro::FallStart()
-{
- Math::Vector pos;
-
- m_object->SetBurn(true); // usable
-
- pos = m_object->RetPosition(0);
- m_fallFloor = m_terrain->RetFloorLevel(pos);
- m_fallSpeed = 0.0f;
- m_fallBulletTime = 0.0f;
- m_bFallEnding = false;
-}
-
-// Seeking an object explode by the falling ball of bees.
-
-CObject* CPyro::FallSearchBeeExplo()
-{
- CObject* pObj;
- Math::Vector iPos, oPos;
- ObjectType oType;
- float iRadius, oRadius, distance, shieldRadius;
- int i, j;
-
- m_object->GetCrashSphere(0, iPos, iRadius);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- oType = pObj->RetType();
- if ( oType != OBJECT_HUMAN &&
- oType != OBJECT_MOBILEfa &&
- oType != OBJECT_MOBILEta &&
- oType != OBJECT_MOBILEwa &&
- oType != OBJECT_MOBILEia &&
- oType != OBJECT_MOBILEfc &&
- oType != OBJECT_MOBILEtc &&
- oType != OBJECT_MOBILEwc &&
- oType != OBJECT_MOBILEic &&
- oType != OBJECT_MOBILEfi &&
- oType != OBJECT_MOBILEti &&
- oType != OBJECT_MOBILEwi &&
- oType != OBJECT_MOBILEii &&
- oType != OBJECT_MOBILEfs &&
- oType != OBJECT_MOBILEts &&
- oType != OBJECT_MOBILEws &&
- oType != OBJECT_MOBILEis &&
- oType != OBJECT_MOBILErt &&
- oType != OBJECT_MOBILErc &&
- oType != OBJECT_MOBILErr &&
- oType != OBJECT_MOBILErs &&
- oType != OBJECT_MOBILEsa &&
- oType != OBJECT_MOBILEtg &&
- oType != OBJECT_MOBILEft &&
- oType != OBJECT_MOBILEtt &&
- oType != OBJECT_MOBILEwt &&
- oType != OBJECT_MOBILEit &&
- oType != OBJECT_MOBILEdr &&
- oType != OBJECT_BASE &&
- oType != OBJECT_DERRICK &&
- oType != OBJECT_STATION &&
- oType != OBJECT_FACTORY &&
- oType != OBJECT_REPAIR &&
- oType != OBJECT_DESTROYER&&
- oType != OBJECT_CONVERT &&
- oType != OBJECT_TOWER &&
- oType != OBJECT_RESEARCH &&
- oType != OBJECT_RADAR &&
- oType != OBJECT_INFO &&
- oType != OBJECT_ENERGY &&
- oType != OBJECT_LABO &&
- oType != OBJECT_NUCLEAR &&
- oType != OBJECT_PARA &&
- oType != OBJECT_SAFE &&
- oType != OBJECT_HUSTON &&
- oType != OBJECT_METAL &&
- oType != OBJECT_POWER &&
- oType != OBJECT_ATOMIC ) continue;
-
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
-
- oPos = pObj->RetPosition(0);
-
- shieldRadius = pObj->RetShieldRadius();
- if ( shieldRadius > 0.0f )
- {
- distance = Math::Distance(oPos, iPos);
- if ( distance <= shieldRadius ) return pObj;
- }
-
- if ( oType == OBJECT_BASE )
- {
- distance = Math::Distance(oPos, iPos);
- if ( distance < 25.0f ) return pObj;
- }
-
- // Test the center of the object, which is necessary for objects
- // that have no sphere in the center (station).
- distance = Math::Distance(oPos, iPos)-4.0f;
- if ( distance < 5.0f ) return pObj;
-
- // Test with all spheres of the object.
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- distance = Math::Distance(oPos, iPos);
- if ( distance <= iRadius+oRadius )
- {
- return pObj;
- }
- }
- }
- return 0;
-}
-
-// Fall of an object's freight.
-
-void CPyro::FallProgress(float rTime)
-{
- CObject* pObj;
- Math::Vector pos;
- bool bFloor = false;
-
- if ( m_object == 0 ) return;
-
- m_fallSpeed += rTime*50.0f; // v2 = v1 + a*dt
- pos = m_object->RetPosition(0);
- pos.y -= m_fallSpeed*rTime; // dd -= v2*dt
-
- if ( pos.y <= m_fallFloor ) // below the ground level?
- {
- pos.y = m_fallFloor;
- bFloor = true;
- }
- m_object->SetPosition(0, pos);
-
- if ( m_object->RetType() == OBJECT_BULLET )
- {
- m_fallBulletTime += rTime;
-
- if ( m_fallBulletTime > 0.2f || bFloor )
- {
- m_fallBulletTime = 0.0f;
-
- pObj = FallSearchBeeExplo();
- if ( pObj == 0 )
- {
- if ( bFloor ) // reaches the ground?
- {
- m_object->ExploObject(EXPLO_BOUM, 0.0f); // start explosion
- }
- }
- else
- {
- if ( pObj->RetShieldRadius() > 0.0f ) // protected by shield?
- {
- m_particule->CreateParticule(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
- {
- if ( pObj->ExploObject(EXPLO_BOUM, 1.0f) ) // start explosion
- {
- DeleteObject(true, true); // removes the ball
- }
- else
- {
- m_object->ExploObject(EXPLO_BOUM, 0.0f); // start explosion
- }
- }
- }
-
- if ( bFloor || pObj != 0 )
- {
- m_bFallEnding = true;
- }
- }
- }
-}
-
-// Indicates whether the fall is over.
-
-Error CPyro::FallIsEnded()
-{
- Math::Vector pos;
-
- if ( m_bFallEnding || m_object == 0 ) return ERR_STOP;
-
- pos = m_object->RetPosition(0);
- if ( pos.y > m_fallFloor ) return ERR_CONTINUE;
-
- m_sound->Play(SOUND_BOUM, pos);
- m_object->SetBurn(false); // usable again
-
- return ERR_STOP;
-}
-
+// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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://www.gnu.org/licenses/. + +// pyro.cpp + + +#include <windows.h> +#include <stdio.h> +#include <d3d.h> + +#include "common/struct.h" +#include "math/const.h" +#include "math/geometry.h" +#include "old/d3dengine.h" +#include "old/d3dmath.h" +#include "common/event.h" +#include "common/misc.h" +#include "common/iman.h" +#include "old/math3d.h" +#include "object/robotmain.h" +#include "old/terrain.h" +#include "old/camera.h" +#include "old/particule.h" +#include "old/light.h" +#include "object/object.h" +#include "object/motion/motion.h" +#include "object/motion/motionhuman.h" +#include "ui/displaytext.h" +#include "old/sound.h" +#include "old/pyro.h" + + + + +// Object's constructor. + +CPyro::CPyro(CInstanceManager* iMan) +{ + m_iMan = iMan; + m_iMan->AddInstance(CLASS_PYRO, this, 100); + + m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE); + m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN); + m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA); + m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE); + m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT); + m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT); + m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN); + m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND); + m_object = 0; + + m_progress = 0.0f; + m_speed = 0.0f; + m_lightRank = -1; + m_soundChannel = -1; + LightOperFlush(); +} + +// Object's destructor. + +CPyro::~CPyro() +{ + m_iMan->DeleteInstance(CLASS_PYRO, this); +} + + +// Destroys the object. + +void CPyro::DeleteObject(bool bAll) +{ + if ( m_lightRank != -1 ) + { + m_light->DeleteLight(m_lightRank); + m_lightRank = -1; + } +} + + +// Creates pyrotechnic effect. + +bool CPyro::Create(PyroType type, CObject* pObj, float force) +{ + Math::Matrix* mat; + CObject* power; + CMotion* motion; + Math::Vector min, max, pos, speed; + Math::Point dim; + ObjectType oType; + Sound sound; + float duration, mass, h, limit; + int part, objRank, total, i, channel; + + m_object = pObj; + m_force = force; + + oType = pObj->RetType(); + objRank = pObj->RetObjectRank(0); + if ( objRank == -1 ) return false; + m_engine->GetBBox(objRank, min, max); + pos = pObj->RetPosition(0); + + DisplayError(type, pObj); // displays eventual messages + + // Copies all spheres of the object. + for ( i=0 ; i<50 ; i++ ) + { + if ( !pObj->GetCrashSphere(i, m_crashSpherePos[i], m_crashSphereRadius[i]) ) break; + } + m_crashSphereUsed = i; + + // 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_type = type; + m_progress = 0.0f; + m_speed = 1.0f/20.0f; + m_time = 0.0f; + m_lastParticule = 0.0f; + m_lastParticuleSmoke = 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. + power = pObj->RetPower(); + if ( power == 0 ) + { + m_bPower = false; + } + else + { + m_bPower = true; + pos = power->RetPosition(0); + pos.y += 1.0f; + mat = pObj->RetWorldMatrix(0); + m_posPower = Math::Transform(*mat, pos); + } + if ( oType == OBJECT_POWER || + oType == OBJECT_ATOMIC || + oType == OBJECT_URANIUM || + oType == OBJECT_TNT || + oType == OBJECT_BOMB ) + { + m_bPower = true; + m_posPower = m_pos; + m_posPower.y += 1.0f; + m_pos = m_posPower; + } + if ( oType == OBJECT_STATION ) + { + m_bPower = true; + mat = pObj->RetWorldMatrix(0); + m_posPower = Math::Transform(*mat, Math::Vector(-15.0f, 7.0f, 0.0f)); + m_pos = m_posPower; + } + if ( oType == OBJECT_ENERGY ) + { + m_bPower = true; + mat = pObj->RetWorldMatrix(0); + m_posPower = Math::Transform(*mat, Math::Vector(-7.0f, 6.0f, 0.0f)); + m_pos = m_posPower; + } + if ( oType == OBJECT_NUCLEAR ) + { + m_bPower = true; + m_posPower = m_pos; + } + if ( oType == OBJECT_PARA ) + { + m_bPower = true; + m_posPower = m_pos; + } + if ( oType == OBJECT_SCRAP4 || + oType == OBJECT_SCRAP5 ) // plastic material? + { + m_bPower = 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 ) + { + if ( m_bPower ) + { + 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); + } + 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->RetEyePt()); + } + 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); + } + if ( type == PT_SHOTH && m_object->RetSelect() ) + { + m_sound->Play(SOUND_AIE, m_pos); + m_sound->Play(SOUND_AIE, m_engine->RetEyePt()); + } + } + + if ( m_type == PT_FRAGT || + m_type == PT_FRAGO || + m_type == PT_FRAGW ) + { + m_engine->ShadowDelete(m_object->RetObjectRank(0)); + } + + if ( m_type == PT_DEADG ) + { + m_object->SetDead(true); + + motion = m_object->RetMotion(); + if ( motion != 0 ) + { + motion->SetAction(MHS_DEADg, 1.0f); + } + m_camera->StartCentering(m_object, Math::PI*0.5f, 99.9f, 0.0f, 1.5f); + m_camera->StartOver(OE_FADEOUTw, m_pos, 1.0f); + m_speed = 1.0f/10.0f; + return true; + } + if ( m_type == PT_DEADW ) + { + m_object->SetDead(true); + + motion = m_object->RetMotion(); + if ( motion != 0 ) + { + motion->SetAction(MHS_DEADw, 4.0f); + } + m_camera->StartCentering(m_object, Math::PI*0.5f, 99.9f, 0.0f, 3.0f); + m_camera->StartOver(OE_FADEOUTb, m_pos, 1.0f); + m_speed = 1.0f/10.0f; + return true; + } + + if ( m_type == PT_SHOTT || + m_type == PT_SHOTM ) + { + m_camera->StartEffect(CE_SHOT, m_pos, force); + m_speed = 1.0f/1.0f; + return true; + } + if ( m_type == PT_SHOTH ) + { + if ( m_object->RetSelect() ) + { + m_camera->StartOver(OE_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->SetEnable(false); // object more functional + } + if ( m_type == PT_FLCREATE ) + { + m_speed = 1.0f/2.0f; + } + if ( m_type == PT_FLDELETE ) + { + m_speed = 1.0f/2.0f; + m_object->SetEnable(false); // object more functional + } + if ( m_type == PT_RESET ) + { + m_speed = 1.0f/2.0f; + m_object->SetPosition(0, m_object->RetResetPosition()); + m_object->SetAngle(0, m_object->RetResetAngle()); + m_object->SetZoom(0, 0.0f); + } + if ( m_type == PT_FINDING ) + { + 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_EXPLOT || + m_type == PT_EXPLOO || + m_type == PT_EXPLOW ) + { + CreateTriangle(pObj, oType, 0); + m_engine->ShadowDelete(m_object->RetObjectRank(0)); + 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 = Math::Vector(-3.0f, 2.0f, 0.0f); + mat = pObj->RetWorldMatrix(0); + m_pos = Math::Transform(*mat, pos); + + m_engine->ShadowDelete(m_object->RetObjectRank(0)); + } + + if ( m_type != PT_EGG && + m_type != PT_WIN && + m_type != PT_LOST ) + { + 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_camera->StartEffect(CE_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 || + 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 ) ) + { + for ( part=0 ; part<OBJECTMAXPART ; part++ ) + { + CreateTriangle(pObj, oType, part); + } + } + + if ( m_type == PT_FRAGT || + m_type == PT_EXPLOT ) + { + if ( m_bPower ) + { + total = (int)(10.0f*m_engine->RetParticuleDensity()); + if ( oType == OBJECT_TNT || + oType == OBJECT_BOMB ) total *= 3; + for ( i=0 ; i<total ; i++ ) + { + pos = m_posPower; + speed.x = (Math::Rand()-0.5f)*30.0f; + speed.z = (Math::Rand()-0.5f)*30.0f; + speed.y = Math::Rand()*30.0f; + dim.x = 1.0f; + dim.y = dim.x; + duration = Math::Rand()*3.0f+2.0f; + mass = Math::Rand()*10.0f+15.0f; + m_particule->CreateTrack(pos, speed, dim, PARTITRACK1, + duration, mass, Math::Rand()+0.7f, 1.0f); + } + } + + if ( m_size > 10.0f ) // large enough (freight excluded)? + { + if ( m_bPower ) + { + pos = m_posPower; + } + else + { + pos = m_pos; + m_terrain->MoveOnFloor(pos); + pos.y += 1.0f; + } + dim.x = m_size*0.4f; + dim.y = dim.x; + m_particule->CreateParticule(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 ) + { + total = (int)(10.0f*m_engine->RetParticuleDensity()); + for ( i=0 ; i<total ; i++ ) + { + pos = m_pos; + speed.x = (Math::Rand()-0.5f)*30.0f; + speed.z = (Math::Rand()-0.5f)*30.0f; + speed.y = Math::Rand()*50.0f; + dim.x = 1.0f; + dim.y = dim.x; + duration = Math::Rand()*1.0f+0.8f; + mass = Math::Rand()*10.0f+15.0f; + m_particule->CreateParticule(pos, speed, dim, PARTIORGANIC1, + duration, mass); + } + total = (int)(5.0f*m_engine->RetParticuleDensity()); + for ( i=0 ; i<total ; i++ ) + { + pos = m_pos; + speed.x = (Math::Rand()-0.5f)*30.0f; + speed.z = (Math::Rand()-0.5f)*30.0f; + speed.y = Math::Rand()*50.0f; + dim.x = 1.0f; + dim.y = dim.x; + duration = Math::Rand()*2.0f+1.4f; + mass = Math::Rand()*10.0f+15.0f; + m_particule->CreateTrack(pos, speed, dim, PARTITRACK4, + duration, mass, duration*0.5f, dim.x*2.0f); + } + } + + if ( m_type == PT_SPIDER ) + { + for ( 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; + speed.x = (Math::Rand()-0.5f)*24.0f; + speed.z = (Math::Rand()-0.5f)*24.0f; + speed.y = 10.0f+Math::Rand()*10.0f; + dim.x = 1.0f; + dim.y = dim.x; + channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN3, 2.0f+Math::Rand()*2.0f, 10.0f); + m_particule->SetObjectFather(channel, pObj); + } + total = (int)(10.0f*m_engine->RetParticuleDensity()); + for ( 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; + speed.x = (Math::Rand()-0.5f)*24.0f; + speed.z = (Math::Rand()-0.5f)*24.0f; + speed.y = 7.0f+Math::Rand()*7.0f; + dim.x = 1.0f; + dim.y = dim.x; + m_particule->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_bPower ) + { + pos = m_pos; +//? m_terrain->MoveOnFloor(pos); +//? pos.y += 2.0f; + speed = Math::Vector(0.0f, 0.0f, 0.0f); + dim.x = m_size; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTICHOC, 2.0f); + } + } + + return true; +} + +// Creates an explosion with triangular form of particles. + +void CPyro::CreateTriangle(CObject* pObj, ObjectType oType, int part) +{ + D3DTriangle buffer[100]; + Math::Matrix* mat; + Math::Vector offset, pos, speed; + float percent, min, max, h, duration, mass; + int objRank, total, i; + + objRank = pObj->RetObjectRank(part); + if ( objRank == -1 ) return; + + min = 0.0f; + max = m_engine->RetLimitLOD(0); + total = m_engine->RetTotalTriangles(objRank); + percent = 0.10f; + if ( total < 50 ) percent = 0.25f; + if ( total < 20 ) percent = 0.50f; + if ( m_type == PT_EGG ) percent = 0.30f; + if ( oType == OBJECT_POWER || + oType == OBJECT_ATOMIC || + oType == OBJECT_URANIUM || + oType == OBJECT_TNT || + oType == OBJECT_BOMB ) percent = 0.75f; + if ( oType == OBJECT_MOBILEtg ) percent = 0.50f; + if ( oType == OBJECT_TEEN28 ) percent = 0.75f; + if ( oType == OBJECT_MOTHER ) max = 1000000.0f; + if ( oType == OBJECT_TEEN28 ) max = 1000000.0f; + if ( oType == OBJECT_TEEN31 ) max = 1000000.0f; + total = m_engine->GetTriangles(objRank, min, max, buffer, 100, percent); + + for ( i=0 ; i<total ; i++ ) + { + Math::Vector p1, p2, p3; + + p1.x = buffer[i].triangle[0].x; + p1.y = buffer[i].triangle[0].y; + p1.z = buffer[i].triangle[0].z; + p2.x = buffer[i].triangle[1].x; + p2.y = buffer[i].triangle[1].y; + p2.z = buffer[i].triangle[1].z; + p3.x = buffer[i].triangle[2].x; + p3.y = buffer[i].triangle[2].y; + p3.z = buffer[i].triangle[2].z; + + 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].x = p1.x; + buffer[i].triangle[0].y = p1.y; + buffer[i].triangle[0].z = p1.z; + buffer[i].triangle[1].x = p2.x; + buffer[i].triangle[1].y = p2.y; + buffer[i].triangle[1].z = p2.z; + buffer[i].triangle[2].x = p3.x; + buffer[i].triangle[2].y = p3.y; + buffer[i].triangle[2].z = p3.z; + + offset.x = (buffer[i].triangle[0].x+buffer[i].triangle[1].x+buffer[i].triangle[2].x)/3.0f; + offset.y = (buffer[i].triangle[0].y+buffer[i].triangle[1].y+buffer[i].triangle[2].y)/3.0f; + offset.z = (buffer[i].triangle[0].z+buffer[i].triangle[1].z+buffer[i].triangle[2].z)/3.0f; + + buffer[i].triangle[0].x -= offset.x; + buffer[i].triangle[1].x -= offset.x; + buffer[i].triangle[2].x -= offset.x; + + buffer[i].triangle[0].y -= offset.y; + buffer[i].triangle[1].y -= offset.y; + buffer[i].triangle[2].y -= offset.y; + + buffer[i].triangle[0].z -= offset.z; + buffer[i].triangle[1].z -= offset.z; + buffer[i].triangle[2].z -= offset.z; + + mat = pObj->RetWorldMatrix(part); + pos = Math::Transform(*mat, offset); + if ( m_type == PT_EGG ) + { + 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; + duration = Math::Rand()*3.0f+3.0f; + m_particule->CreateFrag(pos, speed, &buffer[i], PARTIFRAG, + duration, mass, 0.5f); + } +} + +// Displays the error or eventual information, +// linked to the destruction of an insect, a vehicle or building. + +void CPyro::DisplayError(PyroType type, CObject* pObj) +{ + ObjectType oType; + Error err; + + oType = pObj->RetType(); + + 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 ) + { + 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 || + oType == OBJECT_MOBILEwc || + oType == OBJECT_MOBILEtc || + oType == OBJECT_MOBILEfc || + oType == OBJECT_MOBILEic || + oType == OBJECT_MOBILEwi || + oType == OBJECT_MOBILEti || + oType == OBJECT_MOBILEfi || + oType == OBJECT_MOBILEii || + oType == OBJECT_MOBILEws || + oType == OBJECT_MOBILEts || + oType == OBJECT_MOBILEfs || + oType == OBJECT_MOBILEis || + oType == OBJECT_MOBILErt || + oType == OBJECT_MOBILErc || + oType == OBJECT_MOBILErr || + oType == OBJECT_MOBILErs || + oType == OBJECT_MOBILEsa || + oType == OBJECT_MOBILEwt || + oType == OBJECT_MOBILEtt || + oType == OBJECT_MOBILEft || + oType == OBJECT_MOBILEit || + oType == OBJECT_MOBILEdr ) + { + 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_displayText->DisplayError(err, pObj->RetPosition(0), 5.0f); + return; + } + + if ( err != ERR_OK ) + { + m_displayText->DisplayError(err, pObj); + } + } +} + + +// Management of an event. + +bool CPyro::EventProcess(const Event &event) +{ + ParticuleType type; + Math::Vector pos, speed, angle; + Math::Point dim; + float prog, factor, duration; + int i, r; + + if ( event.event != EVENT_FRAME ) return true; + if ( m_engine->RetPause() ) return true; + + m_time += event.rTime; + m_progress += event.rTime*m_speed; + + if ( m_soundChannel != -1 && m_object != 0 ) + { + pos = m_object->RetPosition(0); + m_sound->Position(m_soundChannel, pos); + + if ( m_lightRank != -1 ) + { + pos.y += m_lightHeight; + m_light->SetLightPos(m_lightRank, pos); + } + } + + if ( m_type == PT_SHOTT && + m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + if ( m_crashSphereUsed > 0 ) + { + i = rand()%m_crashSphereUsed; + pos = m_crashSpherePos[i]; + pos.x += (Math::Rand()-0.5f)*m_crashSphereRadius[i]*2.0f; + pos.z += (Math::Rand()-0.5f)*m_crashSphereRadius[i]*2.0f; + speed.x = (Math::Rand()-0.5f)*m_crashSphereRadius[i]*0.5f; + speed.z = (Math::Rand()-0.5f)*m_crashSphereRadius[i]*0.5f; + speed.y = Math::Rand()*m_crashSphereRadius[i]*1.0f; + dim.x = Math::Rand()*m_crashSphereRadius[i]*0.5f+m_crashSphereRadius[i]*0.75f*m_force; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 3.0f); + } + else + { + pos = m_pos; + pos.x += (Math::Rand()-0.5f)*m_size*0.3f; + pos.z += (Math::Rand()-0.5f)*m_size*0.3f; + 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; + dim.x = Math::Rand()*m_size/10.0f+m_size/10.0f*m_force; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 3.0f); + } + } + + if ( m_type == PT_SHOTH && + m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + for ( i=0 ; i<10 ; i++ ) + { + 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; + speed.x = (Math::Rand()-0.5f)*5.0f; + speed.z = (Math::Rand()-0.5f)*5.0f; + speed.y = Math::Rand()*1.0f; + dim.x = 1.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIBLOOD, Math::Rand()*3.0f+3.0f, Math::Rand()*10.0f+15.0f, 0.5f); + } + } + + if ( m_type == PT_SHOTM && + m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + r = (int)(10.0f*m_engine->RetParticuleDensity()); + for ( i=0 ; i<r ; i++ ) + { + pos = m_pos; + pos.x += (Math::Rand()-0.5f)*20.0f; + pos.z += (Math::Rand()-0.5f)*20.0f; + pos.y += 8.0f; + speed.x = (Math::Rand()-0.5f)*40.0f; + speed.z = (Math::Rand()-0.5f)*40.0f; + speed.y = Math::Rand()*40.0f; + dim.x = Math::Rand()*8.0f+8.0f*m_force; + dim.y = dim.x; + + m_particule->CreateParticule(pos, speed, dim, PARTIBLOODM, 2.0f, 50.0f, 0.0f); + } + } + + if ( m_type == PT_SHOTW && + m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + if ( m_crashSphereUsed > 0 ) + { + i = rand()%m_crashSphereUsed; + pos = m_crashSpherePos[i]; + pos.x += (Math::Rand()-0.5f)*m_crashSphereRadius[i]*2.0f; + pos.z += (Math::Rand()-0.5f)*m_crashSphereRadius[i]*2.0f; + speed.x = (Math::Rand()-0.5f)*m_crashSphereRadius[i]*0.5f; + speed.z = (Math::Rand()-0.5f)*m_crashSphereRadius[i]*0.5f; + speed.y = Math::Rand()*m_crashSphereRadius[i]*1.0f; + dim.x = 1.0f*m_force; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f); + } + else + { + pos = m_pos; + pos.x += (Math::Rand()-0.5f)*m_size*0.3f; + pos.z += (Math::Rand()-0.5f)*m_size*0.3f; + 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; + dim.x = 1.0f*m_force; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f); + } + } + + if ( m_type == PT_SHOTW && + m_lastParticuleSmoke+m_engine->ParticuleAdapt(0.10f) <= m_time ) + { + m_lastParticuleSmoke = m_time; + + pos = m_pos; + pos.y -= 2.0f; + pos.x += (Math::Rand()-0.5f)*4.0f; + pos.z += (Math::Rand()-0.5f)*4.0f; + speed.x = 0.0f; + speed.z = 0.0f; + speed.y = 10.0f+Math::Rand()*10.0f; + dim.x = Math::Rand()*2.5f+2.0f*m_force; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 4.0f); + } + + if ( (m_type == PT_FRAGT || m_type == PT_EXPLOT) && + m_progress < 0.05f && + m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_pos; + 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; + dim.x = Math::Rand()*m_size/5.0f+m_size/5.0f; + dim.y = dim.x; + + m_particule->CreateParticule(pos, speed, dim, PARTIEXPLOT); + } + + if ( (m_type == PT_FRAGT || m_type == PT_EXPLOT) && + m_progress < 0.10f && + m_lastParticuleSmoke+m_engine->ParticuleAdapt(0.10f) <= m_time ) + { + m_lastParticuleSmoke = m_time; + + dim.x = Math::Rand()*m_size/3.0f+m_size/3.0f; + dim.y = dim.x; + 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->MoveOnFloor(pos); + speed.x = 0.0f; + speed.z = 0.0f; + speed.y = -dim.x/2.0f/4.0f; + pos.y += dim.x/2.0f; + + r = rand()%2; + if ( r == 0 ) type = PARTISMOKE1; + if ( r == 1 ) type = PARTISMOKE2; + m_particule->CreateParticule(pos, speed, dim, type, 6.0f); + } + + if ( (m_type == PT_FRAGO || m_type == PT_EXPLOO) && + m_progress < 0.03f && + m_lastParticule+m_engine->ParticuleAdapt(0.1f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_pos; + 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; + dim.x = Math::Rand()*m_size/2.0f+m_size/2.0f; + dim.y = dim.x; + + m_particule->CreateParticule(pos, speed, dim, PARTIEXPLOO); + } + + if ( (m_type == PT_FRAGW || m_type == PT_EXPLOW) && + m_progress < 0.05f && + m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_pos; + 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; + dim.x = 1.0f; + dim.y = dim.x; + + m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f); + } + + if ( (m_type == PT_FRAGW || m_type == PT_EXPLOW) && + m_progress < 0.25f && + m_lastParticuleSmoke+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticuleSmoke = m_time; + + pos = m_pos; + pos.y -= 2.0f; + pos.x += (Math::Rand()-0.5f)*4.0f; + pos.z += (Math::Rand()-0.5f)*4.0f; + speed.x = 0.0f; + speed.z = 0.0f; + speed.y = 4.0f+Math::Rand()*4.0f; + dim.x = Math::Rand()*2.5f+2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 4.0f); + } + + if ( m_type == PT_WPCHECK ) + { + 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_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_pos; + pos.y += factor; + pos.x += (Math::Rand()-0.5f)*3.0f; + pos.z += (Math::Rand()-0.5f)*3.0f; + speed.x = 0.0f; + speed.z = 0.0f; + speed.y = 5.0f+Math::Rand()*5.0f; + dim.x = Math::Rand()*1.5f+1.5f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f); +//? m_particule->CreateParticule(pos, speed, dim, (ParticuleType)(PARTILENS1+rand()%4), 2.0f); + } + + angle = m_object->RetAngle(0); + 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->SetAngle(0, angle); + + pos = m_pos; + pos.y += factor; + m_object->SetPosition(0, pos); + + if ( m_progress > 0.85f ) + { + m_object->SetZoom(0, 1.0f-(m_progress-0.85f)/0.15f); + } + } + + if ( m_type == PT_FLCREATE ) + { + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_pos; + m_terrain->MoveOnFloor(pos); + pos.x += (Math::Rand()-0.5f)*1.0f; + pos.z += (Math::Rand()-0.5f)*1.0f; + speed.x = (Math::Rand()-0.5f)*2.0f; + speed.z = (Math::Rand()-0.5f)*2.0f; + speed.y = 2.0f+Math::Rand()*2.0f; + dim.x = (Math::Rand()*1.0f+1.0f)*(0.2f+m_progress*0.8f); + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.0f); + } + + angle = m_object->RetAngle(0); +//? angle.y = powf(m_progress, 0.2f)*20.0f; + 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->SetAngle(0, angle); + + m_object->SetZoom(0, m_progress); + } + + if ( m_type == PT_FLDELETE ) + { + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_pos; + m_terrain->MoveOnFloor(pos); + pos.x += (Math::Rand()-0.5f)*1.0f; + pos.z += (Math::Rand()-0.5f)*1.0f; + speed.x = (Math::Rand()-0.5f)*2.0f; + speed.z = (Math::Rand()-0.5f)*2.0f; + speed.y = 2.0f+Math::Rand()*2.0f; + dim.x = (Math::Rand()*1.0f+1.0f)*(0.2f+m_progress*0.8f); + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.5f); + } + + angle = m_object->RetAngle(0); + 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->SetAngle(0, angle); + + m_object->SetZoom(0, 1.0f-m_progress); + } + + if ( m_type == PT_RESET ) + { +#if 0 + if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_pos; + speed.x = (Math::Rand()-0.5f)*6.0f; + speed.z = (Math::Rand()-0.5f)*6.0f; + speed.y = Math::Rand()*12.0f; + dim.x = (Math::Rand()*2.5f+2.5f)*(1.0f-m_progress*0.9f); + dim.y = dim.x; + pos.y += dim.y; + m_particule->CreateParticule(pos, speed, dim, + (ParticuleType)(PARTILENS1+rand()%4), + Math::Rand()*2.5f+2.5f, + Math::Rand()*5.0f+5.0f, 0.0f); + } +#else + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_pos; + pos.x += (Math::Rand()-0.5f)*5.0f; + pos.z += (Math::Rand()-0.5f)*5.0f; + speed.x = 0.0f; + speed.z = 0.0f; + speed.y = 5.0f+Math::Rand()*5.0f; + dim.x = Math::Rand()*2.0f+2.0f; + dim.y = dim.x; + m_particule->CreateParticule(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; + duration = Math::Rand()*1.5f+1.5f; + m_particule->CreateTrack(pos, speed, dim, PARTITRACK6, + duration, 0.0f, + duration*0.9f, 0.7f); + } +#endif + + angle = m_object->RetResetAngle(); + m_object->SetAngleY(0, angle.y-powf((1.0f-m_progress)*5.0f, 2.0f)); + m_object->SetZoom(0, m_progress); + } + + if ( m_type == PT_FINDING ) + { + if ( m_object != 0 && + m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + factor = m_size*0.3f; + if ( m_object->RetType() == OBJECT_SAFE ) factor *= 1.3f; + if ( factor > 40.0f ) factor = 40.0f; + pos = m_pos; + m_terrain->MoveOnFloor(pos); + pos.x += (Math::Rand()-0.5f)*factor; + pos.z += (Math::Rand()-0.5f)*factor; + speed.x = (Math::Rand()-0.5f)*2.0f; + speed.z = (Math::Rand()-0.5f)*2.0f; + speed.y = 4.0f+Math::Rand()*4.0f; + dim.x = (Math::Rand()*3.0f+3.0f)*(1.0f-m_progress*0.9f); + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.5f); + } + } + + if ( (m_type == PT_BURNT || m_type == PT_BURNO) && + m_object != 0 ) + { + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + factor = m_size/25.0f; // 1 = standard size + + pos = m_object->RetPosition(0); + pos.y -= m_object->RetCharacter()->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; + speed.x = 0.0f; + speed.z = 0.0f; + speed.y = 0.0f; + dim.x = (Math::Rand()*2.5f+1.0f)*factor; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIFLAME, 2.0f, 0.0f, 0.2f); + + pos = m_object->RetPosition(0); + pos.y -= m_object->RetCharacter()->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_particule->CreateParticule(pos, speed, dim, PARTIFLAME, 2.0f, 0.0f, 0.2f); + + pos = m_object->RetPosition(0); + 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_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f); + } + + if ( m_type == PT_BURNT ) + { + BurnProgress(); + } + else + { + 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 ) + { + prog = (m_progress-0.8f)/0.2f; // 0..1 + speed.y = -prog*6.0f; // sinks into the ground + m_object->SetZoom(0, 1.0f-prog*0.5f); + } + m_object->SetLinVibration(speed); + } + } + + if ( m_type == PT_WIN ) + { + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_object->RetPosition(0); + pos.y += 1.5f; + speed.x = (Math::Rand()-0.5f)*10.0f; + speed.z = (Math::Rand()-0.5f)*10.0f; + speed.y = 8.0f+Math::Rand()*8.0f; + dim.x = Math::Rand()*0.2f+0.2f; + dim.y = dim.x; + m_particule->CreateTrack(pos, speed, dim, + (ParticuleType)(PARTITRACK7+rand()%4), + 3.0f, 20.0f, 1.0f, 0.4f); + } + } + + if ( m_type == PT_LOST ) + { + if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_object->RetPosition(0); + pos.y -= 2.0f; + pos.x += (Math::Rand()-0.5f)*10.0f; + pos.z += (Math::Rand()-0.5f)*10.0f; + speed.x = 0.0f; + speed.z = 0.0f; + speed.y = 1.0f+Math::Rand()*1.0f; + dim.x = Math::Rand()*1.0f+1.0f; + dim.y = dim.x; + m_particule->CreateParticule(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; +} + +// Indicates that the object binds to the effect no longer exists, without deleting it. + +void CPyro::CutObjectLink(CObject* pObj) +{ + if ( m_object == pObj ) + { + m_object = 0; + } +} + +// Indicates whether the pyrotechnic effect is complete. + +Error CPyro::IsEnded() +{ + // 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 || + 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->SetAngleX(0, 0.0f); + m_object->SetAngleZ(0, 0.0f); + m_object->SetZoom(0, 1.0f); + } + + if ( m_type == PT_RESET ) + { + m_object->SetPosition(0, m_object->RetResetPosition()); + m_object->SetAngle(0, m_object->RetResetAngle()); + m_object->SetZoom(0, 1.0f); + } + + if ( m_lightRank != -1 ) + { + m_light->DeleteLight(m_lightRank); + m_lightRank = -1; + } + + return ERR_STOP; +} + +// Removes the binding to a pyrotechnic effect. + +void CPyro::DeleteObject(bool bPrimary, bool bSecondary) +{ + CObject *sub, *truck; + Math::Vector pos; + ObjectType type; + + if ( m_object == 0 ) return; + + if ( m_object->RetResetCap() == RESET_MOVE ) // resettable object? + { + m_object->SetEnable(false); // object cache and inactive + pos = m_object->RetPosition(0); + pos.y = -100.0f; + m_object->SetPosition(0, pos); + return; + } + + type = m_object->RetType(); + if ( bSecondary && + type != OBJECT_FACTORY && + type != OBJECT_NUCLEAR && + type != OBJECT_ENERGY ) + { + sub = m_object->RetPower(); + if ( sub != 0 ) + { + sub->DeleteObject(); // removes the battery + delete sub; + m_object->SetPower(0); + } + + sub = m_object->RetFret(); + if ( sub != 0 ) + { + sub->DeleteObject(); // removes the object transported + delete sub; + m_object->SetFret(0); + } + } + + if ( bPrimary ) + { + truck = m_object->RetTruck(); + if ( truck != 0 ) // object carries? + { + if ( truck->RetPower() == m_object ) + { + truck->SetPower(0); + } + if ( truck->RetFret() == m_object ) + { + truck->SetFret(0); + } + } + + sub = m_object; + sub->DeleteObject(); // removes the object (*) + delete sub; + m_object = 0; + } +} + +// (*) CObject :: DeleteObject can reset m_object through CPyro :: CutObjectLink! + + +// Empty the table of operations of animation of light. + +void CPyro::LightOperFlush() +{ + m_lightOperTotal = 0; +} + +// Adds an animation operation of the light. + +void CPyro::LightOperAdd(float progress, float intensity, + float r, float g, float b) +{ + int i; + + i = m_lightOperTotal; + + m_lightOper[i].progress = progress; + m_lightOper[i].intensity = intensity; + m_lightOper[i].color.r = r; + m_lightOper[i].color.g = g; + m_lightOper[i].color.b = b; + + m_lightOperTotal ++; +} + +// Makes evolve the associated light. + +void CPyro::LightOperFrame(float rTime) +{ + D3DCOLORVALUE color; + float progress, intensity; + int i; + + for ( i=0 ; i<m_lightOperTotal ; i++ ) + { + if ( m_progress < m_lightOper[i].progress ) + { + progress = (m_progress-m_lightOper[i-1].progress) / (m_lightOper[i].progress-m_lightOper[i-1].progress); + + intensity = m_lightOper[i-1].intensity + (m_lightOper[i].intensity-m_lightOper[i-1].intensity)*progress; + 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_light->SetLightIntensity(m_lightRank, intensity); + m_light->SetLightColor(m_lightRank, color); + break; + } + } +} + + +// Creates light to accompany a pyrotechnic effect. + +bool CPyro::CreateLight(Math::Vector pos, float height) +{ + D3DLIGHT7 light; + + if ( !m_engine->RetLightMode() ) return true; + + m_lightHeight = height; + + ZeroMemory( &light, sizeof(light) ); + light.dltType = D3DLIGHT_SPOT; + light.dvPosition.x = pos.x; + light.dvPosition.y = pos.y+height; + light.dvPosition.z = pos.z; + light.dvDirection.x = 0.0f; + light.dvDirection.y = -1.0f; // against the bottom + light.dvDirection.z = 0.0f; + light.dvRange = D3DLIGHT_RANGE_MAX; + light.dvFalloff = 1.0f; + light.dvAttenuation0 = 1.0f; + light.dvAttenuation1 = 0.0f; + light.dvAttenuation2 = 0.0f; + light.dvTheta = 0.0f; + light.dvPhi = Math::PI/4.0f; + + m_lightRank = m_light->CreateLight(); + if ( m_lightRank == -1 ) return false; + + m_light->SetLight(m_lightRank, light); + m_light->SetLightIntensity(m_lightRank, 0.0f); + + // Only illuminates the objects on the ground. + m_light->SetLightIncluType(m_lightRank, TYPETERRAIN); + + return true; +} + + +// Starts the explosion of a vehicle. + +void CPyro::ExploStart() +{ + Math::Vector pos, angle, speed, min, max; + float weight; + int i, objRank, channel; + + m_burnType = m_object->RetType(); + + pos = m_object->RetPosition(0); + m_burnFall = m_terrain->RetFloorHeight(pos, true); + + m_object->Simplify(); + m_object->SetLock(true); // ruin not usable yet + m_object->SetExplo(true); // being destroyed + m_object->FlatParent(); + + if ( m_object->RetSelect() ) + { + m_object->SetSelect(false); // deselects the object + m_camera->SetType(CAMERA_EXPLO); + m_main->DeselectAll(); + } + m_object->DeleteDeselList(m_object); + + for ( i=0 ; i<OBJECTMAXPART ; i++ ) + { + objRank = m_object->RetObjectRank(i); + if ( objRank == -1 ) continue; + m_engine->ChangeSecondTexture(objRank, "dirty04.tga"); + + pos = m_object->RetPosition(i); + + if ( i == 0 ) // main part? + { + weight = 0.0f; + + speed.y = -1.0f; + speed.x = 0.0f; + speed.z = 0.0f; + } + else + { + m_engine->GetBBox(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; + } + + channel = m_particule->CreatePart(pos, speed, PARTIPART, 10.0f, 20.0f, weight, 0.5f); + if ( channel != -1 ) + { + m_object->SetMasterParticule(i, channel); + } + } + m_engine->LoadTexture("dirty04.tga", 1); + + DeleteObject(false, true); // destroys the object transported + the battery +} + +// Ends the explosion of a vehicle. + +void CPyro::ExploTerminate() +{ + DeleteObject(true, false); // removes the main object +} + + +// Starts a vehicle fire. + +void CPyro::BurnStart() +{ + Math::Vector pos, angle; + int i, objRank; + + m_burnType = m_object->RetType(); + + pos = m_object->RetPosition(0); + m_burnFall = m_terrain->RetFloorHeight(pos, true); + + m_object->Simplify(); + m_object->SetLock(true); // ruin not usable yet + + if ( m_object->RetSelect() ) + { + m_object->SetSelect(false); // deselects the object + m_camera->SetType(CAMERA_EXPLO); + m_main->DeselectAll(); + } + m_object->DeleteDeselList(m_object); + + for ( i=0 ; i<OBJECTMAXPART ; i++ ) + { + objRank = m_object->RetObjectRank(i); + if ( objRank == -1 ) continue; + m_engine->ChangeSecondTexture(objRank, "dirty04.tga"); + } + m_engine->LoadTexture("dirty04.tga", 1); + + m_burnPartTotal = 0; + + 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_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_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_MOBILEwc || + m_burnType == OBJECT_MOBILEwi || + m_burnType == OBJECT_MOBILEws || + m_burnType == OBJECT_MOBILEwt ) // wheels? + { + for ( i=0 ; 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_MOBILEtc || + m_burnType == OBJECT_MOBILEti || + m_burnType == OBJECT_MOBILEts || + m_burnType == OBJECT_MOBILErt || + m_burnType == OBJECT_MOBILErc || + m_burnType == OBJECT_MOBILErr || + m_burnType == OBJECT_MOBILErs || + m_burnType == OBJECT_MOBILEsa || + 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_MOBILEfc || + m_burnType == OBJECT_MOBILEfi || + m_burnType == OBJECT_MOBILEfs || + m_burnType == OBJECT_MOBILEft ) // flying? + { + for ( i=0 ; 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_MOBILEic || + m_burnType == OBJECT_MOBILEii || + m_burnType == OBJECT_MOBILEis ) // legs? + { + for ( 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 + } + } +} + +// Adds a part move. + +void CPyro::BurnAddPart(int part, Math::Vector pos, Math::Vector angle) +{ + int i; + + i = m_burnPartTotal; + m_burnPart[i].part = part; + m_burnPart[i].initialPos = m_object->RetPosition(part); + m_burnPart[i].finalPos = m_burnPart[i].initialPos+pos; + m_burnPart[i].initialAngle = m_object->RetAngle(part); + m_burnPart[i].finalAngle = m_burnPart[i].initialAngle+angle; + + m_burnPartTotal ++; +} + +// Advances of a vehicle fire. + +void CPyro::BurnProgress() +{ + CObject* sub; + Math::Vector pos; + float h; + int i; + + if ( m_burnType == OBJECT_TEEN31 ) // basket? + { + m_object->SetZoomY(0, 1.0f-m_progress*0.5f); // slight flattening + } + + for ( i=0 ; i<m_burnPartTotal ; i++ ) + { + pos = m_burnPart[i].initialPos + m_progress*(m_burnPart[i].finalPos-m_burnPart[i].initialPos); + if ( i == 0 && m_burnFall > 0.0f ) + { + h = powf(m_progress, 2.0f)*1000.0f; + if ( h > m_burnFall ) h = m_burnFall; + pos.y -= h; + } + m_object->SetPosition(m_burnPart[i].part, pos); + + pos = m_burnPart[i].initialAngle + m_progress*(m_burnPart[i].finalAngle-m_burnPart[i].initialAngle); + m_object->SetAngle(m_burnPart[i].part, pos); + } + + sub = m_object->RetPower(); + if ( sub != 0 ) // is there a battery? + { + sub->SetZoomY(0, 1.0f-m_progress); // complete flattening + } +} + +// Indicates whether a part should be retained. + +bool CPyro::BurnIsKeepPart(int part) +{ + int i; + + i = 0; + while ( m_burnKeepPart[i] != -1 ) + { + if ( part == m_burnKeepPart[i++] ) return true; // must keep + } + return false; // must destroy +} + +// Ends the fire of an insect or a vehicle. + +void CPyro::BurnTerminate() +{ + int i, objRank; + + if ( m_type == PT_BURNO ) // organic object is burning? + { + DeleteObject(true, true); // removes the insect + return; + } + + for ( i=1 ; i<OBJECTMAXPART ; i++ ) + { + objRank = m_object->RetObjectRank(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); // others become a ruin + m_object->SetLock(false); + } + else + { + m_object->SetType(OBJECT_RUINmobilew1); // others become a ruin + m_object->SetLock(false); + } + + m_object->SetBurn(false); // ruin usable (c-e-d. recoverable) +} + + +// Start of an object freight falling. + +void CPyro::FallStart() +{ + Math::Vector pos; + + m_object->SetBurn(true); // usable + + pos = m_object->RetPosition(0); + m_fallFloor = m_terrain->RetFloorLevel(pos); + m_fallSpeed = 0.0f; + m_fallBulletTime = 0.0f; + m_bFallEnding = false; +} + +// Seeking an object explode by the falling ball of bees. + +CObject* CPyro::FallSearchBeeExplo() +{ + CObject* pObj; + Math::Vector iPos, oPos; + ObjectType oType; + float iRadius, oRadius, distance, shieldRadius; + int i, j; + + m_object->GetCrashSphere(0, iPos, iRadius); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + oType = pObj->RetType(); + if ( oType != OBJECT_HUMAN && + oType != OBJECT_MOBILEfa && + oType != OBJECT_MOBILEta && + oType != OBJECT_MOBILEwa && + oType != OBJECT_MOBILEia && + oType != OBJECT_MOBILEfc && + oType != OBJECT_MOBILEtc && + oType != OBJECT_MOBILEwc && + oType != OBJECT_MOBILEic && + oType != OBJECT_MOBILEfi && + oType != OBJECT_MOBILEti && + oType != OBJECT_MOBILEwi && + oType != OBJECT_MOBILEii && + oType != OBJECT_MOBILEfs && + oType != OBJECT_MOBILEts && + oType != OBJECT_MOBILEws && + oType != OBJECT_MOBILEis && + oType != OBJECT_MOBILErt && + oType != OBJECT_MOBILErc && + oType != OBJECT_MOBILErr && + oType != OBJECT_MOBILErs && + oType != OBJECT_MOBILEsa && + oType != OBJECT_MOBILEtg && + oType != OBJECT_MOBILEft && + oType != OBJECT_MOBILEtt && + oType != OBJECT_MOBILEwt && + oType != OBJECT_MOBILEit && + oType != OBJECT_MOBILEdr && + oType != OBJECT_BASE && + oType != OBJECT_DERRICK && + oType != OBJECT_STATION && + oType != OBJECT_FACTORY && + oType != OBJECT_REPAIR && + oType != OBJECT_DESTROYER&& + oType != OBJECT_CONVERT && + oType != OBJECT_TOWER && + oType != OBJECT_RESEARCH && + oType != OBJECT_RADAR && + oType != OBJECT_INFO && + oType != OBJECT_ENERGY && + oType != OBJECT_LABO && + oType != OBJECT_NUCLEAR && + oType != OBJECT_PARA && + oType != OBJECT_SAFE && + oType != OBJECT_HUSTON && + oType != OBJECT_METAL && + oType != OBJECT_POWER && + oType != OBJECT_ATOMIC ) continue; + + if ( pObj->RetTruck() != 0 ) continue; // object transported? + + oPos = pObj->RetPosition(0); + + shieldRadius = pObj->RetShieldRadius(); + if ( shieldRadius > 0.0f ) + { + distance = Math::Distance(oPos, iPos); + if ( distance <= shieldRadius ) return pObj; + } + + if ( oType == OBJECT_BASE ) + { + distance = Math::Distance(oPos, iPos); + if ( distance < 25.0f ) return pObj; + } + + // Test the center of the object, which is necessary for objects + // that have no sphere in the center (station). + distance = Math::Distance(oPos, iPos)-4.0f; + if ( distance < 5.0f ) return pObj; + + // Test with all spheres of the object. + j = 0; + while ( pObj->GetCrashSphere(j++, oPos, oRadius) ) + { + distance = Math::Distance(oPos, iPos); + if ( distance <= iRadius+oRadius ) + { + return pObj; + } + } + } + return 0; +} + +// Fall of an object's freight. + +void CPyro::FallProgress(float rTime) +{ + CObject* pObj; + Math::Vector pos; + bool bFloor = false; + + if ( m_object == 0 ) return; + + m_fallSpeed += rTime*50.0f; // v2 = v1 + a*dt + pos = m_object->RetPosition(0); + pos.y -= m_fallSpeed*rTime; // dd -= v2*dt + + if ( pos.y <= m_fallFloor ) // below the ground level? + { + pos.y = m_fallFloor; + bFloor = true; + } + m_object->SetPosition(0, pos); + + if ( m_object->RetType() == OBJECT_BULLET ) + { + m_fallBulletTime += rTime; + + if ( m_fallBulletTime > 0.2f || bFloor ) + { + m_fallBulletTime = 0.0f; + + pObj = FallSearchBeeExplo(); + if ( pObj == 0 ) + { + if ( bFloor ) // reaches the ground? + { + m_object->ExploObject(EXPLO_BOUM, 0.0f); // start explosion + } + } + else + { + if ( pObj->RetShieldRadius() > 0.0f ) // protected by shield? + { + m_particule->CreateParticule(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 + { + if ( pObj->ExploObject(EXPLO_BOUM, 1.0f) ) // start explosion + { + DeleteObject(true, true); // removes the ball + } + else + { + m_object->ExploObject(EXPLO_BOUM, 0.0f); // start explosion + } + } + } + + if ( bFloor || pObj != 0 ) + { + m_bFallEnding = true; + } + } + } +} + +// Indicates whether the fall is over. + +Error CPyro::FallIsEnded() +{ + Math::Vector pos; + + if ( m_bFallEnding || m_object == 0 ) return ERR_STOP; + + pos = m_object->RetPosition(0); + if ( pos.y > m_fallFloor ) return ERR_CONTINUE; + + m_sound->Play(SOUND_BOUM, pos); + m_object->SetBurn(false); // usable again + + return ERR_STOP; +} + |