summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorZaba999 <qrwfw5rp>2012-10-11 23:10:07 +0200
committerZaba999 <qrwfw5rp>2012-10-11 23:10:07 +0200
commit7575ffd49b76aaf4b054c0ca8cb8369fb12c11c9 (patch)
tree10915bce6a98c2b0848421dbb79b36ce52bb045b /src
parent8a932fed3e5700af283017deab3cb1da11cb0dce (diff)
parentdfe21c5a9c2ebf3df0f445014588bcce0387d699 (diff)
downloadcolobot-7575ffd49b76aaf4b054c0ca8cb8369fb12c11c9.tar.gz
colobot-7575ffd49b76aaf4b054c0ca8cb8369fb12c11c9.tar.bz2
colobot-7575ffd49b76aaf4b054c0ca8cb8369fb12c11c9.zip
Merge branch 'dev' of https://github.com/colobot/colobot into dev
Diffstat (limited to 'src')
-rw-r--r--src/CBot/CBotString.cpp2
-rw-r--r--src/CBot/CMakeLists.txt2
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/app/app.h2
-rw-r--r--src/common/restext.cpp6
-rw-r--r--src/common/test/CMakeLists.txt6
-rw-r--r--src/graphics/core/color.h8
-rw-r--r--src/graphics/core/device.h2
-rw-r--r--src/graphics/core/light.h4
-rw-r--r--src/graphics/engine/engine.cpp1
-rw-r--r--src/graphics/engine/engine.h3
-rw-r--r--src/graphics/engine/lightning.cpp375
-rw-r--r--src/graphics/engine/lightning.h58
-rw-r--r--src/graphics/engine/particle.cpp3866
-rw-r--r--src/graphics/engine/particle.h353
-rw-r--r--src/graphics/engine/pyro.cpp2323
-rw-r--r--src/graphics/engine/pyro.h135
-rw-r--r--src/graphics/opengl/gldevice.cpp2
-rw-r--r--src/object/brain.cpp4
-rw-r--r--src/object/object.cpp8
-rw-r--r--src/object/robotmain.cpp256
-rw-r--r--src/object/robotmain.h11
-rw-r--r--src/object/task/taskbuild.cpp3
-rw-r--r--src/object/task/taskshield.cpp2
-rw-r--r--src/script/script.cpp1
-rw-r--r--src/ui/edit.cpp4
-rw-r--r--src/ui/key.cpp169
-rw-r--r--src/ui/key.h45
-rw-r--r--src/ui/maindialog.cpp117
-rw-r--r--src/ui/mainshort.cpp2
-rw-r--r--src/ui/mainshort.h2
-rw-r--r--src/ui/studio.cpp4
32 files changed, 6997 insertions, 781 deletions
diff --git a/src/CBot/CBotString.cpp b/src/CBot/CBotString.cpp
index 6f48127..4795b63 100644
--- a/src/CBot/CBotString.cpp
+++ b/src/CBot/CBotString.cpp
@@ -100,7 +100,7 @@ const std::map<EID,const char *> CBotString::s_keywordString =
{ID_DEC, "--"},
{ID_LO, "<"},
{ID_HI, ">"},
- {ID_LS, "<<"},
+ {ID_LS, "<="},
{ID_HS, ">="},
{ID_EQ, "=="},
{ID_NE, "!="},
diff --git a/src/CBot/CMakeLists.txt b/src/CBot/CMakeLists.txt
index 9f5b987..271f2ce 100644
--- a/src/CBot/CMakeLists.txt
+++ b/src/CBot/CMakeLists.txt
@@ -17,3 +17,5 @@ if(${CBOT_STATIC})
else()
add_library(CBot SHARED ${SOURCES})
endif()
+
+INSTALL_TARGETS(/lib CBot)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 4dbd201..33fe532 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -193,3 +193,5 @@ link_directories(${CMAKE_CURRENT_SOURCE_DIR}/CBot)
add_executable(colobot ${SOURCES})
target_link_libraries(colobot ${LIBS})
+
+INSTALL_TARGETS(/games colobot)
diff --git a/src/app/app.h b/src/app/app.h
index e887a63..32f03f8 100644
--- a/src/app/app.h
+++ b/src/app/app.h
@@ -38,7 +38,7 @@
class CInstanceManager;
-class CEvent;
+class CEventQueue;
class CRobotMain;
class CSoundInterface;
diff --git a/src/common/restext.cpp b/src/common/restext.cpp
index 0f33f52..9a3d964 100644
--- a/src/common/restext.cpp
+++ b/src/common/restext.cpp
@@ -105,7 +105,7 @@ static void PutKeyName(char* dst, const char* src)
{
if ( SearchKey(src+s+5, key) )
{
- res = CRobotMain::GetInstancePointer()->GetInputBinding(key).key;
+ res = CRobotMain::GetInstancePointer()->GetInputBinding(key).primary;
if (res != KEY_INVALID)
{
if ( GetResource(RES_KEY, res, name) )
@@ -172,7 +172,9 @@ static const char* GetResourceBase(ResType type, int num)
case RES_KEY:
- if (num == VIRTUAL_KMOD_CTRL)
+ if (num == KEY_INVALID)
+ return "";
+ else if (num == VIRTUAL_KMOD_CTRL)
return "Ctrl";
else if (num == VIRTUAL_KMOD_SHIFT)
return "Shift";
diff --git a/src/common/test/CMakeLists.txt b/src/common/test/CMakeLists.txt
index 7936862..ccbb739 100644
--- a/src/common/test/CMakeLists.txt
+++ b/src/common/test/CMakeLists.txt
@@ -14,7 +14,7 @@ ${GTEST_DIR}/include
add_executable(image_test ../image.cpp image_test.cpp)
target_link_libraries(image_test ${SDL_LIBRARY} ${SDLIMAGE_LIBRARY} ${PNG_LIBRARIES})
-add_executable(profile_test ../profile.cpp ../logger.cpp profile_test.cpp)
-target_link_libraries(profile_test gtest ${Boost_LIBRARIES})
+#add_executable(profile_test ../profile.cpp ../logger.cpp profile_test.cpp)
+#target_link_libraries(profile_test gtest ${Boost_LIBRARIES})
-add_test(profile_test ./profile_test)
+#add_test(profile_test ./profile_test)
diff --git a/src/graphics/core/color.h b/src/graphics/core/color.h
index 0bec7e9..7cbd175 100644
--- a/src/graphics/core/color.h
+++ b/src/graphics/core/color.h
@@ -107,6 +107,14 @@ inline IntColor ColorToIntColor(Color color)
static_cast<unsigned char>(color.a * 255.0f));
}
+inline Color IntensityToColor(float intensity)
+{
+ if (intensity <= 0.0f) return Color(0.0f, 0.0f, 0.0f, 0.0f);
+ if (intensity >= 1.0f) return Color(1.0f, 1.0f, 1.0f, 1.0f);
+
+ return Color(intensity, intensity, intensity, intensity);
+}
+
/**
* \struct ColorHSV
* \brief HSV color
diff --git a/src/graphics/core/device.h b/src/graphics/core/device.h
index ba5af6e..b6dd138 100644
--- a/src/graphics/core/device.h
+++ b/src/graphics/core/device.h
@@ -72,7 +72,7 @@ struct DeviceConfig
size = Math::IntPoint(800, 600);
bpp = 32;
fullScreen = false;
- resizeable = true;
+ resizeable = false;
doubleBuf = true;
noFrame = false;
}
diff --git a/src/graphics/core/light.h b/src/graphics/core/light.h
index 35f37e6..28733c1 100644
--- a/src/graphics/core/light.h
+++ b/src/graphics/core/light.h
@@ -68,7 +68,7 @@ struct Light
float attenuation1;
//! Quadratic attenuation factor
float attenuation2;
- //! Angle of spotlight cone (0-90 degrees)
+ //! Angle of spotlight cone (0-PI/2 radians)
float spotAngle;
//! Intensity of spotlight (0 = uniform; 128 = most intense)
@@ -91,7 +91,7 @@ struct Light
direction = Math::Vector(0.0f, 0.0f, 1.0f);
attenuation0 = 1.0f;
attenuation1 = attenuation2 = 0.0f;
- spotAngle = 90.0f;
+ spotAngle = Math::PI/2.0f;
spotIntensity = 0.0f;
}
};
diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp
index f3eb1dc..3365b24 100644
--- a/src/graphics/engine/engine.cpp
+++ b/src/graphics/engine/engine.cpp
@@ -272,6 +272,7 @@ bool CEngine::Create()
m_planet = new CPlanet(m_iMan, this);
m_lightMan->SetDevice(m_device);
+ m_particle->SetDevice(m_device);
m_text->SetDevice(m_device);
if (! m_text->Create())
diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h
index 14a40db..27f0173 100644
--- a/src/graphics/engine/engine.h
+++ b/src/graphics/engine/engine.h
@@ -961,9 +961,6 @@ public:
bool GetFog();
//@}
- //! Indicates whether it is possible to give a color SetState
- bool GetStateColor();
-
//@{
//! Management of the global mode of secondary texturing
void SetSecondTexture(int texNum);
diff --git a/src/graphics/engine/lightning.cpp b/src/graphics/engine/lightning.cpp
index 1b9cbf1..337d578 100644
--- a/src/graphics/engine/lightning.cpp
+++ b/src/graphics/engine/lightning.cpp
@@ -19,6 +19,17 @@
#include "graphics/engine/lightning.h"
#include "common/logger.h"
+#include "common/iman.h"
+
+#include "graphics/core/device.h"
+#include "graphics/engine/camera.h"
+#include "graphics/engine/terrain.h"
+
+#include "object/object.h"
+
+#include "object/auto/autopara.h"
+
+#include "math/geometry.h"
// Graphics module namespace
@@ -27,68 +38,380 @@ namespace Gfx {
CLightning::CLightning(CInstanceManager* iMan, CEngine* engine)
{
- GetLogger()->Trace("CLightning::CLightning() stub!\n");
- // TODO!
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_BLITZ, this);
+
+ m_engine = engine;
+ m_terrain = nullptr;
+ m_camera = nullptr;
+ m_sound = nullptr;
+
+ Flush();
}
CLightning::~CLightning()
{
- GetLogger()->Trace("CLightning::~CLightning() stub!\n");
- // TODO!
}
void CLightning::Flush()
{
- GetLogger()->Trace("CLightning::Flush() stub!\n");
- // TODO!
+ m_lightningExists = false;
+ m_phase = LP_WAIT;
+ m_speed = 0.0f;
+ m_progress = 0.0f;
+
+ for (int i = 0; i < FLASH_SEGMENTS; i++)
+ {
+ m_shift[i] = Math::Point(0.0f, 0.0f);
+ m_width[i] = 1.0f;
+ }
}
bool CLightning::EventProcess(const Event &event)
{
- GetLogger()->Trace("CLightning::EventProcess() stub!\n");
- // TODO!
+ if (event.type == EVENT_FRAME)
+ return EventFrame(event);
+
return true;
}
-bool CLightning::Create(float sleep, float delay, float magnetic)
+bool CLightning::EventFrame(const Event &event)
{
- GetLogger()->Trace("CLightning::Create() stub!\n");
- // TODO!
+ if (m_engine->GetPause()) return true;
+ if (m_engine->GetMovieLock()) return true;
+
+ m_progress += event.rTime*m_speed;
+
+ if (m_phase == LP_WAIT)
+ {
+ if (m_progress >= 1.0f)
+ {
+
+ m_pos.x = (Math::Rand()-0.5f)*(3200.0f-200.0f);
+ m_pos.z = (Math::Rand()-0.5f)*(3200.0f-200.0f);
+ m_pos.y = 0.0f;
+
+ CObject* obj = SearchObject(m_pos);
+ if (obj == nullptr)
+ {
+ m_terrain->AdjustToFloor(m_pos, true);
+ }
+ else
+ {
+ m_pos = obj->GetPosition(0);
+ m_terrain->AdjustToFloor(m_pos, true);
+
+ ObjectType type = obj->GetType();
+ if (type == OBJECT_BASE)
+ {
+ m_pos.y += 120.0f; // top of the rocket
+ }
+ else if (type == OBJECT_PARA)
+ {
+ CAutoPara* automat = dynamic_cast<CAutoPara*>(obj->GetAuto());
+ if (automat != nullptr)
+ automat->StartLightning();
+
+ m_pos.y += 67.0f; // top of lightning rod
+ }
+ else
+ {
+ obj->ExploObject(EXPLO_BOUM, 1.0f);
+ }
+ }
+
+ Math::Vector eye = m_engine->GetEyePt();
+ float dist = Math::Distance(m_pos, eye);
+ float deep = m_engine->GetDeepView();
+
+ if (dist < deep)
+ {
+ Math::Vector pos = eye+((m_pos-eye)*0.2f); // like so close!
+ m_sound->Play(SOUND_BLITZ, pos);
+
+ m_camera->StartOver(CAM_OVER_EFFECT_LIGHTNING, m_pos, 1.0f);
+
+ m_phase = LP_FLASH;
+ m_progress = 0.0f;
+ m_speed = 1.0f;
+ }
+ }
+ }
+
+ if (m_phase == LP_FLASH)
+ {
+ if (m_progress < 1.0f)
+ {
+ float max = 5.0f;
+ for (int i = 0; i < FLASH_SEGMENTS; i++)
+ {
+ max += 0.4f;
+
+ m_shift[i].x += (Math::Rand()-0.5f)*max*2.0f;
+ if ( m_shift[i].x < -max ) m_shift[i].x = -max;
+ if ( m_shift[i].x > max ) m_shift[i].x = max;
+
+ m_shift[i].y += (Math::Rand()-0.5f)*max*2.0f;
+ if ( m_shift[i].y < -max ) m_shift[i].y = -max;
+ if ( m_shift[i].y > max ) m_shift[i].y = max;
+
+ m_width[i] += (Math::Rand()-0.5f)*2.0f;
+ if ( m_width[i] < 1.0f ) m_width[i] = 1.0f;
+ if ( m_width[i] > 6.0f ) m_width[i] = 6.0f;
+ }
+ m_shift[0].x = 0.0f;
+ m_shift[0].y = 0.0f;
+ m_width[0] = 0.0f;
+ }
+ else
+ {
+ m_phase = LP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f / (1.0f+Math::Rand()*m_delay);
+ }
+ }
+
return true;
}
+bool CLightning::Create(float sleep, float delay, float magnetic)
+{
+ m_lightningExists = true;
+ if (sleep < 1.0f) sleep = 1.0f;
+ m_sleep = sleep;
+ m_delay = delay;
+ m_magnetic = magnetic;
+
+ m_phase = LP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f / m_sleep;
+
+ if (m_terrain == nullptr)
+ m_terrain = static_cast<CTerrain*>(m_iMan->SearchInstance(CLASS_TERRAIN));
+
+ if (m_camera == nullptr)
+ m_camera = static_cast<CCamera*>(m_iMan->SearchInstance(CLASS_CAMERA));
+
+ if (m_sound == nullptr)
+ m_sound = static_cast<CSoundInterface*>(m_iMan->SearchInstance(CLASS_SOUND));
+
+ return false;
+}
+
bool CLightning::GetStatus(float &sleep, float &delay, float &magnetic, float &progress)
{
- GetLogger()->Trace("CLightning::GetStatus() stub!\n");
- // TODO!
+ if (! m_lightningExists) return false;
+
+ sleep = m_sleep;
+ delay = m_delay;
+ magnetic = m_magnetic;
+ progress = m_progress;
+
return true;
}
bool CLightning::SetStatus(float sleep, float delay, float magnetic, float progress)
{
- GetLogger()->Trace("CLightning::SetStatus() stub!\n");
- // TODO!
+ m_lightningExists = true;
+
+ m_sleep = sleep;
+ m_delay = delay;
+ m_magnetic = magnetic;
+ m_progress = progress;
+ m_phase = LP_WAIT;
+ m_speed = 1.0f/m_sleep;
+
return true;
}
void CLightning::Draw()
{
- GetLogger()->Trace("CLightning::Draw() stub!\n");
- // TODO!
-}
+ if (!m_lightningExists) return;
+ if (m_phase != LP_FLASH) return;
-bool CLightning::EventFrame(const Event &event)
-{
- GetLogger()->Trace("CLightning::EventFrame() stub!\n");
- // TODO!
- return true;
+ CDevice* device = m_engine->GetDevice();
+
+ Math::Matrix mat;
+ mat.LoadIdentity();
+ device->SetTransform(TRANSFORM_WORLD, mat);
+
+ m_engine->SetTexture("effect00.png");
+ m_engine->SetState(ENG_RSTATE_TTEXTURE_BLACK);
+
+ Math::Point texInf;
+ texInf.x = 64.5f/256.0f;
+ texInf.y = 33.0f/256.0f;
+ Math::Point texSup;
+ texSup.x = 95.5f/256.0f;
+ texSup.y = 34.0f/256.0f; // blank
+
+ Math::Vector p1 = m_pos;
+ Math::Vector eye = m_engine->GetEyePt();
+ float a = Math::RotateAngle(eye.x-p1.x, eye.z-p1.z);
+ Math::Vector n = Math::Normalize(p1-eye);
+
+ Math::Vector corner[4];
+ Vertex vertex[4];
+
+ for (int i = 0; i < FLASH_SEGMENTS-1; i++)
+ {
+ Math::Vector p2 = p1;
+ p2.y += 8.0f+0.2f*i;
+
+ Math::Point rot;
+
+ Math::Vector p = p1;
+ p.x += m_width[i];
+ rot = Math::RotatePoint(Math::Point(p1.x, p1.z), a+Math::PI/2.0f, Math::Point(p.x, p.z));
+ corner[0].x = rot.x+m_shift[i].x;
+ corner[0].y = p1.y;
+ corner[0].z = rot.y+m_shift[i].y;
+ rot = Math::RotatePoint(Math::Point(p1.x, p1.z), a-Math::PI/2.0f, Math::Point(p.x, p.z));
+ corner[1].x = rot.x+m_shift[i].x;
+ corner[1].y = p1.y;
+ corner[1].z = rot.y+m_shift[i].y;
+
+ p = p2;
+ p.x += m_width[i+1];
+ rot = Math::RotatePoint(Math::Point(p2.x, p2.z), a+Math::PI/2.0f, Math::Point(p.x, p.z));
+ corner[2].x = rot.x+m_shift[i+1].x;
+ corner[2].y = p2.y;
+ corner[2].z = rot.y+m_shift[i+1].y;
+ rot = Math::RotatePoint(Math::Point(p2.x, p2.z), a-Math::PI/2.0f, Math::Point(p.x, p.z));
+ corner[3].x = rot.x+m_shift[i+1].x;
+ corner[3].y = p2.y;
+ corner[3].z = rot.y+m_shift[i+1].y;
+
+ if (p2.y < p1.y)
+ {
+ vertex[0] = Vertex(corner[1], n, Math::Point(texSup.x, texSup.y));
+ vertex[1] = Vertex(corner[0], n, Math::Point(texInf.x, texSup.y));
+ vertex[2] = Vertex(corner[3], n, Math::Point(texSup.x, texInf.y));
+ vertex[3] = Vertex(corner[2], n, Math::Point(texInf.x, texInf.y));
+ }
+ else
+ {
+ vertex[0] = Vertex(corner[0], n, Math::Point(texSup.x, texSup.y));
+ vertex[1] = Vertex(corner[1], n, Math::Point(texInf.x, texSup.y));
+ vertex[2] = Vertex(corner[2], n, Math::Point(texSup.x, texInf.y));
+ vertex[3] = Vertex(corner[3], n, Math::Point(texInf.x, texInf.y));
+ }
+
+ device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, vertex, 4);
+ m_engine->AddStatisticTriangle(2);
+
+ p1 = p2;
+ }
}
CObject* CLightning::SearchObject(Math::Vector pos)
{
- GetLogger()->Trace("CLightning::SearchObject() stub!\n");
- // TODO!
- return nullptr;
+ // Lightning conductors
+ std::vector<CObject*> paraObj;
+ paraObj.reserve(100);
+ std::vector<Math::Vector> paraObjPos;
+ paraObjPos.reserve(100);
+
+ // Seeking the object closest to the point of impact of lightning.
+ CObject* bestObj = 0;
+ float min = 100000.0f;
+ for (int i = 0; i < 1000000; i++)
+ {
+ CObject* obj = static_cast<CObject*>( m_iMan->SearchInstance(CLASS_OBJECT, i) );
+ if (obj == nullptr) break;
+
+ if (!obj->GetActif()) continue; // inactive object?
+ if (obj->GetTruck() != nullptr) continue; // object transported?
+
+ ObjectType type = obj->GetType();
+ if ( type == OBJECT_BASE ||
+ type == OBJECT_PARA ) // building a lightning effect?
+ {
+ paraObj.push_back(obj);
+ paraObjPos.push_back(obj->GetPosition(0));
+ }
+
+ float detect = 0.0f;
+ if ( type == OBJECT_BASE ||
+ type == OBJECT_DERRICK ||
+ type == OBJECT_FACTORY ||
+ type == OBJECT_REPAIR ||
+ type == OBJECT_DESTROYER||
+ type == OBJECT_STATION ||
+ type == OBJECT_CONVERT ||
+ type == OBJECT_TOWER ||
+ type == OBJECT_RESEARCH ||
+ type == OBJECT_RADAR ||
+ type == OBJECT_INFO ||
+ type == OBJECT_ENERGY ||
+ type == OBJECT_LABO ||
+ type == OBJECT_NUCLEAR ||
+ type == OBJECT_PARA ||
+ type == OBJECT_SAFE ||
+ type == OBJECT_HUSTON )
+ {
+ detect = m_magnetic;
+ }
+ if ( type == OBJECT_METAL ||
+ type == OBJECT_POWER ||
+ type == OBJECT_ATOMIC )
+ {
+ detect = m_magnetic*0.3f;
+ }
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEis ||
+ type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ||
+ type == OBJECT_MOBILEsa ||
+ type == OBJECT_MOBILEft ||
+ type == OBJECT_MOBILEtt ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEit ||
+ type == OBJECT_MOBILEdr )
+ {
+ detect = m_magnetic*0.5f;
+ }
+ if (detect == 0.0f) continue;
+
+ Math::Vector oPos = obj->GetPosition(0);
+ float dist = Math::DistanceProjected(oPos, pos);
+ if (dist > detect) continue;
+ if (dist < min)
+ {
+ min = dist;
+ bestObj = obj;
+ }
+ }
+
+ if (bestObj == nullptr)
+ return nullptr; // nothing found
+
+ // Under the protection of a lightning conductor?
+ Math::Vector oPos = bestObj->GetPosition(0);
+ for (int i = paraObj.size()-1; i >= 0; i--)
+ {
+ float dist = Math::DistanceProjected(oPos, paraObjPos[i]);
+ if (dist <= LTNG_PROTECTION_RADIUS)
+ return paraObj[i];
+ }
+
+ return bestObj;
}
diff --git a/src/graphics/engine/lightning.h b/src/graphics/engine/lightning.h
index d873c64..b21f681 100644
--- a/src/graphics/engine/lightning.h
+++ b/src/graphics/engine/lightning.h
@@ -30,7 +30,7 @@
class CInstanceManager;
class CObject;
-class CSound;
+class CSoundInterface;
// Graphics module namespace
@@ -40,21 +40,15 @@ class CEngine;
class CTerrain;
class CCamera;
+//! Radius of lightning protection
+const float LTNG_PROTECTION_RADIUS = 200.0f;
-const float BLITZPARA = 200.0f; // radius of lightning protection
-const short BLITZMAX = 50;
-
-enum BlitzPhase
-{
- BPH_WAIT,
- BPH_BLITZ,
-};
/**
* \class CLightning
* \brief Lightning effect renderer
*
- * Functions are only stubs for now.
+ * TODO: documentation
*/
class CLightning
{
@@ -62,35 +56,55 @@ public:
CLightning(CInstanceManager* iMan, CEngine* engine);
~CLightning();
- void Flush();
- bool EventProcess(const Event &event);
+ //! Triggers lightning
bool Create(float sleep, float delay, float magnetic);
+
+ //! Removes lightning
+ void Flush();
+
+ //! Gives the status of lightning
bool GetStatus(float &sleep, float &delay, float &magnetic, float &progress);
+ //! Specifies the status of lightning
bool SetStatus(float sleep, float delay, float magnetic, float progress);
+
+ //! Management of an event
+ bool EventProcess(const Event &event);
+
+ //! Draws lightning
void Draw();
protected:
+ //! Updates lightning
bool EventFrame(const Event &event);
+ //! Seeks for the object closest to the lightning
CObject* SearchObject(Math::Vector pos);
protected:
- CInstanceManager* m_iMan;
- CEngine* m_engine;
- CTerrain* m_terrain;
- CCamera* m_camera;
- CSound* m_sound;
+ CInstanceManager* m_iMan;
+ CEngine* m_engine;
+ CTerrain* m_terrain;
+ CCamera* m_camera;
+ CSoundInterface* m_sound;
- bool m_bBlitzExist;
+ bool m_lightningExists;
float m_sleep;
float m_delay;
float m_magnetic;
- BlitzPhase m_phase;
- float m_time;
+
float m_speed;
float m_progress;
Math::Vector m_pos;
- Math::Point m_shift[BLITZMAX];
- float m_width[BLITZMAX];
+
+ enum LightningPhase
+ {
+ LP_WAIT,
+ LP_FLASH,
+ };
+ LightningPhase m_phase;
+
+ static const short FLASH_SEGMENTS = 50;
+ Math::Point m_shift[FLASH_SEGMENTS];
+ float m_width[FLASH_SEGMENTS];
};
diff --git a/src/graphics/engine/particle.cpp b/src/graphics/engine/particle.cpp
index 9d3d084..acc40df 100644
--- a/src/graphics/engine/particle.cpp
+++ b/src/graphics/engine/particle.cpp
@@ -20,289 +20,3897 @@
#include "common/logger.h"
+#include "graphics/core/device.h"
+#include "graphics/engine/engine.h"
+#include "graphics/engine/terrain.h"
+#include "graphics/engine/water.h"
+
+#include "math/geometry.h"
+
+#include "object/object.h"
+#include "object/robotmain.h"
+
+#include <cstring>
+
// Graphics module namespace
namespace Gfx {
-CParticle::CParticle(CInstanceManager* iMan, CEngine* engine)
+const float FOG_HSUP = 10.0f;
+const float FOG_HINF = 100.0f;
+
+
+
+
+//! Check if an object can be destroyed, but is not an enemy
+bool IsSoft(ObjectType type)
{
- GetLogger()->Trace("CParticle::CParticle() stub!\n");
- // TODO!
+ return ( type == OBJECT_HUMAN ||
+ type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEis ||
+ type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ||
+ type == OBJECT_MOBILEsa ||
+ type == OBJECT_MOBILEft ||
+ type == OBJECT_MOBILEtt ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEit ||
+ type == OBJECT_MOBILEdr || // robot?
+ type == OBJECT_METAL ||
+ type == OBJECT_POWER ||
+ type == OBJECT_ATOMIC || // cargo?
+ type == OBJECT_DERRICK ||
+ type == OBJECT_STATION ||
+ type == OBJECT_FACTORY ||
+ type == OBJECT_REPAIR ||
+ type == OBJECT_DESTROYER||
+ type == OBJECT_CONVERT ||
+ type == OBJECT_TOWER ||
+ type == OBJECT_RESEARCH ||
+ type == OBJECT_RADAR ||
+ type == OBJECT_INFO ||
+ type == OBJECT_ENERGY ||
+ type == OBJECT_LABO ||
+ type == OBJECT_NUCLEAR ||
+ type == OBJECT_PARA ); // building?
+}
+
+//! Check if an object is a destroyable enemy
+bool IsAlien(ObjectType type)
+{
+ return ( type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_BEE ||
+ type == OBJECT_WORM ||
+ type == OBJECT_MOTHER ||
+ type == OBJECT_NEST ||
+ type == OBJECT_BULLET ||
+ type == OBJECT_EGG ||
+ type == OBJECT_MOBILEtg ||
+ type == OBJECT_TEEN28 ||
+ type == OBJECT_TEEN31 );
+}
+
+//! Returns the damping factor for friendly fire
+float GetDecay(ObjectType type)
+{
+ if (IsSoft(type)) return 0.2f;
+ return 1.0f;
+}
+
+
+
+CParticle::CParticle(CInstanceManager *iMan, CEngine* engine)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_PARTICULE, this);
+
+ m_device = nullptr;
+ m_engine = engine;
+ m_main = nullptr;
+ m_terrain = nullptr;
+ m_water = nullptr;
+ m_sound = nullptr;
+ m_uniqueStamp = 0;
+ m_exploGunCounter = 0;
+ m_lastTimeGunDel = 0.0f;
+ m_absTime = 0.0f;
+
+ FlushParticle();
}
CParticle::~CParticle()
{
- GetLogger()->Trace("CParticle::~CParticle() stub!\n");
- // TODO!
+ m_iMan->DeleteInstance(CLASS_PARTICULE, this);
}
void CParticle::SetDevice(CDevice* device)
{
- GetLogger()->Trace("CParticle::SetDevice() stub!\n");
- // TODO!
+ m_device = device;
}
void CParticle::FlushParticle()
{
- GetLogger()->Trace("CParticle::FlushParticle() stub!\n");
- // TODO!
+ for (int i = 0; i < MAXPARTICULE*MAXPARTITYPE; i++)
+ m_particle[i].used = false;
+
+ for (int i = 0; i < MAXPARTITYPE; i++)
+ {
+ for (int j = 0; j < SH_MAX; j++)
+ {
+ m_totalInterface[i][j] = 0;
+ }
+ }
+
+ for (int i = 0; i < MAXTRACK; i++)
+ m_track[i].used = false;
+
+ m_wheelTraceTotal = 0;
+ m_wheelTraceIndex = 0;
+
+ for (int i = 0; i < SH_MAX; i++)
+ m_frameUpdate[i] = true;
+
+ m_fogTotal = 0;
+ m_exploGunCounter = 0;
}
void CParticle::FlushParticle(int sheet)
{
- GetLogger()->Trace("CParticle::FlushParticle() stub!\n");
- // TODO!
+ for (int i = 0; i < MAXPARTICULE*MAXPARTITYPE; i++)
+ {
+ if (!m_particle[i].used) continue;
+ if (m_particle[i].sheet != sheet) continue;
+
+ m_particle[i].used = false;
+ }
+
+ for (int i = 0; i < MAXPARTITYPE; i++)
+ m_totalInterface[i][sheet] = 0;
+
+ for (int i = 0; i < MAXTRACK; i++)
+ m_track[i].used = false;
+
+ if (sheet == SH_WORLD)
+ {
+ m_wheelTraceTotal = 0;
+ m_wheelTraceIndex = 0;
+ }
+}
+
+
+//! Returns file name of the effect effectNN.png, with NN = number
+void NameParticle(std::string &name, int num)
+{
+ if (num == 1) name = "effect00.png";
+ else if (num == 2) name = "effect01.png";
+ else if (num == 3) name = "effect02.png";
+ else if (num == 4) name = "text.png";
+ else name = "";
}
+/** Returns the channel of the particle created or -1 on error. */
int CParticle::CreateParticle(Math::Vector pos, Math::Vector speed, Math::Point dim,
- ParticleType type, float duration, float mass,
- float windSensitivity, int sheet)
+ ParticleType type,
+ float duration, float mass,
+ float windSensitivity, int sheet)
+{
+ if (m_main == nullptr)
+ m_main = static_cast<CRobotMain*>(m_iMan->SearchInstance(CLASS_MAIN));
+
+ int t = -1;
+ if ( type == PARTIEXPLOT ||
+ type == PARTIEXPLOO ||
+ type == PARTIMOTOR ||
+ type == PARTIBLITZ ||
+ type == PARTICRASH ||
+ type == PARTIVAPOR ||
+ type == PARTIGAS ||
+ type == PARTIBASE ||
+ type == PARTIFIRE ||
+ type == PARTIFIREZ ||
+ type == PARTIBLUE ||
+ type == PARTIROOT ||
+ type == PARTIRECOVER ||
+ type == PARTIEJECT ||
+ type == PARTISCRAPS ||
+ type == PARTIGUN2 ||
+ type == PARTIGUN3 ||
+ type == PARTIGUN4 ||
+ type == PARTIQUEUE ||
+ type == PARTIORGANIC1 ||
+ type == PARTIORGANIC2 ||
+ type == PARTIFLAME ||
+ type == PARTIBUBBLE ||
+ type == PARTIERROR ||
+ type == PARTIWARNING ||
+ type == PARTIINFO ||
+ type == PARTISPHERE1 ||
+ type == PARTISPHERE2 ||
+ type == PARTISPHERE4 ||
+ type == PARTISPHERE5 ||
+ type == PARTISPHERE6 ||
+ type == PARTIPLOUF0 ||
+ type == PARTITRACK1 ||
+ type == PARTITRACK2 ||
+ type == PARTITRACK3 ||
+ type == PARTITRACK4 ||
+ type == PARTITRACK5 ||
+ type == PARTITRACK6 ||
+ type == PARTITRACK7 ||
+ type == PARTITRACK8 ||
+ type == PARTITRACK9 ||
+ type == PARTITRACK10 ||
+ type == PARTITRACK11 ||
+ type == PARTITRACK12 ||
+ type == PARTILENS1 ||
+ type == PARTILENS2 ||
+ type == PARTILENS3 ||
+ type == PARTILENS4 ||
+ type == PARTIGFLAT ||
+ type == PARTIDROP ||
+ type == PARTIWATER ||
+ type == PARTILIMIT1 ||
+ type == PARTILIMIT2 ||
+ type == PARTILIMIT3 ||
+ type == PARTILIMIT4 ||
+ type == PARTIEXPLOG1 ||
+ type == PARTIEXPLOG2 )
+ {
+ t = 1; // effect00
+ }
+ if ( type == PARTIGLINT ||
+ type == PARTIGLINTb ||
+ type == PARTIGLINTr ||
+ type == PARTITOTO ||
+ type == PARTISELY ||
+ type == PARTISELR ||
+ type == PARTIQUARTZ ||
+ type == PARTIGUNDEL ||
+ type == PARTICONTROL ||
+ type == PARTISHOW ||
+ type == PARTICHOC ||
+ type == PARTIFOG4 ||
+ type == PARTIFOG5 ||
+ type == PARTIFOG6 ||
+ type == PARTIFOG7 )
+ {
+ t = 2; // effect01
+ }
+ if ( type == PARTIGUN1 ||
+ type == PARTIFLIC ||
+ type == PARTISPHERE0 ||
+ type == PARTISPHERE3 ||
+ type == PARTIFOG0 ||
+ type == PARTIFOG1 ||
+ type == PARTIFOG2 ||
+ type == PARTIFOG3 )
+ {
+ t = 3; // effect02
+ }
+ if ( type == PARTISMOKE1 ||
+ type == PARTISMOKE2 ||
+ type == PARTISMOKE3 ||
+ type == PARTIBLOOD ||
+ type == PARTIBLOODM ||
+ type == PARTIVIRUS1 ||
+ type == PARTIVIRUS2 ||
+ type == PARTIVIRUS3 ||
+ type == PARTIVIRUS4 ||
+ type == PARTIVIRUS5 ||
+ type == PARTIVIRUS6 ||
+ type == PARTIVIRUS7 ||
+ type == PARTIVIRUS8 ||
+ type == PARTIVIRUS9 ||
+ type == PARTIVIRUS10 )
+ {
+ t = 4; // text (D3DSTATETTw)
+ }
+ if (t >= MAXPARTITYPE) return -1;
+ if (t == -1) return -1;
+
+ for (int j = 0; j < MAXPARTICULE; j++)
+ {
+ int i = MAXPARTICULE*t+j;
+
+ if (! m_particle[i].used)
+ {
+ memset(&m_particle[i], 0, sizeof(Particle));
+ m_particle[i].used = true;
+ m_particle[i].ray = false;
+ m_particle[i].uniqueStamp = m_uniqueStamp++;
+ m_particle[i].sheet = sheet;
+ m_particle[i].mass = mass;
+ m_particle[i].duration = duration;
+ m_particle[i].pos = pos;
+ m_particle[i].goal = pos;
+ m_particle[i].speed = speed;
+ m_particle[i].windSensitivity = windSensitivity;
+ m_particle[i].dim = dim;
+ m_particle[i].zoom = 1.0f;
+ m_particle[i].angle = 0.0f;
+ m_particle[i].intensity = 1.0f;
+ m_particle[i].type = type;
+ m_particle[i].phase = PARPHSTART;
+ m_particle[i].texSup.x = 0.0f;
+ m_particle[i].texSup.y = 0.0f;
+ m_particle[i].texInf.x = 0.0f;
+ m_particle[i].texInf.y = 0.0f;
+ m_particle[i].time = 0.0f;
+ m_particle[i].phaseTime = 0.0f;
+ m_particle[i].testTime = 0.0f;
+ m_particle[i].objLink = 0;
+ m_particle[i].objFather = 0;
+ m_particle[i].trackRank = -1;
+
+ m_totalInterface[t][sheet] ++;
+
+ if ( type == PARTIEXPLOT ||
+ type == PARTIEXPLOO )
+ {
+ m_particle[i].angle = Math::Rand()*Math::PI*2.0f;
+ }
+
+ if ( type == PARTIGUN1 ||
+ type == PARTIGUN4 )
+ {
+ m_particle[i].testTime = 1.0f; // impact immediately
+ }
+
+ if ( type >= PARTIFOG0 &&
+ type <= PARTIFOG9 )
+ {
+ if (m_fogTotal < MAXPARTIFOG)
+ m_fog[m_fogTotal++] = i;
+ }
+
+ return i | ((m_particle[i].uniqueStamp&0xffff)<<16);
+ }
+ }
+
+ return -1;
+}
+
+/** Returns the channel of the particle created or -1 on error */
+int CParticle::CreateFrag(Math::Vector pos, Math::Vector speed,
+ EngineTriangle *triangle,
+ ParticleType type,
+ float duration, float mass,
+ float windSensitivity, int sheet)
{
- GetLogger()->Trace("CParticle::CreateParticle() stub!\n");
- // TODO!
- return 0;
+ int t = 0;
+ for (int j = 0; j < MAXPARTICULE; j++)
+ {
+ int i = MAXPARTICULE*t+j;
+
+ if (!m_particle[i].used)
+ {
+ memset(&m_particle[i], 0, sizeof(Particle));
+ m_particle[i].used = true;
+ m_particle[i].ray = false;
+ m_particle[i].uniqueStamp = m_uniqueStamp++;
+ m_particle[i].sheet = sheet;
+ m_particle[i].mass = mass;
+ m_particle[i].duration = duration;
+ m_particle[i].pos = pos;
+ m_particle[i].goal = pos;
+ m_particle[i].speed = speed;
+ m_particle[i].windSensitivity = windSensitivity;
+ m_particle[i].zoom = 1.0f;
+ m_particle[i].angle = 0.0f;
+ m_particle[i].intensity = 1.0f;
+ m_particle[i].type = type;
+ m_particle[i].phase = PARPHSTART;
+ m_particle[i].texSup.x = 0.0f;
+ m_particle[i].texSup.y = 0.0f;
+ m_particle[i].texInf.x = 0.0f;
+ m_particle[i].texInf.y = 0.0f;
+ m_particle[i].time = 0.0f;
+ m_particle[i].phaseTime = 0.0f;
+ m_particle[i].testTime = 0.0f;
+ m_particle[i].objLink = 0;
+ m_particle[i].objFather = 0;
+ m_particle[i].trackRank = -1;
+ m_triangle[i] = *triangle;
+
+ m_totalInterface[t][sheet] ++;
+
+ Math::Vector p1;
+ p1.x = m_triangle[i].triangle[0].coord.x;
+ p1.y = m_triangle[i].triangle[0].coord.y;
+ p1.z = m_triangle[i].triangle[0].coord.z;
+
+ Math::Vector p2;
+ p2.x = m_triangle[i].triangle[1].coord.x;
+ p2.y = m_triangle[i].triangle[1].coord.y;
+ p2.z = m_triangle[i].triangle[1].coord.z;
+
+ Math::Vector p3;
+ p3.x = m_triangle[i].triangle[2].coord.x;
+ p3.y = m_triangle[i].triangle[2].coord.y;
+ p3.z = m_triangle[i].triangle[2].coord.z;
+
+ float l1 = Math::Distance(p1, p2);
+ float l2 = Math::Distance(p2, p3);
+ float l3 = Math::Distance(p3, p1);
+ float dx = fabs(Math::Min(l1, l2, l3))*0.5f;
+ float dy = fabs(Math::Max(l1, l2, l3))*0.5f;
+ p1 = Math::Vector(-dx, dy, 0.0f);
+ p2 = Math::Vector( dx, dy, 0.0f);
+ p3 = Math::Vector(-dx, -dy, 0.0f);
+
+ m_triangle[i].triangle[0].coord.x = p1.x;
+ m_triangle[i].triangle[0].coord.y = p1.y;
+ m_triangle[i].triangle[0].coord.z = p1.z;
+
+ m_triangle[i].triangle[1].coord.x = p2.x;
+ m_triangle[i].triangle[1].coord.y = p2.y;
+ m_triangle[i].triangle[1].coord.z = p2.z;
+
+ m_triangle[i].triangle[2].coord.x = p3.x;
+ m_triangle[i].triangle[2].coord.y = p3.y;
+ m_triangle[i].triangle[2].coord.z = p3.z;
+
+ Math::Vector n(0.0f, 0.0f, -1.0f);
+
+ m_triangle[i].triangle[0].normal.x = n.x;
+ m_triangle[i].triangle[0].normal.y = n.y;
+ m_triangle[i].triangle[0].normal.z = n.z;
+
+ m_triangle[i].triangle[1].normal.x = n.x;
+ m_triangle[i].triangle[1].normal.y = n.y;
+ m_triangle[i].triangle[1].normal.z = n.z;
+
+ m_triangle[i].triangle[2].normal.x = n.x;
+ m_triangle[i].triangle[2].normal.y = n.y;
+ m_triangle[i].triangle[2].normal.z = n.z;
+
+ if (type == PARTIFRAG)
+ m_particle[i].angle = Math::Rand()*Math::PI*2.0f;
+
+ return i | ((m_particle[i].uniqueStamp&0xffff)<<16);
+ }
+ }
+
+ return -1;
}
-int CParticle::CreateFrag(Math::Vector pos, Math::Vector speed, EngineTriangle *triangle,
- ParticleType type, float duration, float mass,
- float windSensitivity, int sheet)
+
+/** Returns the channel of the particle created or -1 on error */
+int CParticle::CreatePart(Math::Vector pos, Math::Vector speed,
+ ParticleType type,
+ float duration, float mass, float weight,
+ float windSensitivity, int sheet)
+{
+ int t = 0;
+ for (int j = 0; j < MAXPARTICULE; j++)
+ {
+ int i = MAXPARTICULE*t+j;
+
+ if (!m_particle[i].used)
+ {
+ memset(&m_particle[i], 0, sizeof(Particle));
+ m_particle[i].used = true;
+ m_particle[i].ray = false;
+ m_particle[i].uniqueStamp = m_uniqueStamp++;
+ m_particle[i].sheet = sheet;
+ m_particle[i].mass = mass;
+ m_particle[i].weight = weight;
+ m_particle[i].duration = duration;
+ m_particle[i].pos = pos;
+ m_particle[i].goal = pos;
+ m_particle[i].speed = speed;
+ m_particle[i].windSensitivity = windSensitivity;
+ m_particle[i].zoom = 1.0f;
+ m_particle[i].angle = 0.0f;
+ m_particle[i].intensity = 1.0f;
+ m_particle[i].type = type;
+ m_particle[i].phase = PARPHSTART;
+ m_particle[i].texSup.x = 0.0f;
+ m_particle[i].texSup.y = 0.0f;
+ m_particle[i].texInf.x = 0.0f;
+ m_particle[i].texInf.y = 0.0f;
+ m_particle[i].time = 0.0f;
+ m_particle[i].phaseTime = 0.0f;
+ m_particle[i].testTime = 0.0f;
+ m_particle[i].trackRank = -1;
+
+ m_totalInterface[t][sheet] ++;
+
+ return i | ((m_particle[i].uniqueStamp&0xffff)<<16);
+ }
+ }
+
+ return -1;
+}
+
+/** Returns the channel of the particle created or -1 on error */
+int CParticle::CreateRay(Math::Vector pos, Math::Vector goal,
+ ParticleType type, Math::Point dim,
+ float duration, int sheet)
{
- GetLogger()->Trace("CParticle::CreateFrag() stub!\n");
- // TODO!
- return 0;
+ int t = -1;
+ if ( type == PARTIRAY1 ||
+ type == PARTIRAY2 ||
+ type == PARTIRAY3 ||
+ type == PARTIRAY4 )
+ {
+ t = 3; // effect02
+ }
+ if (t >= MAXPARTITYPE) return -1;
+ if (t == -1) return -1;
+
+ for (int j = 0; j < MAXPARTICULE; j++)
+ {
+ int i = MAXPARTICULE*t+j;
+
+ if (!m_particle[i].used)
+ {
+ memset(&m_particle[i], 0, sizeof(Particle));
+ m_particle[i].used = true;
+ m_particle[i].ray = true;
+ m_particle[i].uniqueStamp = m_uniqueStamp++;
+ m_particle[i].sheet = sheet;
+ m_particle[i].mass = 0.0f;
+ m_particle[i].duration = duration;
+ m_particle[i].pos = pos;
+ m_particle[i].goal = goal;
+ m_particle[i].speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_particle[i].windSensitivity = 0.0f;
+ m_particle[i].dim = dim;
+ m_particle[i].zoom = 1.0f;
+ m_particle[i].angle = 0.0f;
+ m_particle[i].intensity = 1.0f;
+ m_particle[i].type = type;
+ m_particle[i].phase = PARPHSTART;
+ m_particle[i].texSup.x = 0.0f;
+ m_particle[i].texSup.y = 0.0f;
+ m_particle[i].texInf.x = 0.0f;
+ m_particle[i].texInf.y = 0.0f;
+ m_particle[i].time = 0.0f;
+ m_particle[i].phaseTime = 0.0f;
+ m_particle[i].testTime = 0.0f;
+ m_particle[i].objLink = 0;
+ m_particle[i].objFather = 0;
+ m_particle[i].trackRank = -1;
+
+ m_totalInterface[t][sheet] ++;
+
+ return i | ((m_particle[i].uniqueStamp&0xffff)<<16);
+ }
+ }
+
+ return -1;
}
-int CParticle::CreatePart(Math::Vector pos, Math::Vector speed, ParticleType type,
- float duration, float mass, float weight,
- float windSensitivity, int sheet)
+/** "length" is the length of the tail of drag (in seconds)! */
+int CParticle::CreateTrack(Math::Vector pos, Math::Vector speed, Math::Point dim,
+ ParticleType type, float duration, float mass,
+ float length, float width)
{
- GetLogger()->Trace("CParticle::CreatePart() stub!\n");
- // TODO!
- return 0;
+ // Creates the normal particle.
+ int channel = CreateParticle(pos, speed, dim, type, duration, mass, 0.0f, 0);
+ if (channel == -1) return -1;
+
+ // Seeks a streak free.
+ for (int i = 0; i < MAXTRACK; i++)
+ {
+ if (!m_track[i].used) // free?
+ {
+ int rank = channel;
+ if (!CheckChannel(rank)) return -1;
+ m_particle[rank].trackRank = i;
+
+ m_track[i].used = true;
+ m_track[i].step = (length/duration) / MAXTRACKLEN;
+ m_track[i].last = 0.0f;
+ m_track[i].intensity = 1.0f;
+ m_track[i].width = width;
+ m_track[i].posUsed = 1;
+ m_track[i].head = 0;
+ m_track[i].pos[0] = pos;
+ break;
+ }
+ }
+
+ return channel;
}
-int CParticle::CreateRay(Math::Vector pos, Math::Vector goal, ParticleType type, Math::Point dim,
- float duration, int sheet)
+void CParticle::CreateWheelTrace(const Math::Vector &p1, const Math::Vector &p2,
+ const Math::Vector &p3, const Math::Vector &p4,
+ ParticleType type)
{
- GetLogger()->Trace("CParticle::CreateRay() stub!\n");
- // TODO!
- return 0;
+ int max = MAXWHEELTRACE;
+ int i = m_wheelTraceIndex++;
+ if (m_wheelTraceIndex > max) m_wheelTraceIndex = 0;
+
+ m_wheelTrace[i].type = type;
+ m_wheelTrace[i].pos[0] = p1; // ul
+ m_wheelTrace[i].pos[1] = p2; // dl
+ m_wheelTrace[i].pos[2] = p3; // ur
+ m_wheelTrace[i].pos[3] = p4; // dr
+ m_wheelTrace[i].startTime = m_absTime;
+
+ if (m_terrain == nullptr)
+ m_terrain = static_cast<CTerrain*>(m_iMan->SearchInstance(CLASS_TERRAIN));
+
+ m_terrain->AdjustToFloor(m_wheelTrace[i].pos[0]);
+ m_wheelTrace[i].pos[0].y += 0.2f; // just above the ground
+
+ m_terrain->AdjustToFloor(m_wheelTrace[i].pos[1]);
+ m_wheelTrace[i].pos[1].y += 0.2f; // just above the ground
+
+ m_terrain->AdjustToFloor(m_wheelTrace[i].pos[2]);
+ m_wheelTrace[i].pos[2].y += 0.2f; // just above the ground
+
+ m_terrain->AdjustToFloor(m_wheelTrace[i].pos[3]);
+ m_wheelTrace[i].pos[3].y += 0.2f; // just above the ground
+
+ if (m_wheelTraceTotal < max)
+ m_wheelTraceTotal++;
+ else
+ m_wheelTraceTotal = max;
}
-int CParticle::CreateTrack(Math::Vector pos, Math::Vector speed, Math::Point dim, ParticleType type,
- float duration, float mass, float length, float width)
+
+
+/** Adapts the channel so it can be used as an offset in m_particle */
+bool CParticle::CheckChannel(int &channel)
{
- GetLogger()->Trace("CParticle::CreateTrack() stub!\n");
- // TODO!
- return 0;
+ int uniqueStamp = (channel>>16)&0xffff;
+ channel &= 0xffff;
+
+ if (channel < 0) return false;
+ if (channel >= MAXPARTICULE*MAXPARTITYPE) return false;
+
+ if (!m_particle[channel].used)
+ {
+ GetLogger()->Error("CheckChannel used=false !\n");
+ return false;
+ }
+
+ if (m_particle[channel].uniqueStamp != uniqueStamp)
+ {
+ GetLogger()->Error("CheckChannel uniqueStamp !\n");
+ return false;
+ }
+
+ return true;
}
-void CParticle::CreateWheelTrace(const Math::Vector &p1, const Math::Vector &p2, const Math::Vector &p3,
- const Math::Vector &p4, ParticleType type)
+void CParticle::DeleteRank(int rank)
{
- GetLogger()->Trace("CParticle::CreateWheelTrace() stub!\n");
- // TODO!
+ if (m_totalInterface[rank/MAXPARTICULE][m_particle[rank].sheet] > 0)
+ m_totalInterface[rank/MAXPARTICULE][m_particle[rank].sheet]--;
+
+ int i = m_particle[rank].trackRank;
+ if (i != -1) // drag associated?
+ m_track[i].used = false; // frees the drag
+
+ m_particle[rank].used = false;
}
void CParticle::DeleteParticle(ParticleType type)
{
- GetLogger()->Trace("CParticle::DeleteParticle() stub!\n");
- // TODO!
+ for (int i = 0; i < MAXPARTICULE*MAXPARTITYPE; i++)
+ {
+ if (!m_particle[i].used) continue;
+ if (m_particle[i].type != type) continue;
+
+ DeleteRank(i);
+ }
}
void CParticle::DeleteParticle(int channel)
{
- GetLogger()->Trace("CParticle::DeleteParticle() stub!\n");
- // TODO!
+ if (!CheckChannel(channel)) return;
+
+ if (m_totalInterface[channel/MAXPARTICULE][m_particle[channel].sheet] > 0 )
+ m_totalInterface[channel/MAXPARTICULE][m_particle[channel].sheet]--;
+
+ int i = m_particle[channel].trackRank;
+ if (i != -1) // drag associated?
+ m_track[i].used = false; // frees the drag
+
+ m_particle[channel].used = false;
}
void CParticle::SetObjectLink(int channel, CObject *object)
{
- GetLogger()->Trace("CParticle::SetObjectLink() stub!\n");
- // TODO!
+ if (!CheckChannel(channel)) return;
+ m_particle[channel].objLink = object;
}
void CParticle::SetObjectFather(int channel, CObject *object)
{
- GetLogger()->Trace("CParticle::SetObjectFather() stub!\n");
- // TODO!
+ if (!CheckChannel(channel)) return;
+ m_particle[channel].objFather = object;
}
void CParticle::SetPosition(int channel, Math::Vector pos)
{
- GetLogger()->Trace("CParticle::SetPosition() stub!\n");
- // TODO!
+ if (!CheckChannel(channel)) return;
+ m_particle[channel].pos = pos;
}
void CParticle::SetDimension(int channel, Math::Point dim)
{
- GetLogger()->Trace("CParticle::SetDimension() stub!\n");
- // TODO!
+ if (!CheckChannel(channel)) return;
+ m_particle[channel].dim = dim;
}
void CParticle::SetZoom(int channel, float zoom)
{
- GetLogger()->Trace("CParticle::SetZoom() stub!\n");
- // TODO!
+ if (!CheckChannel(channel)) return;
+ m_particle[channel].zoom = zoom;
}
void CParticle::SetAngle(int channel, float angle)
{
- GetLogger()->Trace("CParticle::SetAngle() stub!\n");
- // TODO!
+ if (!CheckChannel(channel)) return;
+ m_particle[channel].angle = angle;
}
void CParticle::SetIntensity(int channel, float intensity)
{
- GetLogger()->Trace("CParticle::SetIntensity() stub!\n");
- // TODO!
+ if (!CheckChannel(channel)) return;
+ m_particle[channel].intensity = intensity;
}
-void CParticle::SetParam(int channel, Math::Vector pos, Math::Point dim, float zoom, float angle, float intensity)
+void CParticle::SetParam(int channel, Math::Vector pos, Math::Point dim, float zoom,
+ float angle, float intensity)
{
- GetLogger()->Trace("CParticle::SetParam() stub!\n");
- // TODO!
+ if (!CheckChannel(channel)) return;
+ m_particle[channel].pos = pos;
+ m_particle[channel].dim = dim;
+ m_particle[channel].zoom = zoom;
+ m_particle[channel].angle = angle;
+ m_particle[channel].intensity = intensity;
}
void CParticle::SetPhase(int channel, ParticlePhase phase, float duration)
{
- GetLogger()->Trace("CParticle::SetPhase() stub!\n");
- // TODO!
+ if (!CheckChannel(channel)) return;
+ m_particle[channel].phase = phase;
+ m_particle[channel].duration = duration;
+ m_particle[channel].phaseTime = m_particle[channel].time;
}
bool CParticle::GetPosition(int channel, Math::Vector &pos)
{
- GetLogger()->Trace("CParticle::GetPosition() stub!\n");
- // TODO!
+ if (!CheckChannel(channel)) return false;
+ pos = m_particle[channel].pos;
return true;
}
-Color CParticle::GetFogColor(Math::Vector pos)
-{
- GetLogger()->Trace("CParticle::GetFogColor() stub!\n");
- // TODO!
- return Color();
-}
-
void CParticle::SetFrameUpdate(int sheet, bool update)
{
- GetLogger()->Trace("CParticle::SetFrameUpdate() stub!\n");
- // TODO!
+ m_frameUpdate[sheet] = update;
}
void CParticle::FrameParticle(float rTime)
{
- GetLogger()->Trace("CParticle::FrameParticle() stub!\n");
- // TODO!
-}
+ if (m_main == nullptr)
+ m_main = static_cast<CRobotMain*>(m_iMan->SearchInstance(CLASS_MAIN));
-void CParticle::DrawParticle(int sheet)
-{
- GetLogger()->Trace("CParticle::DrawParticle() stub!\n");
- // TODO!
-}
+ bool pause = (m_engine->GetPause() && !m_main->GetInfoLock());
-bool CParticle::WriteWheelTrace(const char *filename, int width, int height, Math::Vector dl, Math::Vector ur)
-{
- GetLogger()->Trace("CParticle::WriteWheelTrace() stub!\n");
- // TODO!
- return true;
+ if (m_terrain == nullptr)
+ m_terrain = static_cast<CTerrain*>(m_iMan->SearchInstance(CLASS_TERRAIN));
+
+ if (m_water == nullptr)
+ m_water = static_cast<CWater*>(m_iMan->SearchInstance(CLASS_WATER));
+
+ if (!pause)
+ {
+ m_lastTimeGunDel += rTime;
+ m_absTime += rTime;
+ }
+
+ Math::Vector wind = m_terrain->GetWind();
+ Math::Vector eye = m_engine->GetEyePt();
+
+ Math::Point ts, ti;
+ Math::Vector pos;
+
+ for (int i = 0; i < MAXPARTICULE*MAXPARTITYPE; i++)
+ {
+ if (!m_particle[i].used) continue;
+ if (!m_frameUpdate[m_particle[i].sheet]) continue;
+
+ if (m_particle[i].type != PARTISHOW)
+ {
+ if (pause && m_particle[i].sheet != SH_INTERFACE) continue;
+ }
+
+ if (m_particle[i].type != PARTIQUARTZ)
+ m_particle[i].pos += m_particle[i].speed*rTime;
+
+ if (m_particle[i].sheet == SH_WORLD)
+ {
+ float h = rTime*m_particle[i].windSensitivity*Math::Rand()*2.0f;
+ m_particle[i].pos += wind*h;
+ }
+
+ float progress = (m_particle[i].time-m_particle[i].phaseTime)/m_particle[i].duration;
+
+ // Manages the particles with mass that bounce.
+ if ( m_particle[i].mass != 0.0f &&
+ m_particle[i].type != PARTIQUARTZ )
+ {
+ m_particle[i].speed.y -= m_particle[i].mass*rTime;
+
+ float h;
+ if (m_particle[i].sheet == SH_INTERFACE)
+ h = 0.0f;
+ else
+ h = m_terrain->GetFloorLevel(m_particle[i].pos, true);
+
+ h += m_particle[i].dim.y*0.75f;
+ if (m_particle[i].pos.y < h) // impact with the ground?
+ {
+ if ( m_particle[i].type == PARTIPART &&
+ m_particle[i].weight > 3.0f && // heavy enough?
+ m_particle[i].bounce < 3 )
+ {
+ float amplitude = m_particle[i].weight*0.1f;
+ amplitude *= 1.0f-0.3f*m_particle[i].bounce;
+ if (amplitude > 1.0f) amplitude = 1.0f;
+ if (amplitude > 0.0f)
+ {
+ Play(SOUND_BOUM, m_particle[i].pos, amplitude);
+ }
+ }
+
+ if (m_particle[i].bounce < 3)
+ {
+ m_particle[i].pos.y = h;
+ m_particle[i].speed.y *= -0.4f;
+ m_particle[i].speed.x *= 0.4f;
+ m_particle[i].speed.z *= 0.4f;
+ m_particle[i].bounce ++; // more impact
+ }
+ else // disappears after 3 bounces?
+ {
+ if ( m_particle[i].pos.y < h-10.0f ||
+ m_particle[i].time >= 20.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+ }
+ }
+ }
+
+ // Manages drag associated.
+ int r = m_particle[i].trackRank;
+ if (r != -1) // drag exists?
+ {
+ if (TrackMove(r, m_particle[i].pos, progress))
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_track[r].drawParticle = (progress < 1.0f);
+ }
+
+ if (m_particle[i].type == PARTITRACK1) // explosion technique?
+ {
+ m_particle[i].zoom = 1.0f-(m_particle[i].time-m_particle[i].duration);
+
+ ts.x = 0.375f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTITRACK2) // spray blue?
+ {
+ m_particle[i].zoom = 1.0f-(m_particle[i].time-m_particle[i].duration);
+
+ ts.x = 0.500f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTITRACK3) // spider?
+ {
+ m_particle[i].zoom = 1.0f-(m_particle[i].time-m_particle[i].duration);
+
+ ts.x = 0.500f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTITRACK4) // insect explosion?
+ {
+ m_particle[i].zoom = 1.0f-(m_particle[i].time-m_particle[i].duration);
+
+ ts.x = 0.625f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTITRACK5) // derrick?
+ {
+ m_particle[i].zoom = 1.0f-(m_particle[i].time-m_particle[i].duration);
+
+ ts.x = 0.750f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTITRACK6) // reset in/out?
+ {
+ ts.x = 0.0f;
+ ts.y = 0.0f;
+ ti.x = 0.0f;
+ ti.y = 0.0f;
+ }
+
+ if ( m_particle[i].type == PARTITRACK7 || // win-1 ?
+ m_particle[i].type == PARTITRACK8 || // win-2 ?
+ m_particle[i].type == PARTITRACK9 || // win-3 ?
+ m_particle[i].type == PARTITRACK10 ) // win-4 ?
+ {
+ m_particle[i].zoom = 1.0f-(m_particle[i].time-m_particle[i].duration);
+
+ ts.x = 0.25f*(m_particle[i].type-PARTITRACK7);
+ ts.y = 0.25f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if (m_particle[i].type == PARTITRACK11) // phazer shot?
+ {
+ CObject* object = SearchObjectGun(m_particle[i].goal, m_particle[i].pos, m_particle[i].type, m_particle[i].objFather);
+ m_particle[i].goal = m_particle[i].pos;
+ if (object != nullptr)
+ {
+ if (object->GetType() == OBJECT_MOTHER)
+ object->ExploObject(EXPLO_BOUM, 0.1f);
+ else
+ object->ExploObject(EXPLO_BOUM, 0.0f, GetDecay(object->GetType()));
+ }
+
+ m_particle[i].zoom = 1.0f-(m_particle[i].time-m_particle[i].duration);
+
+ ts.x = 0.375f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTITRACK12) // drag reactor?
+ {
+ m_particle[i].zoom = 1.0f;
+
+ ts.x = 0.375f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTIMOTOR)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].zoom = 1.0f-progress;
+ m_particle[i].intensity = 1.0f-progress;
+
+ ts.x = 0.000f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTIBLITZ)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].zoom = 1.0f-progress;
+ m_particle[i].angle = Math::Rand()*Math::PI*2.0f;
+
+ ts.x = 0.125f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTICRASH)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if (progress < 0.25f)
+ m_particle[i].zoom = progress/0.25f;
+ else
+ m_particle[i].intensity = 1.0f-(progress-0.25f)/0.75f;
+
+ ts.x = 0.000f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTIVAPOR)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].intensity = 1.0f-progress;
+ m_particle[i].zoom = 1.0f+progress*3.0f;
+
+ ts.x = 0.000f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTIGAS)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].zoom = 1.0f-progress;
+
+ ts.x = 0.375f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTIBASE)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].zoom = 1.0f+progress*7.0f;
+ m_particle[i].intensity = powf(1.0f-progress, 3.0f);
+
+ ts.x = 0.375f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particle[i].type == PARTIFIRE ||
+ m_particle[i].type == PARTIFIREZ )
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if (m_particle[i].type == PARTIFIRE)
+ m_particle[i].zoom = 1.0f-progress;
+ else
+ m_particle[i].zoom = progress;
+
+ ts.x = 0.500f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTIGUN1) // fireball shot?
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if (m_particle[i].testTime >= 0.1f)
+ {
+ m_particle[i].testTime = 0.0f;
+
+ if (m_terrain->GetHeightToFloor(m_particle[i].pos, true) < -2.0f)
+ {
+ m_exploGunCounter++;
+
+ if (m_exploGunCounter % 2 == 0)
+ {
+ pos = m_particle[i].goal;
+ m_terrain->AdjustToFloor(pos, true);
+ Math::Vector speed;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 0.0f;
+ Math::Point dim;
+ dim.x = Math::Rand()*6.0f+6.0f;
+ dim.y = dim.x;
+ float duration = Math::Rand()*1.0f+1.0f;
+ float mass = 0.0f;
+ CreateParticle(pos, speed, dim, PARTIEXPLOG1, duration, mass, 1.0f);
+
+ pos.y += 1.0f;
+ int total = static_cast<int>(2.0f*m_engine->GetParticleDensity());
+ for (int j = 0; j < total; j++)
+ {
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ speed.y = Math::Rand()*20.0f;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ duration = Math::Rand()*1.0f+1.0f;
+ mass = Math::Rand()*10.0f+15.0f;
+ CreateParticle(pos, speed, dim, PARTIEXPLOG1, duration, mass, 1.0f);
+ }
+ }
+
+ if (m_exploGunCounter % 4 == 0)
+ Play(SOUND_EXPLOg1, pos, 0.5f);
+
+ DeleteRank(i);
+ continue;
+ }
+
+ CObject* object = SearchObjectGun(m_particle[i].goal, m_particle[i].pos, m_particle[i].type, m_particle[i].objFather);
+ m_particle[i].goal = m_particle[i].pos;
+ if (object != nullptr)
+ {
+ object->ExploObject(EXPLO_BURN, 0.0f, GetDecay(object->GetType()));
+
+ m_exploGunCounter++;
+
+ if (m_exploGunCounter % 2 == 0)
+ {
+ pos = m_particle[i].pos;
+ Math::Vector speed;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 0.0f;
+ Math::Point dim;
+ dim.x = Math::Rand()*6.0f+6.0f;
+ dim.y = dim.x;
+ float duration = Math::Rand()*1.0f+1.0f;
+ float mass = 0.0f;
+ CreateParticle(pos, speed, dim, PARTIEXPLOG1, duration, mass, 1.0f);
+
+ pos.y += 1.0f;
+ int total = static_cast<int>(2.0f*m_engine->GetParticleDensity());
+ for (int j = 0; j < total; j++)
+ {
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ speed.y = Math::Rand()*20.0f;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ duration = Math::Rand()*1.0f+1.0f;
+ mass = Math::Rand()*10.0f+15.0f;
+ CreateParticle(pos, speed, dim, PARTIEXPLOG1, duration, mass, 1.0f);
+ }
+ }
+
+ if (m_exploGunCounter % 4 == 0)
+ Play(SOUND_EXPLOg1, pos, 0.5f);
+
+ DeleteRank(i);
+ continue;
+ }
+ }
+
+ m_particle[i].angle -= rTime*Math::PI*8.0f;
+ m_particle[i].zoom = 1.0f-progress;
+
+ ts.x = 0.00f;
+ ts.y = 0.50f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if (m_particle[i].type == PARTIGUN2) // ant shot?
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if (m_particle[i].testTime >= 0.2f)
+ {
+ m_particle[i].testTime = 0.0f;
+ CObject* object = SearchObjectGun(m_particle[i].goal, m_particle[i].pos, m_particle[i].type, m_particle[i].objFather);
+ m_particle[i].goal = m_particle[i].pos;
+ if (object != nullptr)
+ {
+ if (object->GetShieldRadius() > 0.0f) // protected by shield?
+ {
+ CreateParticle(m_particle[i].pos, Math::Vector(0.0f, 0.0f, 0.0f), Math::Point(6.0f, 6.0f), PARTIGUNDEL, 2.0f);
+ if (m_lastTimeGunDel > 0.2f)
+ {
+ m_lastTimeGunDel = 0.0f;
+ Play(SOUND_GUNDEL, m_particle[i].pos, 1.0f);
+ }
+ DeleteRank(i);
+ continue;
+ }
+ else
+ {
+ if (object->GetType() != OBJECT_HUMAN)
+ Play(SOUND_TOUCH, m_particle[i].pos, 1.0f);
+
+ object->ExploObject(EXPLO_BOUM, 0.0f); // starts explosion
+ }
+ }
+ }
+
+ m_particle[i].angle = Math::Rand()*Math::PI*2.0f;
+ m_particle[i].zoom = 1.0f-progress;
+
+ ts.x = 0.125f;
+ ts.y = 0.875f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTIGUN3) // spider suicides?
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if (m_particle[i].testTime >= 0.2f)
+ {
+ m_particle[i].testTime = 0.0f;
+ CObject* object = SearchObjectGun(m_particle[i].goal, m_particle[i].pos, m_particle[i].type, m_particle[i].objFather);
+ m_particle[i].goal = m_particle[i].pos;
+ if (object != nullptr)
+ {
+ if (object->GetShieldRadius() > 0.0f)
+ {
+ CreateParticle(m_particle[i].pos, Math::Vector(0.0f, 0.0f, 0.0f), Math::Point(6.0f, 6.0f), PARTIGUNDEL, 2.0f);
+ if (m_lastTimeGunDel > 0.2f)
+ {
+ m_lastTimeGunDel = 0.0f;
+ Play(SOUND_GUNDEL, m_particle[i].pos, 1.0f);
+ }
+ DeleteRank(i);
+ continue;
+ }
+ else
+ {
+ object->ExploObject(EXPLO_BURN, 1.0f); // starts explosion
+ }
+ }
+ }
+
+ ts.x = 0.500f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTIGUN4) // orgaball shot?
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if (m_particle[i].testTime >= 0.1f)
+ {
+ m_particle[i].testTime = 0.0f;
+
+ if (m_terrain->GetHeightToFloor(m_particle[i].pos, true) < -2.0f)
+ {
+ m_exploGunCounter ++;
+
+ if (m_exploGunCounter % 2 == 0)
+ {
+ pos = m_particle[i].goal;
+ m_terrain->AdjustToFloor(pos, true);
+ Math::Vector speed;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 0.0f;
+ Math::Point dim;
+ dim.x = Math::Rand()*4.0f+2.0f;
+ dim.y = dim.x;
+ float duration = Math::Rand()*0.7f+0.7f;
+ float mass = 0.0f;
+ CreateParticle(pos, speed, dim, PARTIEXPLOG2, duration, mass, 1.0f);
+ }
+
+ if (m_exploGunCounter % 4 == 0)
+ {
+ Play(SOUND_EXPLOg2, pos, 0.5f);
+ }
+
+ DeleteRank(i);
+ continue;
+ }
+
+ CObject* object = SearchObjectGun(m_particle[i].goal, m_particle[i].pos, m_particle[i].type, m_particle[i].objFather);
+ m_particle[i].goal = m_particle[i].pos;
+ if (object != nullptr)
+ {
+ object->ExploObject(EXPLO_BOUM, 0.0f, GetDecay(object->GetType()));
+
+ m_exploGunCounter ++;
+
+ if (m_exploGunCounter % 2 == 0)
+ {
+ pos = m_particle[i].pos;
+ Math::Vector speed;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 0.0f;
+ Math::Point dim;
+ dim.x = Math::Rand()*4.0f+2.0f;
+ dim.y = dim.x;
+ float duration = Math::Rand()*0.7f+0.7f;
+ float mass = 0.0f;
+ CreateParticle(pos, speed, dim, PARTIEXPLOG2, duration, mass, 1.0f);
+ }
+
+ if (m_exploGunCounter % 4 == 0)
+ Play(SOUND_EXPLOg2, pos, 0.5f);
+
+ DeleteRank(i);
+ continue;
+ }
+ }
+
+ m_particle[i].angle = Math::Rand()*Math::PI*2.0f;
+ m_particle[i].zoom = 1.0f-progress;
+
+ ts.x = 0.125f;
+ ts.y = 0.875f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTIFLIC)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].zoom = 0.1f+progress;
+ m_particle[i].intensity = 1.0f-progress;
+
+ ts.x = 0.00f;
+ ts.y = 0.75f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if (m_particle[i].type == PARTISHOW)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if (progress < 0.5f) m_particle[i].intensity = progress/0.5f;
+ else m_particle[i].intensity = 2.0f-progress/0.5f;
+ m_particle[i].zoom = 1.0f-progress*0.8f;
+ m_particle[i].angle -= rTime*Math::PI*0.5f;
+
+ ts.x = 0.50f;
+ ts.y = 0.00f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if (m_particle[i].type == PARTICHOC)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].zoom = 0.1f+progress;
+ m_particle[i].intensity = 1.0f-progress;
+
+ ts.x = 0.50f;
+ ts.y = 0.50f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if (m_particle[i].type == PARTIGFLAT)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].zoom = 0.1f+progress;
+ m_particle[i].intensity = 1.0f-progress;
+ m_particle[i].angle -= rTime*Math::PI*2.0f;
+
+ ts.x = 0.00f;
+ ts.y = 0.50f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if (m_particle[i].type == PARTILIMIT1)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].zoom = 1.0f;
+ m_particle[i].intensity = 1.0f;
+
+ ts.x = 0.000f;
+ ts.y = 0.125f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+ if (m_particle[i].type == PARTILIMIT2)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].zoom = 1.0f;
+ m_particle[i].intensity = 1.0f;
+
+ ts.x = 0.375f;
+ ts.y = 0.125f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+ if (m_particle[i].type == PARTILIMIT3)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].zoom = 1.0f;
+ m_particle[i].intensity = 1.0f;
+
+ ts.x = 0.500f;
+ ts.y = 0.125f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTIFOG0)
+ {
+ m_particle[i].zoom = progress;
+ m_particle[i].intensity = 0.3f+sinf(progress)*0.15f;
+ m_particle[i].angle += rTime*0.05f;
+
+ ts.x = 0.25f;
+ ts.y = 0.75f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+ if (m_particle[i].type == PARTIFOG1)
+ {
+ m_particle[i].zoom = progress;
+ m_particle[i].intensity = 0.3f+sinf(progress)*0.15f;
+ m_particle[i].angle -= rTime*0.07f;
+
+ ts.x = 0.25f;
+ ts.y = 0.75f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if (m_particle[i].type == PARTIFOG2)
+ {
+ m_particle[i].zoom = progress;
+ m_particle[i].intensity = 0.6f+sinf(progress)*0.15f;
+ m_particle[i].angle += rTime*0.05f;
+
+ ts.x = 0.75f;
+ ts.y = 0.75f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+ if (m_particle[i].type == PARTIFOG3)
+ {
+ m_particle[i].zoom = progress;
+ m_particle[i].intensity = 0.6f+sinf(progress)*0.15f;
+ m_particle[i].angle -= rTime*0.07f;
+
+ ts.x = 0.75f;
+ ts.y = 0.75f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if (m_particle[i].type == PARTIFOG4)
+ {
+ m_particle[i].zoom = progress;
+ m_particle[i].intensity = 0.5f+sinf(progress)*0.2f;
+ m_particle[i].angle += rTime*0.05f;
+
+ ts.x = 0.00f;
+ ts.y = 0.25f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+ if (m_particle[i].type == PARTIFOG5)
+ {
+ m_particle[i].zoom = progress;
+ m_particle[i].intensity = 0.5f+sinf(progress)*0.2f;
+ m_particle[i].angle -= rTime*0.07f;
+
+ ts.x = 0.00f;
+ ts.y = 0.25f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if (m_particle[i].type == PARTIFOG6)
+ {
+ m_particle[i].zoom = progress;
+ m_particle[i].intensity = 0.5f+sinf(progress)*0.2f;
+ m_particle[i].angle += rTime*0.05f;
+
+ ts.x = 0.50f;
+ ts.y = 0.25f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+ if (m_particle[i].type == PARTIFOG7)
+ {
+ m_particle[i].zoom = progress;
+ m_particle[i].intensity = 0.5f+sinf(progress)*0.2f;
+ m_particle[i].angle -= rTime*0.07f;
+
+ ts.x = 0.50f;
+ ts.y = 0.25f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ // Decreases the intensity if the camera
+ // is almost at the same height (fog was eye level).
+ if ( m_particle[i].type >= PARTIFOG0 &&
+ m_particle[i].type <= PARTIFOG9 )
+ {
+ float h = 10.0f;
+
+ if ( m_particle[i].pos.y >= eye.y &&
+ m_particle[i].pos.y < eye.y+h )
+ {
+ m_particle[i].intensity *= (m_particle[i].pos.y-eye.y)/h;
+ }
+ if ( m_particle[i].pos.y > eye.y-h &&
+ m_particle[i].pos.y < eye.y )
+ {
+ m_particle[i].intensity *= (eye.y-m_particle[i].pos.y)/h;
+ }
+ }
+
+ if ( m_particle[i].type == PARTIEXPLOT ||
+ m_particle[i].type == PARTIEXPLOO )
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].zoom = 1.0f-progress/2.0f;
+ m_particle[i].intensity = 1.0f-progress;
+
+ if (m_particle[i].type == PARTIEXPLOT) ts.x = 0.750f;
+ else ts.x = 0.875f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTIEXPLOG1)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].intensity = 1.0f-progress;
+
+ ts.x = 0.375f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+ if (m_particle[i].type == PARTIEXPLOG2)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].intensity = 1.0f-progress;
+
+ ts.x = 0.625f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTIFLAME)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].zoom = 1.0f-progress/2.0f;
+ if (progress < 0.5f)
+ {
+ m_particle[i].intensity = progress/0.5f;
+ }
+ else
+ {
+ m_particle[i].intensity = 2.0f-progress/0.5f;
+ }
+
+ ts.x = 0.750f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTIBUBBLE)
+ {
+ if ( progress >= 1.0f ||
+ m_particle[i].pos.y >= m_water->GetLevel() )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].zoom = 1.0f-progress/2.0f;
+ m_particle[i].intensity = 1.0f-progress;
+
+ ts.x = 0.250f;
+ ts.y = 0.875f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particle[i].type == PARTISMOKE1 ||
+ m_particle[i].type == PARTISMOKE2 ||
+ m_particle[i].type == PARTISMOKE3 )
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if (progress < 0.25f)
+ {
+ m_particle[i].zoom = progress/0.25f;
+ }
+ else
+ {
+ m_particle[i].intensity = 1.0f-(progress-0.25f)/0.75f;
+ }
+
+ ts.x = 0.500f+0.125f*(m_particle[i].type-PARTISMOKE1);
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTIBLOOD)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].intensity = 1.0f-progress;
+
+ ts.x = 0.750f+(rand()%2)*0.125f;
+ ts.y = 0.875f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTIBLOODM)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].intensity = 1.0f-progress;
+
+ ts.x = 0.875f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particle[i].type == PARTIVIRUS1 ||
+ m_particle[i].type == PARTIVIRUS2 ||
+ m_particle[i].type == PARTIVIRUS3 ||
+ m_particle[i].type == PARTIVIRUS4 ||
+ m_particle[i].type == PARTIVIRUS5 ||
+ m_particle[i].type == PARTIVIRUS6 ||
+ m_particle[i].type == PARTIVIRUS7 ||
+ m_particle[i].type == PARTIVIRUS8 ||
+ m_particle[i].type == PARTIVIRUS9 ||
+ m_particle[i].type == PARTIVIRUS10 )
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if (progress < 0.25f)
+ m_particle[i].zoom = progress/0.25f;
+ else
+ m_particle[i].intensity = 1.0f-(progress-0.25f)/0.75f;
+
+ m_particle[i].angle += rTime*Math::PI*1.0f;
+
+ if (m_particle[i].type == PARTIVIRUS1) // A ?
+ {
+ ts.x = 0.0f/256.0f; ts.y = 19.0f/256.0f;
+ ti.x = 10.0f/256.0f; ti.y = 30.0f/256.0f;
+ }
+ if (m_particle[i].type == PARTIVIRUS2) // C ?
+ {
+ ts.x = 19.0f/256.0f; ts.y = 19.0f/256.0f;
+ ti.x = 28.0f/256.0f; ti.y = 30.0f/256.0f;
+ }
+ if (m_particle[i].type == PARTIVIRUS3) // E ?
+ {
+ ts.x = 36.0f/256.0f; ts.y = 19.0f/256.0f;
+ ti.x = 45.0f/256.0f; ti.y = 30.0f/256.0f;
+ }
+ if (m_particle[i].type == PARTIVIRUS4) // N ?
+ {
+ ts.x = 110.0f/256.0f; ts.y = 19.0f/256.0f;
+ ti.x = 120.0f/256.0f; ti.y = 30.0f/256.0f;
+ }
+ if (m_particle[i].type == PARTIVIRUS5) // R ?
+ {
+ ts.x = 148.0f/256.0f; ts.y = 19.0f/256.0f;
+ ti.x = 158.0f/256.0f; ti.y = 30.0f/256.0f;
+ }
+ if (m_particle[i].type == PARTIVIRUS6) // T ?
+ {
+ ts.x = 166.0f/256.0f; ts.y = 19.0f/256.0f;
+ ti.x = 175.0f/256.0f; ti.y = 30.0f/256.0f;
+ }
+ if (m_particle[i].type == PARTIVIRUS7) // 0 ?
+ {
+ ts.x = 90.0f/256.0f; ts.y = 2.0f/256.0f;
+ ti.x = 98.0f/256.0f; ti.y = 13.0f/256.0f;
+ }
+ if (m_particle[i].type == PARTIVIRUS8) // 2 ?
+ {
+ ts.x = 103.0f/256.0f; ts.y = 2.0f/256.0f;
+ ti.x = 111.0f/256.0f; ti.y = 13.0f/256.0f;
+ }
+ if (m_particle[i].type == PARTIVIRUS9) // 5 ?
+ {
+ ts.x = 125.0f/256.0f; ts.y = 2.0f/256.0f;
+ ti.x = 132.0f/256.0f; ti.y = 13.0f/256.0f;
+ }
+ if (m_particle[i].type == PARTIVIRUS10) // 9 ?
+ {
+ ts.x = 153.0f/256.0f; ts.y = 2.0f/256.0f;
+ ti.x = 161.0f/256.0f; ti.y = 13.0f/256.0f;
+ }
+ }
+
+ if (m_particle[i].type == PARTIBLUE)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].zoom = 1.0f-progress;
+
+ ts.x = 0.625f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTIROOT)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if (progress < 0.25f)
+ {
+ m_particle[i].zoom = progress/0.25f;
+ }
+ else
+ {
+ m_particle[i].intensity = 1.0f-(progress-0.25f)/0.75f;
+ }
+
+ ts.x = 0.000f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTIRECOVER)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if (progress < 0.25f)
+ {
+ m_particle[i].zoom = progress/0.25f;
+ }
+ else
+ {
+ m_particle[i].intensity = 1.0f-(progress-0.25f)/0.75f;
+ }
+
+ ts.x = 0.875f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTIEJECT)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].zoom = 1.0f+powf(progress, 2.0f)*5.0f;
+ m_particle[i].intensity = 1.0f-progress;
+
+ ts.x = 0.625f;
+ ts.y = 0.875f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTISCRAPS)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].zoom = 1.0f-progress;
+
+ ts.x = 0.625f;
+ ts.y = 0.875f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTIFRAG)
+ {
+ m_particle[i].angle += rTime*Math::PI*0.5f;
+
+ ts.x = 0.0f;
+ ts.y = 0.0f;
+ ti.x = 0.0f;
+ ti.y = 0.0f;
+ }
+
+ if (m_particle[i].type == PARTIPART)
+ {
+ ts.x = 0.0f;
+ ts.y = 0.0f;
+ ti.x = 0.0f;
+ ti.y = 0.0f;
+ }
+
+ if (m_particle[i].type == PARTIQUEUE)
+ {
+ if (m_particle[i].testTime >= 0.05f)
+ {
+ m_particle[i].testTime = 0.0f;
+
+ pos = m_particle[i].pos;
+ Math::Vector speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ Math::Point dim;
+ dim.x = 1.0f*(Math::Rand()*0.8f+0.6f);
+ dim.y = dim.x;
+ CreateParticle(pos, speed, dim, PARTIGAS, 0.5f);
+ }
+
+ ts.x = 0.375f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTIORGANIC1)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+
+ pos = m_particle[i].pos;
+ Math::Point dim;
+ dim.x = m_particle[i].dim.x/4.0f;
+ dim.y = dim.x;
+ float duration = m_particle[i].duration;
+ float mass = m_particle[i].mass;
+ int total = static_cast<int>((10.0f*m_engine->GetParticleDensity()));
+ for (int j = 0; j < total; j++)
+ {
+ Math::Vector speed;
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.y = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ CreateParticle(pos, speed, dim, PARTIORGANIC2, duration, mass);
+ }
+ total = static_cast<int>((5.0f*m_engine->GetParticleDensity()));
+ for (int j = 0; j < total; j++)
+ {
+ Math::Vector speed;
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.y = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ duration *= Math::Rand()+0.8f;
+ CreateTrack(pos, speed, dim, PARTITRACK4, duration, mass, duration*0.2f, dim.x*2.0f);
+ }
+ continue;
+ }
+
+ m_particle[i].zoom = (m_particle[i].time-m_particle[i].duration);
+
+ ts.x = 0.125f;
+ ts.y = 0.875f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTIORGANIC2)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].zoom = 1.0f-(m_particle[i].time-m_particle[i].duration);
+
+ ts.x = 0.125f;
+ ts.y = 0.875f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTIGLINT)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if (progress > 0.5f)
+ m_particle[i].zoom = 1.0f-(progress-0.5f)*2.0f;
+
+ m_particle[i].angle = m_particle[i].time*Math::PI;
+
+ ts.x = 0.75f;
+ ts.y = 0.25f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if (m_particle[i].type == PARTIGLINTb)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if (progress > 0.5f)
+ m_particle[i].zoom = 1.0f-(progress-0.5f)*2.0f;
+
+ m_particle[i].angle = m_particle[i].time*Math::PI;
+
+ ts.x = 0.75f;
+ ts.y = 0.50f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if (m_particle[i].type == PARTIGLINTr)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if (progress > 0.5f)
+ m_particle[i].zoom = 1.0f-(progress-0.5f)*2.0f;
+
+ m_particle[i].angle = m_particle[i].time*Math::PI;
+
+ ts.x = 0.75f;
+ ts.y = 0.00f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if ( m_particle[i].type >= PARTILENS1 &&
+ m_particle[i].type <= PARTILENS4 )
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if (progress < 0.5f)
+ m_particle[i].zoom = progress*2.0f;
+ else
+ m_particle[i].intensity = 1.0f-(progress-0.5f)*2.0f;
+
+ ts.x = 0.25f*(m_particle[i].type-PARTILENS1);
+ ts.y = 0.25f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if (m_particle[i].type == PARTICONTROL)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if (progress < 0.3f)
+ {
+ m_particle[i].zoom = progress/0.3f;
+ }
+ else
+ {
+ m_particle[i].zoom = 1.0f;
+ m_particle[i].intensity = 1.0f-(progress-0.3f)/0.7f;
+ }
+
+ ts.x = 0.00f;
+ ts.y = 0.00f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if (m_particle[i].type == PARTIGUNDEL)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if (progress > 0.5f)
+ m_particle[i].zoom = 1.0f-(m_particle[i].time-m_particle[i].duration/2.0f);
+
+ m_particle[i].angle = m_particle[i].time*Math::PI;
+
+ ts.x = 0.75f;
+ ts.y = 0.50f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if (m_particle[i].type == PARTIQUARTZ)
+ {
+ if (progress >= 1.0f)
+ {
+ m_particle[i].time = 0.0f;
+ m_particle[i].duration = 0.5f+Math::Rand()*2.0f;
+ m_particle[i].pos.x = m_particle[i].speed.x + (Math::Rand()-0.5f)*m_particle[i].mass;
+ m_particle[i].pos.y = m_particle[i].speed.y + (Math::Rand()-0.5f)*m_particle[i].mass;
+ m_particle[i].pos.z = m_particle[i].speed.z + (Math::Rand()-0.5f)*m_particle[i].mass;
+ m_particle[i].dim.x = 0.5f+Math::Rand()*1.5f;
+ m_particle[i].dim.y = m_particle[i].dim.x;
+ progress = 0.0f;
+ }
+
+ if (progress < 0.2f)
+ {
+ m_particle[i].zoom = progress/0.2f;
+ m_particle[i].intensity = 1.0f;
+ }
+ else
+ {
+ m_particle[i].zoom = 1.0f;
+ m_particle[i].intensity = 1.0f-(progress-0.2f)/0.8f;
+ }
+
+ ts.x = 0.25f;
+ ts.y = 0.25f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if (m_particle[i].type == PARTITOTO)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].zoom = 1.0f-progress;
+ if (progress < 0.15f)
+ m_particle[i].intensity = progress/0.15f;
+ else
+ m_particle[i].intensity = 1.0f-(progress-0.15f)/0.85f;
+
+ m_particle[i].intensity *= 0.5f;
+
+ ts.x = 0.25f;
+ ts.y = 0.50f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if (m_particle[i].type == PARTIERROR)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].zoom = progress*1.0f;
+ m_particle[i].intensity = 1.0f-progress;
+
+ ts.x = 0.500f;
+ ts.y = 0.875f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTIWARNING)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].zoom = progress*1.0f;
+ m_particle[i].intensity = 1.0f-progress;
+
+ ts.x = 0.875f;
+ ts.y = 0.875f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTIINFO)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].zoom = progress*1.0f;
+ m_particle[i].intensity = 1.0f-progress;
+
+ ts.x = 0.750f;
+ ts.y = 0.875f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTISELY)
+ {
+ ts.x = 0.75f;
+ ts.y = 0.25f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+ if (m_particle[i].type == PARTISELR)
+ {
+ ts.x = 0.75f;
+ ts.y = 0.00f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if (m_particle[i].type == PARTISPHERE0)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].zoom = progress*m_particle[i].dim.x;
+
+ if (progress < 0.65f)
+ m_particle[i].intensity = progress/0.65f;
+ else
+ m_particle[i].intensity = 1.0f-(progress-0.65f)/0.35f;
+
+ m_particle[i].intensity *= 0.5f;
+
+ ts.x = 0.50f;
+ ts.y = 0.75f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if (m_particle[i].type == PARTISPHERE1)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if (progress < 0.30f)
+ m_particle[i].intensity = progress/0.30f;
+ else
+ m_particle[i].intensity = 1.0f-(progress-0.30f)/0.70f;
+
+ m_particle[i].zoom = progress*m_particle[i].dim.x;
+ m_particle[i].angle = m_particle[i].time*Math::PI*2.0f;
+
+ ts.x = 0.000f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTISPHERE2)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if (progress < 0.20f)
+ m_particle[i].intensity = 1.0f;
+ else
+ m_particle[i].intensity = 1.0f-(progress-0.20f)/0.80f;
+
+ m_particle[i].zoom = progress*m_particle[i].dim.x;
+ m_particle[i].angle = m_particle[i].time*Math::PI*2.0f;
+
+ ts.x = 0.125f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTISPHERE3)
+ {
+ if (m_particle[i].phase == PARPHEND &&
+ progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if (m_particle[i].phase == PARPHSTART)
+ {
+ m_particle[i].intensity = progress;
+ if (m_particle[i].intensity > 1.0f)
+ m_particle[i].intensity = 1.0f;
+ }
+
+ if (m_particle[i].phase == PARPHEND)
+ m_particle[i].intensity = 1.0f-progress;
+
+ m_particle[i].zoom = m_particle[i].dim.x;
+ m_particle[i].angle = m_particle[i].time*Math::PI*0.2f;
+
+ ts.x = 0.25f;
+ ts.y = 0.75f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if (m_particle[i].type == PARTISPHERE4)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].zoom = progress*m_particle[i].dim.x;
+
+ if (progress < 0.65 )
+ m_particle[i].intensity = progress/0.65f;
+ else
+ m_particle[i].intensity = 1.0f-(progress-0.65f)/0.35f;
+
+ m_particle[i].intensity *= 0.5f;
+
+ ts.x = 0.125f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTISPHERE5)
+ {
+ m_particle[i].intensity = 0.7f+sinf(progress)*0.3f;
+ m_particle[i].zoom = m_particle[i].dim.x*(1.0f+sinf(progress*0.7f)*0.01f);
+ m_particle[i].angle = m_particle[i].time*Math::PI*0.2f;
+
+ ts.x = 0.25f;
+ ts.y = 0.50f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if (m_particle[i].type == PARTISPHERE6)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].zoom = (1.0f-progress)*m_particle[i].dim.x;
+ m_particle[i].intensity = progress*0.5f;
+
+ ts.x = 0.125f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTIPLOUF0)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].zoom = progress;
+ m_particle[i].intensity = 1.0f-progress;
+
+ ts.x = 0.50f;
+ ts.y = 0.50f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if (m_particle[i].type == PARTIDROP)
+ {
+ if (progress >= 1.0f ||
+ m_particle[i].pos.y < m_water->GetLevel())
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].zoom = 1.0f-progress;
+ m_particle[i].intensity = 1.0f-progress;
+
+ ts.x = 0.750f;
+ ts.y = 0.500f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTIWATER)
+ {
+ if (progress >= 1.0f ||
+ m_particle[i].pos.y < m_water->GetLevel())
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particle[i].intensity = 1.0f-progress;
+
+ ts.x = 0.125f;
+ ts.y = 0.125f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if (m_particle[i].type == PARTIRAY1) // rayon tour ?
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if (m_particle[i].testTime >= 0.2f)
+ {
+ m_particle[i].testTime = 0.0f;
+ CObject* object = SearchObjectRay(m_particle[i].pos, m_particle[i].goal,
+ m_particle[i].type, m_particle[i].objFather);
+ if (object != nullptr)
+ object->ExploObject(EXPLO_BOUM, 0.0f);
+ }
+
+ ts.x = 0.00f;
+ ts.y = 0.00f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if (m_particle[i].type == PARTIRAY2 ||
+ m_particle[i].type == PARTIRAY3)
+ {
+ if (progress >= 1.0f)
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ ts.x = 0.00f;
+ ts.y = 0.25f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ float dp = (1.0f/256.0f)/2.0f;
+ m_particle[i].texSup.x = ts.x+dp;
+ m_particle[i].texSup.y = ts.y+dp;
+ m_particle[i].texInf.x = ti.x-dp;
+ m_particle[i].texInf.y = ti.y-dp;
+ m_particle[i].time += rTime;
+ m_particle[i].testTime += rTime;
+ }
}
-void CParticle::DeleteRank(int rank)
+bool CParticle::TrackMove(int i, Math::Vector pos, float progress)
{
- GetLogger()->Trace("CParticle::DeleteRank() stub!\n");
- // TODO!
+ if (i < 0 || i >= MAXTRACK) return true;
+ if (! m_track[i].used) return true;
+
+ if (progress < 1.0f) // particle exists?
+ {
+ int h = m_track[i].head;
+
+ Math::Vector last;
+
+ if ( m_track[i].posUsed == 1 ||
+ m_track[i].last+m_track[i].step <= progress )
+ {
+ m_track[i].last = progress;
+ last = m_track[i].pos[h];
+ h ++;
+ if (h == MAXTRACKLEN) h = 0;
+ if (m_track[i].posUsed < MAXTRACKLEN) m_track[i].posUsed++;
+ }
+ else
+ {
+ int hh = h-1;
+ if (hh < 0) hh = MAXTRACKLEN-1;
+ last = m_track[i].pos[hh];
+ }
+ m_track[i].pos[h] = pos;
+ m_track[i].len[h] = Math::Distance(pos, last);
+
+ m_track[i].head = h;
+
+ m_track[i].intensity = 1.0f-progress;
+ }
+ else // slow death of the track ?
+ {
+ m_track[i].intensity = 0.0f;
+ }
+
+ return (m_track[i].intensity <= 0.0f);
}
-bool CParticle::CheckChannel(int &channel)
+void CParticle::TrackDraw(int i, ParticleType type)
{
- GetLogger()->Trace("CParticle::CheckChannel() stub!\n");
- // TODO!
- return true;
+ // Calculates the total length memorized.
+ float lTotal = 0.0f;
+ int h = m_track[i].head;
+ for (int counter = 0; counter < m_track[i].posUsed-1; counter++)
+ {
+ lTotal += m_track[i].len[h];
+ h--;
+ if (h < 0) h = MAXTRACKLEN-1;
+ }
+
+ Math::Matrix mat;
+ mat.LoadIdentity();
+ m_device->SetTransform(TRANSFORM_WORLD, mat);
+
+ Math::Point texInf, texSup;
+
+ if (type == PARTITRACK1) // explosion technique?
+ {
+ texInf.x = 64.5f/256.0f;
+ texInf.y = 21.0f/256.0f;
+ texSup.x = 95.5f/256.0f;
+ texSup.y = 22.0f/256.0f; // orange
+ }
+ if (type == PARTITRACK2) // blue spray?
+ {
+ texInf.x = 64.5f/256.0f;
+ texInf.y = 13.0f/256.0f;
+ texSup.x = 95.5f/256.0f;
+ texSup.y = 14.0f/256.0f; // blue
+ }
+ if (type == PARTITRACK3) // spider?
+ {
+ texInf.x = 64.5f/256.0f;
+ texInf.y = 5.0f/256.0f;
+ texSup.x = 95.5f/256.0f;
+ texSup.y = 6.0f/256.0f; // brown
+ }
+ if (type == PARTITRACK4) // insect explosion?
+ {
+ texInf.x = 64.5f/256.0f;
+ texInf.y = 9.0f/256.0f;
+ texSup.x = 95.5f/256.0f;
+ texSup.y = 10.0f/256.0f; // dark green
+ }
+ if (type == PARTITRACK5) // derrick?
+ {
+ texInf.x = 64.5f/256.0f;
+ texInf.y = 29.0f/256.0f;
+ texSup.x = 95.5f/256.0f;
+ texSup.y = 30.0f/256.0f; // dark brown
+ }
+ if (type == PARTITRACK6) // reset in/out?
+ {
+ texInf.x = 64.5f/256.0f;
+ texInf.y = 17.0f/256.0f;
+ texSup.x = 95.5f/256.0f;
+ texSup.y = 18.0f/256.0f; // cyan
+ }
+ if (type == PARTITRACK7) // win-1?
+ {
+ texInf.x = 64.5f/256.0f;
+ texInf.y = 41.0f/256.0f;
+ texSup.x = 95.5f/256.0f;
+ texSup.y = 42.0f/256.0f; // orange
+ }
+ if (type == PARTITRACK8) // win-2?
+ {
+ texInf.x = 64.5f/256.0f;
+ texInf.y = 45.0f/256.0f;
+ texSup.x = 95.5f/256.0f;
+ texSup.y = 46.0f/256.0f; // yellow
+ }
+ if (type == PARTITRACK9) // win-3?
+ {
+ texInf.x = 64.5f/256.0f;
+ texInf.y = 49.0f/256.0f;
+ texSup.x = 95.5f/256.0f;
+ texSup.y = 50.0f/256.0f; // red
+ }
+ if (type == PARTITRACK10) // win-4?
+ {
+ texInf.x = 64.5f/256.0f;
+ texInf.y = 53.0f/256.0f;
+ texSup.x = 95.5f/256.0f;
+ texSup.y = 54.0f/256.0f; // violet
+ }
+ if (type == PARTITRACK11) // phazer shot?
+ {
+ texInf.x = 64.5f/256.0f;
+ texInf.y = 21.0f/256.0f;
+ texSup.x = 95.5f/256.0f;
+ texSup.y = 22.0f/256.0f; // orange
+ }
+ if (type == PARTITRACK12) // drag reactor?
+ {
+ texInf.x = 64.5f/256.0f;
+ texInf.y = 21.0f/256.0f;
+ texSup.x = 95.5f/256.0f;
+ texSup.y = 22.0f/256.0f; // orange
+ }
+
+ h = m_track[i].head;
+ Math::Vector p1 = m_track[i].pos[h];
+ float f1 = m_track[i].intensity;
+
+ Math::Vector eye = m_engine->GetEyePt();
+ float a = Math::RotateAngle(eye.x-p1.x, eye.z-p1.z);
+
+ Vertex vertex[4];
+ Math::Vector corner[4];
+
+ for (int counter = 0; counter < m_track[i].posUsed-1; counter++)
+ {
+ float f2 = f1-(m_track[i].len[h]/lTotal);
+ if (f2 < 0.0f) f2 = 0.0f;
+
+ h --;
+ if (h < 0) h = MAXTRACKLEN-1;
+
+ Math::Vector p2 = m_track[i].pos[h];
+
+ Math::Vector n = Normalize(p1-eye);
+
+ Math::Vector p;
+ Math::Point rot;
+
+ p = p1;
+ p.x += f1*m_track[i].width;
+ rot = Math::RotatePoint(Math::Point(p1.x, p1.z), a+Math::PI/2.0f, Math::Point(p.x, p.z));
+ corner[0].x = rot.x;
+ corner[0].y = p1.y;
+ corner[0].z = rot.y;
+ rot = Math::RotatePoint(Math::Point(p1.x, p1.z), a-Math::PI/2.0f, Math::Point(p.x, p.z));
+ corner[1].x = rot.x;
+ corner[1].y = p1.y;
+ corner[1].z = rot.y;
+
+ p = p2;
+ p.x += f2*m_track[i].width;
+ rot = Math::RotatePoint(Math::Point(p2.x, p2.z), a+Math::PI/2.0f, Math::Point(p.x, p.z));
+ corner[2].x = rot.x;
+ corner[2].y = p2.y;
+ corner[2].z = rot.y;
+ rot = Math::RotatePoint(Math::Point(p2.x, p2.z), a-Math::PI/2.0f, Math::Point(p.x, p.z));
+ corner[3].x = rot.x;
+ corner[3].y = p2.y;
+ corner[3].z = rot.y;
+
+ if (p2.y < p1.y)
+ {
+ vertex[0] = Vertex(corner[1], n, Math::Point(texSup.x, texSup.y));
+ vertex[1] = Vertex(corner[0], n, Math::Point(texInf.x, texSup.y));
+ vertex[2] = Vertex(corner[3], n, Math::Point(texSup.x, texInf.y));
+ vertex[3] = Vertex(corner[2], n, Math::Point(texInf.x, texInf.y));
+ }
+ else
+ {
+ vertex[0] = Vertex(corner[0], n, Math::Point(texSup.x, texSup.y));
+ vertex[1] = Vertex(corner[1], n, Math::Point(texInf.x, texSup.y));
+ vertex[2] = Vertex(corner[2], n, Math::Point(texSup.x, texInf.y));
+ vertex[3] = Vertex(corner[3], n, Math::Point(texInf.x, texInf.y));
+ }
+
+ m_device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, vertex, 4);
+ m_engine->AddStatisticTriangle(2);
+
+ if (f2 < 0.0f) break;
+ f1 = f2;
+ p1 = p2;
+ }
}
void CParticle::DrawParticleTriangle(int i)
{
- GetLogger()->Trace("CParticle::DrawParticleTriangle() stub!\n");
- // TODO!
+ if (m_particle[i].zoom == 0.0f) return;
+
+ Math::Vector eye = m_engine->GetEyePt();
+ Math::Vector pos = m_particle[i].pos;
+
+ CObject* object = m_particle[i].objLink;
+ if (object != nullptr)
+ pos += object->GetPosition(0);
+
+ Math::Vector angle;
+ angle.x = -Math::RotateAngle(Math::DistanceProjected(pos, eye), pos.y-eye.y);
+ angle.y = Math::RotateAngle(pos.z-eye.z, pos.x-eye.x);
+ angle.z = m_particle[i].angle;
+
+ Math::Matrix mat;
+ Math::LoadRotationXZYMatrix(mat, angle);
+ mat.Set(1, 4, pos.x);
+ mat.Set(2, 4, pos.y);
+ mat.Set(3, 4, pos.z);
+ m_device->SetTransform(TRANSFORM_WORLD, mat);
+
+ m_device->DrawPrimitive(PRIMITIVE_TRIANGLES, m_triangle[i].triangle, 3);
+ m_engine->AddStatisticTriangle(1);
}
void CParticle::DrawParticleNorm(int i)
{
- GetLogger()->Trace("CParticle::DrawParticleNorm() stub!\n");
- // TODO!
+ float zoom = m_particle[i].zoom;
+
+ if (zoom == 0.0f) return;
+ if (m_particle[i].intensity == 0.0f) return;
+
+
+ Math::Vector corner[4];
+ Vertex vertex[4];
+
+ if (m_particle[i].sheet == SH_INTERFACE)
+ {
+ Math::Vector pos = m_particle[i].pos;
+
+ Math::Vector n(0.0f, 0.0f, -1.0f);
+
+ Math::Point dim;
+ dim.x = m_particle[i].dim.x * zoom;
+ dim.y = m_particle[i].dim.y * zoom;
+
+ corner[0].x = pos.x+dim.x;
+ corner[0].y = pos.y+dim.y;
+ corner[0].z = 0.0f;
+
+ corner[1].x = pos.x-dim.x;
+ corner[1].y = pos.y+dim.y;
+ corner[1].z = 0.0f;
+
+ corner[2].x = pos.x+dim.x;
+ corner[2].y = pos.y-dim.y;
+ corner[2].z = 0.0f;
+
+ corner[3].x = pos.x-dim.x;
+ corner[3].y = pos.y-dim.y;
+ corner[3].z = 0.0f;
+
+ vertex[0] = Vertex(corner[1], n, Math::Point(m_particle[i].texSup.x, m_particle[i].texSup.y));
+ vertex[1] = Vertex(corner[0], n, Math::Point(m_particle[i].texInf.x, m_particle[i].texSup.y));
+ vertex[2] = Vertex(corner[3], n, Math::Point(m_particle[i].texSup.x, m_particle[i].texInf.y));
+ vertex[3] = Vertex(corner[2], n, Math::Point(m_particle[i].texInf.x, m_particle[i].texInf.y));
+
+ m_device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, vertex, 4);
+ m_engine->AddStatisticTriangle(2);
+ }
+ else
+ {
+ Math::Vector eye = m_engine->GetEyePt();
+ Math::Vector pos = m_particle[i].pos;
+
+ CObject* object = m_particle[i].objLink;
+ if (object != nullptr)
+ pos += object->GetPosition(0);
+
+ Math::Vector angle;
+ angle.x = -Math::RotateAngle(Math::DistanceProjected(pos, eye), pos.y-eye.y);
+ angle.y = Math::RotateAngle(pos.z-eye.z, pos.x-eye.x);
+ angle.z = m_particle[i].angle;
+
+ Math::Matrix mat;
+ Math::LoadRotationXZYMatrix(mat, angle);
+ mat.Set(1, 4, pos.x);
+ mat.Set(2, 4, pos.y);
+ mat.Set(3, 4, pos.z);
+ m_device->SetTransform(TRANSFORM_WORLD, mat);
+
+ Math::Vector n(0.0f, 0.0f, -1.0f);
+
+ Math::Point dim;
+ dim.x = m_particle[i].dim.x * zoom;
+ dim.y = m_particle[i].dim.y * zoom;
+
+ corner[0].x = dim.x;
+ corner[0].y = dim.y;
+ corner[0].z = 0.0f;
+
+ corner[1].x = -dim.x;
+ corner[1].y = dim.y;
+ corner[1].z = 0.0f;
+
+ corner[2].x = dim.x;
+ corner[2].y = -dim.y;
+ corner[2].z = 0.0f;
+
+ corner[3].x = -dim.x;
+ corner[3].y = -dim.y;
+ corner[3].z = 0.0f;
+
+ vertex[0] = Vertex(corner[1], n, Math::Point(m_particle[i].texSup.x, m_particle[i].texSup.y));
+ vertex[1] = Vertex(corner[0], n, Math::Point(m_particle[i].texInf.x, m_particle[i].texSup.y));
+ vertex[2] = Vertex(corner[3], n, Math::Point(m_particle[i].texSup.x, m_particle[i].texInf.y));
+ vertex[3] = Vertex(corner[2], n, Math::Point(m_particle[i].texInf.x, m_particle[i].texInf.y));
+
+ m_device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, vertex, 4);
+ m_engine->AddStatisticTriangle(2);
+ }
}
void CParticle::DrawParticleFlat(int i)
{
- GetLogger()->Trace("CParticle::DrawParticleFlat() stub!\n");
- // TODO!
+ if (m_particle[i].zoom == 0.0f) return;
+ if (m_particle[i].intensity == 0.0f) return;
+
+ Math::Vector pos = m_particle[i].pos;
+
+ CObject* object = m_particle[i].objLink;
+ if (object != nullptr)
+ pos += object->GetPosition(0);
+
+ Math::Vector angle;
+ angle.x = Math::PI/2.0f;
+ angle.y = 0.0f;
+ angle.z = m_particle[i].angle;
+
+ if (m_engine->GetRankView() == 1) // underwater?
+ pos.y -= 1.0f;
+
+ Math::Vector eye = m_engine->GetEyePt();
+ if (pos.y > eye.y) // seen from below?
+ angle.x = -Math::PI/2.0f;
+
+ Math::Matrix mat;
+ Math::LoadRotationXZYMatrix(mat, angle);
+ mat.Set(1, 4, pos.x);
+ mat.Set(2, 4, pos.y);
+ mat.Set(3, 4, pos.z);
+ m_device->SetTransform(TRANSFORM_WORLD, mat);
+
+ Math::Vector n(0.0f, 0.0f, -1.0f);
+
+ Math::Point dim;
+ dim.x = m_particle[i].dim.x * m_particle[i].zoom;
+ dim.y = m_particle[i].dim.y * m_particle[i].zoom;
+
+ Math::Vector corner[4];
+ corner[0].x = dim.x;
+ corner[0].y = dim.y;
+ corner[0].z = 0.0f;
+
+ corner[1].x = -dim.x;
+ corner[1].y = dim.y;
+ corner[1].z = 0.0f;
+
+ corner[2].x = dim.x;
+ corner[2].y = -dim.y;
+ corner[2].z = 0.0f;
+
+ corner[3].x = -dim.x;
+ corner[3].y = -dim.y;
+ corner[3].z = 0.0f;
+
+ Vertex vertex[4];
+ vertex[0] = Vertex(corner[1], n, Math::Point(m_particle[i].texSup.x, m_particle[i].texSup.y));
+ vertex[1] = Vertex(corner[0], n, Math::Point(m_particle[i].texInf.x, m_particle[i].texSup.y));
+ vertex[2] = Vertex(corner[3], n, Math::Point(m_particle[i].texSup.x, m_particle[i].texInf.y));
+ vertex[3] = Vertex(corner[2], n, Math::Point(m_particle[i].texInf.x, m_particle[i].texInf.y));
+
+ m_device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, vertex, 4);
+ m_engine->AddStatisticTriangle(2);
}
void CParticle::DrawParticleFog(int i)
{
- GetLogger()->Trace("CParticle::DrawParticleFog() stub!\n");
- // TODO!
+ if (!m_engine->GetFog()) return;
+ if (m_particle[i].intensity == 0.0f) return;
+
+ Math::Vector pos = m_particle[i].pos;
+
+ Math::Point dim;
+ dim.x = m_particle[i].dim.x;
+ dim.y = m_particle[i].dim.y;
+
+ Math::Point zoom;
+
+ if ( m_particle[i].type == PARTIFOG0 ||
+ m_particle[i].type == PARTIFOG2 ||
+ m_particle[i].type == PARTIFOG4 ||
+ m_particle[i].type == PARTIFOG6 )
+ {
+ zoom.x = 1.0f+sinf(m_particle[i].zoom*2.0f)/6.0f;
+ zoom.y = 1.0f+cosf(m_particle[i].zoom*2.7f)/6.0f;
+ }
+ if ( m_particle[i].type == PARTIFOG1 ||
+ m_particle[i].type == PARTIFOG3 ||
+ m_particle[i].type == PARTIFOG5 ||
+ m_particle[i].type == PARTIFOG7 )
+ {
+ zoom.x = 1.0f+sinf(m_particle[i].zoom*3.0f)/6.0f;
+ zoom.y = 1.0f+cosf(m_particle[i].zoom*3.7f)/6.0f;
+ }
+
+ dim.x *= zoom.x;
+ dim.y *= zoom.y;
+
+ CObject* object = m_particle[i].objLink;
+ if (object != nullptr)
+ pos += object->GetPosition(0);
+
+ Math::Vector angle;
+ angle.x = Math::PI/2.0f;
+ angle.y = 0.0f;
+ angle.z = m_particle[i].angle;
+
+ if (m_engine->GetRankView() == 1) // underwater?
+ pos.y -= 1.0f;
+
+ Math::Vector eye = m_engine->GetEyePt();
+ if (pos.y > eye.y) // seen from below?
+ angle.x = -Math::PI/2.0f;
+
+ Math::Matrix mat;
+ Math::LoadRotationXZYMatrix(mat, angle);
+ mat.Set(1, 4, pos.x);
+ mat.Set(2, 4, pos.y);
+ mat.Set(3, 4, pos.z);
+ m_device->SetTransform(TRANSFORM_WORLD, mat);
+
+ Math::Vector n(0.0f, 0.0f, -1.0f);
+
+ Math::Vector corner[4];
+
+ corner[0].x = dim.x;
+ corner[0].y = dim.y;
+ corner[0].z = 0.0f;
+
+ corner[1].x = -dim.x;
+ corner[1].y = dim.y;
+ corner[1].z = 0.0f;
+
+ corner[2].x = dim.x;
+ corner[2].y = -dim.y;
+ corner[2].z = 0.0f;
+
+ corner[3].x = -dim.x;
+ corner[3].y = -dim.y;
+ corner[3].z = 0.0f;
+
+ Vertex vertex[4];
+
+ vertex[0] = Vertex(corner[1], n, Math::Point(m_particle[i].texSup.x, m_particle[i].texSup.y));
+ vertex[1] = Vertex(corner[0], n, Math::Point(m_particle[i].texInf.x, m_particle[i].texSup.y));
+ vertex[2] = Vertex(corner[3], n, Math::Point(m_particle[i].texSup.x, m_particle[i].texInf.y));
+ vertex[3] = Vertex(corner[2], n, Math::Point(m_particle[i].texInf.x, m_particle[i].texInf.y));
+
+ m_device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, vertex, 4);
+ m_engine->AddStatisticTriangle(2);
}
void CParticle::DrawParticleRay(int i)
{
- GetLogger()->Trace("CParticle::DrawParticleRay() stub!\n");
- // TODO!
+ if (m_particle[i].zoom == 0.0f) return;
+ if (m_particle[i].intensity == 0.0f) return;
+
+ Math::Vector eye = m_engine->GetEyePt();
+ Math::Vector pos = m_particle[i].pos;
+ Math::Vector goal = m_particle[i].goal;
+
+ CObject* object = m_particle[i].objLink;
+ if (object != nullptr)
+ pos += object->GetPosition(0);
+
+ float a = Math::RotateAngle(Math::Point(pos.x,pos.z), Math::Point(goal.x,goal.z), Math::Point(eye.x,eye.z));
+ bool left = (a < Math::PI);
+
+ Math::Vector proj = Math::Projection(pos, goal, eye);
+ Math::Vector angle;
+ angle.x = -Math::RotateAngle(Math::DistanceProjected(proj, eye), proj.y-eye.y);
+ angle.y = Math::RotateAngle(pos.z-goal.z, pos.x-goal.x)+Math::PI/2.0f;
+ angle.z = -Math::RotateAngle(Math::DistanceProjected(pos, goal), pos.y-goal.y);
+ if (left) angle.x = -angle.x;
+
+ Math::Matrix mat;
+ Math::LoadRotationZXYMatrix(mat, angle);
+ mat.Set(1, 4, pos.x);
+ mat.Set(2, 4, pos.y);
+ mat.Set(3, 4, pos.z);
+ m_device->SetTransform(TRANSFORM_WORLD, mat);
+
+ Math::Vector n(0.0f, 0.0f, left ? 1.0f : -1.0f);
+
+ Math::Point dim;
+ dim.x = m_particle[i].dim.x * m_particle[i].zoom;
+ dim.y = m_particle[i].dim.y * m_particle[i].zoom;
+
+ if (left) dim.y = -dim.y;
+
+ float len = Math::Distance(pos, goal);
+ float adv = 0.0f;
+
+ int step = static_cast<int>((len/(dim.x*2.0f))+1);
+
+ float vario1, vario2;
+
+ if (step == 1)
+ {
+ vario1 = 1.0f;
+ vario2 = 1.0f;
+ }
+ else
+ {
+ vario1 = 0.0f;
+ vario2 = 2.0f;
+ }
+
+ int first, last;
+
+ if (m_particle[i].type == PARTIRAY2)
+ {
+ first = 0;
+ last = step;
+ vario1 = 0.0f;
+ vario2 = 0.0f;
+ }
+ else if (m_particle[i].type == PARTIRAY3)
+ {
+ if (m_particle[i].time < m_particle[i].duration*0.40f)
+ {
+ float prop = m_particle[i].time / (m_particle[i].duration*0.40f);
+ first = 0;
+ last = static_cast<int>(prop*step);
+ }
+ else if (m_particle[i].time < m_particle[i].duration*0.60f)
+ {
+ first = 0;
+ last = step;
+ }
+ else
+ {
+ float prop = (m_particle[i].time-m_particle[i].duration*0.60f) / (m_particle[i].duration*0.40f);
+ first = static_cast<int>(prop*step);
+ last = step;
+ }
+ }
+ else
+ {
+ if (m_particle[i].time < m_particle[i].duration*0.50f)
+ {
+ float prop = m_particle[i].time / (m_particle[i].duration*0.50f);
+ first = 0;
+ last = static_cast<int>(prop*step);
+ }
+ else if (m_particle[i].time < m_particle[i].duration*0.75f)
+ {
+ first = 0;
+ last = step;
+ }
+ else
+ {
+ float prop = (m_particle[i].time-m_particle[i].duration*0.75f) / (m_particle[i].duration*0.25f);
+ first = static_cast<int>(prop*step);
+ last = step;
+ }
+ }
+
+ Math::Vector corner[4];
+
+ corner[0].x = adv;
+ corner[2].x = adv;
+ corner[0].y = dim.y;
+ corner[2].y = -dim.y;
+ corner[0].z = (Math::Rand()-0.5f)*vario1;
+ corner[1].z = (Math::Rand()-0.5f)*vario1;
+ corner[2].z = (Math::Rand()-0.5f)*vario1;
+ corner[3].z = (Math::Rand()-0.5f)*vario1;
+
+ Vertex vertex[4];
+
+ for (int rank = 0; rank < step; rank++)
+ {
+ corner[1].x = corner[0].x;
+ corner[3].x = corner[2].x;
+ corner[0].x = adv+dim.x*2.0f+(Math::Rand()-0.5f)*vario2;
+ corner[2].x = adv+dim.x*2.0f+(Math::Rand()-0.5f)*vario2;
+
+ corner[1].y = corner[0].y;
+ corner[3].y = corner[2].y;
+ corner[0].y = dim.y+(Math::Rand()-0.5f)*vario2;
+ corner[2].y = -dim.y+(Math::Rand()-0.5f)*vario2;
+
+ if (rank >= first && rank <= last)
+ {
+ Math::Point texInf = m_particle[i].texInf;
+ Math::Point texSup = m_particle[i].texSup;
+
+ int r = rand() % 16;
+ texInf.x += 0.25f*(r/4);
+ texSup.x += 0.25f*(r/4);
+ if (r % 2 < 1 && adv > 0.0f && m_particle[i].type != PARTIRAY1)
+ Math::Swap(texInf.x, texSup.x);
+
+ if (r % 4 < 2)
+ Math::Swap(texInf.y, texSup.y);
+
+ vertex[0] = Vertex(corner[1], n, Math::Point(texSup.x, texSup.y));
+ vertex[1] = Vertex(corner[0], n, Math::Point(texInf.x, texSup.y));
+ vertex[2] = Vertex(corner[3], n, Math::Point(texSup.x, texInf.y));
+ vertex[3] = Vertex(corner[2], n, Math::Point(texInf.x, texInf.y));
+
+ m_device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, vertex, 4);
+ m_engine->AddStatisticTriangle(2);
+ }
+ adv += dim.x*2.0f;
+ }
}
void CParticle::DrawParticleSphere(int i)
{
- GetLogger()->Trace("CParticle::DrawParticleSphere() stub!\n");
- // TODO!
+ float zoom = m_particle[i].zoom;
+
+ if (zoom == 0.0f) return;
+
+ m_engine->SetState(ENG_RSTATE_TTEXTURE_BLACK | ENG_RSTATE_2FACE | ENG_RSTATE_WRAP,
+ IntensityToColor(m_particle[i].intensity));
+
+ Math::Matrix mat;
+ mat.LoadIdentity();
+ mat.Set(1, 1, zoom);
+ mat.Set(2, 2, zoom);
+ mat.Set(3, 3, zoom);
+ mat.Set(1, 4, m_particle[i].pos.x);
+ mat.Set(2, 4, m_particle[i].pos.y);
+ mat.Set(3, 4, m_particle[i].pos.z);
+
+ if (m_particle[i].angle != 0.0f)
+ {
+ Math::Vector angle;
+ angle.x = m_particle[i].angle*0.4f;
+ angle.y = m_particle[i].angle*1.0f;
+ angle.z = m_particle[i].angle*0.7f;
+ Math::Matrix rot;
+ Math::LoadRotationZXYMatrix(rot, angle);
+ mat = Math::MultiplyMatrices(rot, mat);
+ }
+
+ m_device->SetTransform(TRANSFORM_WORLD, mat);
+
+ Math::Point ts, ti;
+ ts.x = m_particle[i].texSup.x;
+ ts.y = m_particle[i].texSup.y;
+ ti.x = m_particle[i].texInf.x;
+ ti.y = m_particle[i].texInf.y;
+
+ int numRings, numSegments;
+
+ // Choose a tesselation level.
+ if ( m_particle[i].type == PARTISPHERE3 ||
+ m_particle[i].type == PARTISPHERE5 )
+ {
+ numRings = 16;
+ numSegments = 16;
+ }
+ else
+ {
+ numRings = 8;
+ numSegments = 10;
+ }
+
+ // Establish constants used in sphere generation.
+ float deltaRingAngle = Math::PI/numRings;
+ float deltaSegAngle = 2.0f*Math::PI/numSegments;
+
+ Vertex vertex[2*16*(16+1)];
+
+ // Generate the group of rings for the sphere.
+ int j = 0;
+ for (int ring = 0; ring < numRings; ring++)
+ {
+ float r0 = sinf((ring+0)*deltaRingAngle);
+ float r1 = sinf((ring+1)*deltaRingAngle);
+
+ Math::Vector v0, v1;
+
+ v0.y = cosf((ring+0)*deltaRingAngle);
+ v1.y = cosf((ring+1)*deltaRingAngle);
+
+ float tv0 = (ring+0)/static_cast<float>(numRings);
+ float tv1 = (ring+1)/static_cast<float>(numRings);
+ tv0 = ts.y+(ti.y-ts.y)*tv0;
+ tv1 = ts.y+(ti.y-ts.y)*tv1;
+
+ // Generate the group of segments for the current ring.
+ for (int seg = 0; seg < numSegments+1; seg++)
+ {
+ v0.x = r0*sinf(seg*deltaSegAngle);
+ v0.z = r0*cosf(seg*deltaSegAngle);
+ v1.x = r1*sinf(seg*deltaSegAngle);
+ v1.z = r1*cosf(seg*deltaSegAngle);
+
+ // Add two vertices to the strip which makes up the sphere.
+ float tu0 = (static_cast<float>(seg))/numSegments;
+ tu0 = ts.x+(ti.x-ts.x)*tu0;
+ float tu1 = tu0;
+
+ vertex[j++] = Vertex(v0, v0, Math::Point(tu0, tv0));
+ vertex[j++] = Vertex(v1, v1, Math::Point(tu1, tv1));
+ }
+ }
+
+ m_device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, vertex, j);
+ m_engine->AddStatisticTriangle(j);
+
+ m_engine->SetState(ENG_RSTATE_TTEXTURE_BLACK, IntensityToColor(m_particle[i].intensity));
+}
+
+//! Returns the height depending on the progress
+float ProgressCylinder(float progress)
+{
+ if (progress < 0.5f)
+ return 1.0f - (powf(1.0f-progress*2.0f, 2.0f));
+ else
+ return 1.0f - (powf(progress*2.0f-1.0f, 2.0f));
}
void CParticle::DrawParticleCylinder(int i)
{
- GetLogger()->Trace("CParticle::DrawParticleCylinder() stub!\n");
- // TODO!
+ float progress = m_particle[i].zoom;
+ float zoom = m_particle[i].dim.x;
+ float diam = m_particle[i].dim.y;
+ if (progress >= 1.0f || zoom == 0.0f) return;
+
+ m_engine->SetState(ENG_RSTATE_TTEXTURE_BLACK | ENG_RSTATE_2FACE | ENG_RSTATE_WRAP,
+ IntensityToColor(m_particle[i].intensity));
+
+ Math::Matrix mat;
+ mat.LoadIdentity();
+ mat.Set(1, 1, zoom);
+ mat.Set(2, 2, zoom);
+ mat.Set(3, 3, zoom);
+ mat.Set(1, 4, m_particle[i].pos.x);
+ mat.Set(2, 4, m_particle[i].pos.y);
+ mat.Set(3, 4, m_particle[i].pos.z);
+ m_device->SetTransform(TRANSFORM_WORLD, mat);
+
+ Math::Point ts, ti;
+ ts.x = m_particle[i].texSup.x;
+ ts.y = m_particle[i].texSup.y;
+ ti.x = m_particle[i].texInf.x;
+ ti.y = m_particle[i].texInf.y;
+
+ int numRings = 5;
+ int numSegments = 10;
+ float deltaSegAngle = 2.0f*Math::PI/numSegments;
+
+ float h[6] = { 0.0f };
+ float d[6] = { 0.0f };
+
+ if (m_particle[i].type == PARTIPLOUF0)
+ {
+ float p1 = progress; // front
+ float p2 = powf(progress, 5.0f); // back
+
+ for (int ring = 0; ring <= numRings; ring++)
+ {
+ float pp = p2+(p1-p2)*(static_cast<float>(ring)/numRings);
+ d[ring] = diam/zoom+pp*2.0f;
+ h[ring] = ProgressCylinder(pp);
+ }
+ }
+
+ Vertex vertex[2*5*(10+1)];
+
+ int j = 0;
+ for (int ring = 0; ring < numRings; ring++)
+ {
+ Math::Vector v0, v1;
+
+ float r0 = 1.0f*d[ring+0]; // radius at the base
+ float r1 = 1.0f*d[ring+1]; // radius at the top
+
+ v0.y = 1.0f*h[ring+0]; // bottom
+ v1.y = 1.0f*h[ring+1]; // top
+
+ float tv0 = 1.0f-(ring+0)*(1.0f/numRings);
+ float tv1 = 1.0f-(ring+1)*(1.0f/numRings);
+ tv0 = ts.y+(ti.y-ts.y)*tv0;
+ tv1 = ts.y+(ti.y-ts.y)*tv1;
+
+ for (int seg = 0; seg < numSegments+1; seg++)
+ {
+ v0.x = r0*sinf(seg*deltaSegAngle);
+ v0.z = r0*cosf(seg*deltaSegAngle);
+ v1.x = r1*sinf(seg*deltaSegAngle);
+ v1.z = r1*cosf(seg*deltaSegAngle);
+
+ float tu0 = (seg % 2) ? 0.0f : 1.0f;
+ tu0 = ts.x+(ti.x-ts.x)*tu0;
+ float tu1 = tu0;
+
+ vertex[j++] = Vertex(v0, v0, Math::Point(tu0, tv0));
+ vertex[j++] = Vertex(v1, v1, Math::Point(tu1, tv1));
+ }
+ }
+
+ m_device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, vertex, j);
+ m_engine->AddStatisticTriangle(j);
+
+ m_engine->SetState(ENG_RSTATE_TTEXTURE_BLACK, IntensityToColor(m_particle[i].intensity));
}
void CParticle::DrawParticleWheel(int i)
{
- GetLogger()->Trace("CParticle::DrawParticleWheel() stub!\n");
- // TODO!
+ float dist = Math::DistanceProjected(m_engine->GetEyePt(), m_wheelTrace[i].pos[0]);
+ if (dist > 300.0f) return;
+
+ Math::Vector pos[4];
+ pos[0] = m_wheelTrace[i].pos[0];
+ pos[1] = m_wheelTrace[i].pos[1];
+ pos[2] = m_wheelTrace[i].pos[2];
+ pos[3] = m_wheelTrace[i].pos[3];
+
+ Math::Point ts;
+
+ if (m_wheelTrace[i].type == PARTITRACE0) // white ground track?
+ {
+ ts.x = 8.0f/256.0f;
+ ts.y = 224.0f/256.0f;
+ }
+ else if (m_wheelTrace[i].type == PARTITRACE1) // black ground track?
+ {
+ ts.x = 0.0f/256.0f;
+ ts.y = 224.0f/256.0f;
+ }
+ else if (m_wheelTrace[i].type == PARTITRACE2) // gray ground track?
+ {
+ ts.x = 0.0f/256.0f;
+ ts.y = 232.0f/256.0f;
+ }
+ else if (m_wheelTrace[i].type == PARTITRACE3) // light gray ground track?
+ {
+ ts.x = 8.0f/256.0f;
+ ts.y = 232.0f/256.0f;
+ }
+ else if (m_wheelTrace[i].type == PARTITRACE4) // red ground track?
+ {
+ ts.x = 32.0f/256.0f;
+ ts.y = 224.0f/256.0f;
+ }
+ else if (m_wheelTrace[i].type == PARTITRACE5) // pink ground track?
+ {
+ ts.x = 40.0f/256.0f;
+ ts.y = 224.0f/256.0f;
+ }
+ else if (m_wheelTrace[i].type == PARTITRACE6) // violet ground track?
+ {
+ ts.x = 32.0f/256.0f;
+ ts.y = 232.0f/256.0f;
+ }
+ else if (m_wheelTrace[i].type == PARTITRACE7) // orange ground track?
+ {
+ ts.x = 40.0f/256.0f;
+ ts.y = 232.0f/256.0f;
+ }
+ else if (m_wheelTrace[i].type == PARTITRACE8) // yellow ground track?
+ {
+ ts.x = 16.0f/256.0f;
+ ts.y = 224.0f/256.0f;
+ }
+ else if (m_wheelTrace[i].type == PARTITRACE9) // beige ground track?
+ {
+ ts.x = 24.0f/256.0f;
+ ts.y = 224.0f/256.0f;
+ }
+ else if (m_wheelTrace[i].type == PARTITRACE10) // brown ground track?
+ {
+ ts.x = 16.0f/256.0f;
+ ts.y = 232.0f/256.0f;
+ }
+ else if (m_wheelTrace[i].type == PARTITRACE11) // skin ground track?
+ {
+ ts.x = 24.0f/256.0f;
+ ts.y = 232.0f/256.0f;
+ }
+ else if (m_wheelTrace[i].type == PARTITRACE12) // green ground track?
+ {
+ ts.x = 48.0f/256.0f;
+ ts.y = 224.0f/256.0f;
+ }
+ else if (m_wheelTrace[i].type == PARTITRACE13) // light green ground track?
+ {
+ ts.x = 56.0f/256.0f;
+ ts.y = 224.0f/256.0f;
+ }
+ else if (m_wheelTrace[i].type == PARTITRACE14) // blue ground track?
+ {
+ ts.x = 48.0f/256.0f;
+ ts.y = 232.0f/256.0f;
+ }
+ else if (m_wheelTrace[i].type == PARTITRACE15) // light blue ground track?
+ {
+ ts.x = 56.0f/256.0f;
+ ts.y = 232.0f/256.0f;
+ }
+ else if (m_wheelTrace[i].type == PARTITRACE16) // black arrow ground track?
+ {
+ ts.x = 160.0f/256.0f;
+ ts.y = 224.0f/256.0f;
+ }
+ else if (m_wheelTrace[i].type == PARTITRACE17) // red arrow ground track?
+ {
+ ts.x = 176.0f/256.0f;
+ ts.y = 224.0f/256.0f;
+ }
+ else
+ {
+ return;
+ }
+
+ Math::Point ti;
+
+ if ( m_wheelTrace[i].type == PARTITRACE16 ||
+ m_wheelTrace[i].type == PARTITRACE17 )
+ {
+ ti.x = ts.x+16.0f/256.0f;
+ ti.y = ts.y+16.0f/256.0f;
+ }
+ else
+ {
+ ti.x = ts.x+8.0f/256.0f;
+ ti.y = ts.y+8.0f/256.0f;
+ }
+
+ float dp = (1.0f/256.0f)/2.0f;
+ ts.x = ts.x+dp;
+ ts.y = ts.y+dp;
+ ti.x = ti.x-dp;
+ ti.y = ti.y-dp;
+
+ Math::Vector n(0.0f, 1.0f, 0.0f);
+
+ Vertex vertex[4];
+ vertex[0] = Vertex(pos[0], n, Math::Point(ts.x, ts.y));
+ vertex[1] = Vertex(pos[1], n, Math::Point(ti.x, ts.y));
+ vertex[2] = Vertex(pos[2], n, Math::Point(ts.x, ti.y));
+ vertex[3] = Vertex(pos[3], n, Math::Point(ti.x, ti.y));
+
+ m_device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, vertex, 4);
+ m_engine->AddStatisticTriangle(2);
}
-CObject* CParticle::SearchObjectGun(Math::Vector old, Math::Vector pos, ParticleType type, CObject *father)
+void CParticle::DrawParticle(int sheet)
{
- GetLogger()->Trace("CParticle::SearchObjectGun() stub!\n");
- // TODO!
- return nullptr;
+ // Draw the basic particles of triangles.
+ if (m_totalInterface[0][sheet] > 0)
+ {
+ for (int i = 0; i < MAXPARTICULE; i++)
+ {
+ if (!m_particle[i].used) continue;
+ if (m_particle[i].sheet != sheet) continue;
+ if (m_particle[i].type == PARTIPART) continue;
+
+ m_engine->SetTexture(m_triangle[i].tex1Name);
+ m_engine->SetMaterial(m_triangle[i].material);
+ m_engine->SetState(m_triangle[i].state);
+ DrawParticleTriangle(i);
+ }
+ }
+
+ Material mat;
+ mat.diffuse.r = 1.0f;
+ mat.diffuse.g = 1.0f;
+ mat.diffuse.b = 1.0f; // white
+ mat.ambient.r = 0.5f;
+ mat.ambient.g = 0.5f;
+ mat.ambient.b = 0.5f;
+ m_engine->SetMaterial(mat);
+
+ // Draw tire marks.
+ if (m_wheelTraceTotal > 0 && sheet == SH_WORLD)
+ {
+ m_engine->SetTexture("text.png");
+ m_engine->SetState(ENG_RSTATE_TTEXTURE_WHITE);
+ Math::Matrix mat;
+ mat.LoadIdentity();
+ m_device->SetTransform(TRANSFORM_WORLD, mat);
+
+ for (int i = 0; i < m_wheelTraceTotal; i++)
+ DrawParticleWheel(i);
+ }
+
+ for (int t = MAXPARTITYPE-1; t >= 1; t--) // black behind!
+ {
+ if (m_totalInterface[t][sheet] == 0) continue;
+
+ bool loadTexture = false;
+
+ int state;
+ if (t == 4) state = ENG_RSTATE_TTEXTURE_WHITE; // text.png
+ else state = ENG_RSTATE_TTEXTURE_BLACK; // effect[00..02].png
+ m_engine->SetState(state);
+
+ for (int j = 0; j < MAXPARTICULE; j++)
+ {
+ int i = MAXPARTICULE*t+j;
+ if (!m_particle[i].used) continue;
+ if (m_particle[i].sheet != sheet) continue;
+
+ if (!loadTexture)
+ {
+ std::string name;
+ NameParticle(name, t);
+ m_engine->SetTexture(name);
+ loadTexture = true;
+ }
+
+ int r = m_particle[i].trackRank;
+ if (r != -1)
+ {
+ m_engine->SetState(state);
+ TrackDraw(r, m_particle[i].type); // draws the drag
+ if (!m_track[r].drawParticle) continue;
+ }
+
+ m_engine->SetState(state, IntensityToColor(m_particle[i].intensity));
+
+ if (m_particle[i].ray) // ray?
+ {
+ DrawParticleRay(i);
+ }
+ else if ( m_particle[i].type == PARTIFLIC || // circle in the water?
+ m_particle[i].type == PARTISHOW ||
+ m_particle[i].type == PARTICHOC ||
+ m_particle[i].type == PARTIGFLAT )
+ {
+ DrawParticleFlat(i);
+ }
+ else if ( m_particle[i].type >= PARTIFOG0 &&
+ m_particle[i].type <= PARTIFOG9 )
+ {
+ DrawParticleFog(i);
+ }
+ else if ( m_particle[i].type >= PARTISPHERE0 &&
+ m_particle[i].type <= PARTISPHERE9 ) // sphere?
+ {
+ DrawParticleSphere(i);
+ }
+ else if ( m_particle[i].type >= PARTIPLOUF0 &&
+ m_particle[i].type <= PARTIPLOUF4 ) // cylinder?
+ {
+ DrawParticleCylinder(i);
+ }
+ else // normal?
+ {
+ DrawParticleNorm(i);
+ }
+ }
+ }
+}
+
+CObject* CParticle::SearchObjectGun(Math::Vector old, Math::Vector pos,
+ ParticleType type, CObject *father)
+{
+ if (m_main->GetMovieLock()) return nullptr; // current movie?
+
+ bool himself = m_main->GetHimselfDamage();
+
+ float min = 5.0f;
+ if (type == PARTIGUN2) min = 2.0f; // shooting insect?
+ if (type == PARTIGUN3) min = 3.0f; // suiciding spider?
+
+ Math::Vector box1 = old;
+ Math::Vector box2 = pos;
+ if (box1.x > box2.x) Math::Swap(box1.x, box2.x); // box1 < box2
+ if (box1.y > box2.y) Math::Swap(box1.y, box2.y);
+ if (box1.z > box2.z) Math::Swap(box1.z, box2.z);
+ box1.x -= min;
+ box1.y -= min;
+ box1.z -= min;
+ box2.x += min;
+ box2.y += min;
+ box2.z += min;
+
+ CObject* best = 0;
+ bool shield = false;
+ for (int i = 0; i < 1000000; i++)
+ {
+ CObject* obj = static_cast<CObject*>(m_iMan->SearchInstance(CLASS_OBJECT, i));
+ if (obj == 0) break;
+
+ if (!obj->GetActif()) continue; // inactive?
+ if (obj == father) continue;
+
+ ObjectType oType = obj->GetType();
+
+ if (oType == OBJECT_TOTO) continue;
+
+ if (type == PARTIGUN1) // fireball shooting?
+ {
+ if (oType == OBJECT_MOTHER) continue;
+ if (himself) // damage is oneself?
+ {
+ if ( !IsAlien(oType) &&
+ !IsSoft(oType) ) continue;
+ }
+ else // damage only to enemies?
+ {
+ if (!IsAlien(oType)) continue;
+ }
+ }
+ else if (type == PARTIGUN2) // shooting insect?
+ {
+ if (!IsSoft(oType)) continue;
+ }
+ else if (type == PARTIGUN3) // suiciding spider?
+ {
+ if (!IsSoft(oType)) continue;
+ }
+ else if (type == PARTIGUN4) // orgaball shooting?
+ {
+ if (oType == OBJECT_MOTHER) continue;
+ if (himself) // damage is oneself?
+ {
+ if ( !IsAlien(oType) &&
+ !IsSoft(oType) ) continue;
+ }
+ else // damage only to enemies?
+ {
+ if (!IsAlien(oType)) continue;
+ }
+ }
+ else if (type == PARTITRACK11) // phazer shooting?
+ {
+ if (himself) // damage is oneself?
+ {
+ if ( !IsAlien(oType) &&
+ !IsSoft(oType) ) continue;
+ }
+ else // damage only to enemies?
+ {
+ if (!IsAlien(oType)) continue;
+ }
+ }
+ else
+ {
+ continue;
+ }
+
+ Math::Vector oPos = obj->GetPosition(0);
+
+ if ( type == PARTIGUN2 || // shooting insect?
+ type == PARTIGUN3 ) // suiciding spider?
+ {
+ // Test if the ball is entered into the sphere of a shield.
+ float shieldRadius = obj->GetShieldRadius();
+ if (shieldRadius > 0.0f)
+ {
+ float dist = Math::Distance(oPos, pos);
+ if (dist <= shieldRadius)
+ {
+ best = obj;
+ shield = true;
+ }
+ }
+ }
+ if (shield) continue;
+
+ // Test the center of the object, which is necessary for objects
+ // that have no sphere in the center (station).
+ float dist = Math::Distance(oPos, pos)-4.0f;
+ if (dist < min)
+ best = obj;
+
+ // Test with all spheres of the object.
+ int j = 0;
+ float oRadius;
+ while (obj->GetCrashSphere(j++, oPos, oRadius))
+ {
+ if ( oPos.x+oRadius < box1.x || oPos.x-oRadius > box2.x || // outside the box?
+ oPos.y+oRadius < box1.y || oPos.y-oRadius > box2.y ||
+ oPos.z+oRadius < box1.z || oPos.z-oRadius > box2.z ) continue;
+
+ Math::Vector p = Math::Projection(old, pos, oPos);
+ float ddist = Math::Distance(p, oPos)-oRadius;
+ if (ddist < min)
+ best = obj;
+ }
+ }
+
+ return best;
}
-CObject* CParticle::SearchObjectRay(Math::Vector pos, Math::Vector goal, ParticleType type, CObject *father)
+CObject* CParticle::SearchObjectRay(Math::Vector pos, Math::Vector goal,
+ ParticleType type, CObject *father)
{
- GetLogger()->Trace("CParticle::SearchObjectRay() stub!\n");
- // TODO!
+ if (m_main->GetMovieLock()) return nullptr; // current movie?
+
+ float min = 10.0f;
+
+ Math::Vector box1 = pos;
+ Math::Vector box2 = goal;
+ if (box1.x > box2.x) Math::Swap(box1.x, box2.x); // box1 < box2
+ if (box1.y > box2.y) Math::Swap(box1.y, box2.y);
+ if (box1.z > box2.z) Math::Swap(box1.z, box2.z);
+ box1.x -= min;
+ box1.y -= min;
+ box1.z -= min;
+ box2.x += min;
+ box2.y += min;
+ box2.z += min;
+
+ for (int i = 0; i < 1000000; i++)
+ {
+ CObject* obj = static_cast<CObject*>( m_iMan->SearchInstance(CLASS_OBJECT, i) );
+ if (obj == nullptr) break;
+
+ if (!obj->GetActif()) continue; // inactive?
+ if (obj == father) continue;
+
+ ObjectType oType = obj->GetType();
+
+ if (oType == OBJECT_TOTO) continue;
+
+ if ( type == PARTIRAY1 &&
+ oType != OBJECT_MOBILEtg &&
+ oType != OBJECT_TEEN28 &&
+ oType != OBJECT_TEEN31 &&
+ oType != OBJECT_ANT &&
+ oType != OBJECT_SPIDER &&
+ oType != OBJECT_BEE &&
+ oType != OBJECT_WORM &&
+ oType != OBJECT_MOTHER &&
+ oType != OBJECT_NEST ) continue;
+
+ Math::Vector oPos = obj->GetPosition(0);
+
+ if ( oPos.x < box1.x || oPos.x > box2.x || // outside the box?
+ oPos.y < box1.y || oPos.y > box2.y ||
+ oPos.z < box1.z || oPos.z > box2.z ) continue;
+
+ Math::Vector p = Math::Projection(pos, goal, oPos);
+ float dist = Math::Distance(p, oPos);
+ if (dist < min) return obj;
+ }
+
return nullptr;
}
void CParticle::Play(Sound sound, Math::Vector pos, float amplitude)
{
- GetLogger()->Trace("CParticle::Play() stub!\n");
- // TODO!
+ if (m_sound == nullptr)
+ m_sound = static_cast<CSoundInterface*>(m_iMan->SearchInstance(CLASS_SOUND));
+
+ m_sound->Play(sound, pos, amplitude);
}
-bool CParticle::TrackMove(int i, Math::Vector pos, float progress)
+Color CParticle::GetFogColor(Math::Vector pos)
{
- GetLogger()->Trace("CParticle::TrackMove() stub!\n");
- // TODO!
- return true;
+ Color result;
+ result.r = 0.0f;
+ result.g = 0.0f;
+ result.b = 0.0f;
+ result.a = 0.0f;
+
+ for (int fog = 0; fog < m_fogTotal; fog++)
+ {
+ int i = m_fog[fog]; // i = rank of the particle
+
+ if (pos.y >= m_particle[i].pos.y+FOG_HSUP) continue;
+ if (pos.y <= m_particle[i].pos.y-FOG_HINF) continue;
+
+ float dist = Math::DistanceProjected(pos, m_particle[i].pos);
+ if (dist >= m_particle[i].dim.x*1.5f) continue;
+
+ // Calculates the horizontal distance.
+ float factor = 1.0f-powf(dist/(m_particle[i].dim.x*1.5f), 4.0f);
+
+ // Calculates the vertical distance.
+ if (pos.y > m_particle[i].pos.y)
+ factor *= 1.0f-(pos.y-m_particle[i].pos.y)/FOG_HSUP;
+ else
+ factor *= 1.0f-(m_particle[i].pos.y-pos.y)/FOG_HINF;
+
+ factor *= 0.3f;
+
+ Color color;
+
+ if ( m_particle[i].type == PARTIFOG0 ||
+ m_particle[i].type == PARTIFOG1 ) // blue?
+ {
+ color.r = 0.0f;
+ color.g = 0.5f;
+ color.b = 1.0f;
+ }
+ else if ( m_particle[i].type == PARTIFOG2 ||
+ m_particle[i].type == PARTIFOG3 ) // red?
+ {
+ color.r = 2.0f;
+ color.g = 1.0f;
+ color.b = 0.0f;
+ }
+ else if ( m_particle[i].type == PARTIFOG4 ||
+ m_particle[i].type == PARTIFOG5 ) // white?
+ {
+ color.r = 1.0f;
+ color.g = 1.0f;
+ color.b = 1.0f;
+ }
+ else if ( m_particle[i].type == PARTIFOG6 ||
+ m_particle[i].type == PARTIFOG7 ) // yellow?
+ {
+ color.r = 0.8f;
+ color.g = 1.0f;
+ color.b = 0.4f;
+ }
+ else
+ {
+ color.r = 0.0f;
+ color.g = 0.0f;
+ color.b = 0.0f;
+ }
+
+ result.r += color.r*factor;
+ result.g += color.g*factor;
+ result.b += color.b*factor;
+ }
+
+ if (result.r > 0.6f) result.r = 0.6f;
+ if (result.g > 0.6f) result.g = 0.6f;
+ if (result.b > 0.6f) result.b = 0.6f;
+
+ return result;
}
-void CParticle::TrackDraw(int i, ParticleType type)
+bool CParticle::WriteWheelTrace(const char *filename, int width, int height,
+ Math::Vector dl, Math::Vector ur)
{
- GetLogger()->Trace("CParticle::TrackDraw() stub!\n");
- // TODO!
+ // TODO: stub!
+ GetLogger()->Trace("CParticle::WriteWheelTrace(): stub!\n");
+ return true;
}
-
} // namespace Gfx
diff --git a/src/graphics/engine/particle.h b/src/graphics/engine/particle.h
index 33a5c1b..d03b3fc 100644
--- a/src/graphics/engine/particle.h
+++ b/src/graphics/engine/particle.h
@@ -17,7 +17,7 @@
/**
* \file graphics/engine/particle.h
- * \brief Particle rendering - CParticle class (aka particule)
+ * \brief Particle rendering - CParticle class (aka particle)
*/
#pragma once
@@ -46,7 +46,7 @@ const short MAXWHEELTRACE = 1000;
const short SH_WORLD = 0; // particle in the world in the interface
const short SH_FRONT = 1; // particle in the world on the interface
-const short SH_INTERFACE = 2; // particle in the interface
+const short SH_INTERFACE = 2; // particle in the interface
const short SH_MAX = 3;
// type == 0 -> triangles
@@ -58,145 +58,145 @@ const short SH_MAX = 3;
enum ParticleType
{
- PARTIEXPLOT = 1, // technology explosion
- PARTIEXPLOO = 2, // organic explosion
- PARTIMOTOR = 3, // the engine exhaust gas
- PARTIGLINT = 4, // reflection
- PARTIBLITZ = 5, // lightning recharging battery
- PARTICRASH = 6, // dust after fall
- PARTIGAS = 7, // gas from the reactor
- PARTIFIRE = 9, // fireball shrinks
- PARTIFIREZ = 10, // fireball grows
- PARTIBLUE = 11, // blue ball
- PARTISELY = 12, // yellow selection
- PARTISELR = 13, // red selection
- PARTIGUN1 = 18, // a bullet (fireball)
- PARTIGUN2 = 19, // bullet 2 (ant)
- PARTIGUN3 = 20, // bullet 3 (spider)
- PARTIGUN4 = 21, // bullet 4 (orgaball)
- PARTIFRAG = 22, // triangular fragment
- PARTIQUEUE = 23, // inflamed tail
- PARTIORGANIC1 = 24, // organic ball mother
- PARTIORGANIC2 = 25, // organic ball daughter
- PARTISMOKE1 = 26, // black smoke
- PARTISMOKE2 = 27, // black smoke
- PARTISMOKE3 = 28, // black smoke
- PARTISMOKE4 = 29, // black smoke
- PARTIBLOOD = 30, // human blood
- PARTIBLOODM = 31, // blood laying
- PARTIVAPOR = 32, // steam
- PARTIVIRUS1 = 33, // virus 1
- PARTIVIRUS2 = 34, // virus 2
- PARTIVIRUS3 = 35, // virus 3
- PARTIVIRUS4 = 36, // virus 4
- PARTIVIRUS5 = 37, // virus 5
- PARTIVIRUS6 = 38, // virus 6
- PARTIVIRUS7 = 39, // virus 7
- PARTIVIRUS8 = 40, // virus 8
- PARTIVIRUS9 = 41, // virus 9
- PARTIVIRUS10 = 42, // virus 10
- PARTIRAY1 = 43, // ray 1 (turn)
- PARTIRAY2 = 44, // ray 2 (electric arc)
- PARTIRAY3 = 45, // ray 3
- PARTIRAY4 = 46, // ray 4
- PARTIFLAME = 47, // flame
- PARTIBUBBLE = 48, // bubble
- PARTIFLIC = 49, // circles in the water
- PARTIEJECT = 50, // ejection from the reactor
- PARTISCRAPS = 51, // waste from the reactor
- PARTITOTO = 52, // reactor of tot
- PARTIERROR = 53, // toto says no
- PARTIWARNING = 54, // foo says blah
- PARTIINFO = 54, // toto says yes
- PARTIQUARTZ = 55, // reflection crystal
- PARTISPHERE0 = 56, // explosion sphere
- PARTISPHERE1 = 57, // energy sphere
- PARTISPHERE2 = 58, // analysis sphere
- PARTISPHERE3 = 59, // shield sphere
- PARTISPHERE4 = 60, // information sphere (emit)
- PARTISPHERE5 = 61, // botanical sphere (gravity root)
- PARTISPHERE6 = 62, // information sphere (receive)
- PARTISPHERE7 = 63, // sphere
- PARTISPHERE8 = 64, // sphere
- PARTISPHERE9 = 65, // sphere
- PARTIGUNDEL = 66, // bullet destroyed by shield
- PARTIPART = 67, // object part
- PARTITRACK1 = 68, // drag 1
- PARTITRACK2 = 69, // drag 2
- PARTITRACK3 = 70, // drag 3
- PARTITRACK4 = 71, // drag 4
- PARTITRACK5 = 72, // drag 5
- PARTITRACK6 = 73, // drag 6
- PARTITRACK7 = 74, // drag 7
- PARTITRACK8 = 75, // drag 8
- PARTITRACK9 = 76, // drag 9
- PARTITRACK10 = 77, // drag 10
- PARTITRACK11 = 78, // drag 11
- PARTITRACK12 = 79, // drag 12
- PARTITRACK13 = 80, // drag 13
- PARTITRACK14 = 81, // drag 14
- PARTITRACK15 = 82, // drag 15
- PARTITRACK16 = 83, // drag 16
- PARTITRACK17 = 84, // drag 17
- PARTITRACK18 = 85, // drag 18
- PARTITRACK19 = 86, // drag 19
- PARTITRACK20 = 87, // drag 20
- PARTIGLINTb = 88, // blue reflection
- PARTIGLINTr = 89, // red reflection
- PARTILENS1 = 90, // brilliance 1 (orange)
- PARTILENS2 = 91, // brilliance 2 (yellow)
- PARTILENS3 = 92, // brilliance 3 (red)
- PARTILENS4 = 93, // brilliance 4 (violet)
- PARTICONTROL = 94, // reflection on button
- PARTISHOW = 95, // shows a place
- PARTICHOC = 96, // shock wave
- PARTIGFLAT = 97, // shows if the ground is flat
- PARTIRECOVER = 98, // blue ball recycler
- PARTIROOT = 100, // gravity root smoke
- PARTIPLOUF0 = 101, // splash
- PARTIPLOUF1 = 102, // splash
- PARTIPLOUF2 = 103, // splash
- PARTIPLOUF3 = 104, // splash
- PARTIPLOUF4 = 105, // splash
- PARTIDROP = 106, // drop
- PARTIFOG0 = 107, // fog 0
- PARTIFOG1 = 108, // fog 1
- PARTIFOG2 = 109, // fog 2
- PARTIFOG3 = 110, // fog 3
- PARTIFOG4 = 111, // fog 4
- PARTIFOG5 = 112, // fog 5
- PARTIFOG6 = 113, // fog 6
- PARTIFOG7 = 114, // fog 7
- PARTIFOG8 = 115, // fog 8
- PARTIFOG9 = 116, // fog 9
- PARTILIMIT1 = 117, // shows the limits 1
- PARTILIMIT2 = 118, // shows the limits 2
- PARTILIMIT3 = 119, // shows the limits 3
- PARTILIMIT4 = 120, // shows the limits 4
- PARTIWATER = 121, // drop of water
- PARTIEXPLOG1 = 122, // ball explosion 1
- PARTIEXPLOG2 = 123, // ball explosion 2
- PARTIBASE = 124, // gases of spaceship
- PARTITRACE0 = 140, // trace
- PARTITRACE1 = 141, // trace
- PARTITRACE2 = 142, // trace
- PARTITRACE3 = 143, // trace
- PARTITRACE4 = 144, // trace
- PARTITRACE5 = 145, // trace
- PARTITRACE6 = 146, // trace
- PARTITRACE7 = 147, // trace
- PARTITRACE8 = 148, // trace
- PARTITRACE9 = 149, // trace
- PARTITRACE10 = 150, // trace
- PARTITRACE11 = 151, // trace
- PARTITRACE12 = 152, // trace
- PARTITRACE13 = 153, // trace
- PARTITRACE14 = 154, // trace
- PARTITRACE15 = 155, // trace
- PARTITRACE16 = 156, // trace
- PARTITRACE17 = 157, // trace
- PARTITRACE18 = 158, // trace
- PARTITRACE19 = 159, // trace
+ PARTIEXPLOT = 1, //! < technology explosion
+ PARTIEXPLOO = 2, //! < organic explosion
+ PARTIMOTOR = 3, //! < the engine exhaust gas
+ PARTIGLINT = 4, //! < reflection
+ PARTIBLITZ = 5, //! < lightning recharging battery
+ PARTICRASH = 6, //! < dust after fall
+ PARTIGAS = 7, //! < gas from the reactor
+ PARTIFIRE = 9, //! < fireball shrinks
+ PARTIFIREZ = 10, //! < fireball grows
+ PARTIBLUE = 11, //! < blue ball
+ PARTISELY = 12, //! < yellow selection
+ PARTISELR = 13, //! < red selection
+ PARTIGUN1 = 18, //! < a bullet (fireball)
+ PARTIGUN2 = 19, //! < bullet 2 (ant)
+ PARTIGUN3 = 20, //! < bullet 3 (spider)
+ PARTIGUN4 = 21, //! < bullet 4 (orgaball)
+ PARTIFRAG = 22, //! < triangular fragment
+ PARTIQUEUE = 23, //! < inflamed tail
+ PARTIORGANIC1 = 24, //! < organic ball mother
+ PARTIORGANIC2 = 25, //! < organic ball daughter
+ PARTISMOKE1 = 26, //! < black smoke
+ PARTISMOKE2 = 27, //! < black smoke
+ PARTISMOKE3 = 28, //! < black smoke
+ PARTISMOKE4 = 29, //! < black smoke
+ PARTIBLOOD = 30, //! < human blood
+ PARTIBLOODM = 31, //! < blood laying
+ PARTIVAPOR = 32, //! < steam
+ PARTIVIRUS1 = 33, //! < virus 1
+ PARTIVIRUS2 = 34, //! < virus 2
+ PARTIVIRUS3 = 35, //! < virus 3
+ PARTIVIRUS4 = 36, //! < virus 4
+ PARTIVIRUS5 = 37, //! < virus 5
+ PARTIVIRUS6 = 38, //! < virus 6
+ PARTIVIRUS7 = 39, //! < virus 7
+ PARTIVIRUS8 = 40, //! < virus 8
+ PARTIVIRUS9 = 41, //! < virus 9
+ PARTIVIRUS10 = 42, //! < virus 10
+ PARTIRAY1 = 43, //! < ray 1 (turn)
+ PARTIRAY2 = 44, //! < ray 2 (electric arc)
+ PARTIRAY3 = 45, //! < ray 3
+ PARTIRAY4 = 46, //! < ray 4
+ PARTIFLAME = 47, //! < flame
+ PARTIBUBBLE = 48, //! < bubble
+ PARTIFLIC = 49, //! < circles in the water
+ PARTIEJECT = 50, //! < ejection from the reactor
+ PARTISCRAPS = 51, //! < waste from the reactor
+ PARTITOTO = 52, //! < reactor of tot
+ PARTIERROR = 53, //! < toto says no
+ PARTIWARNING = 54, //! < foo says blah
+ PARTIINFO = 54, //! < toto says yes
+ PARTIQUARTZ = 55, //! < reflection crystal
+ PARTISPHERE0 = 56, //! < explosion sphere
+ PARTISPHERE1 = 57, //! < energy sphere
+ PARTISPHERE2 = 58, //! < analysis sphere
+ PARTISPHERE3 = 59, //! < shield sphere
+ PARTISPHERE4 = 60, //! < information sphere (emit)
+ PARTISPHERE5 = 61, //! < botanical sphere (gravity root)
+ PARTISPHERE6 = 62, //! < information sphere (receive)
+ PARTISPHERE7 = 63, //! < sphere
+ PARTISPHERE8 = 64, //! < sphere
+ PARTISPHERE9 = 65, //! < sphere
+ PARTIGUNDEL = 66, //! < bullet destroyed by shield
+ PARTIPART = 67, //! < object part
+ PARTITRACK1 = 68, //! < drag 1
+ PARTITRACK2 = 69, //! < drag 2
+ PARTITRACK3 = 70, //! < drag 3
+ PARTITRACK4 = 71, //! < drag 4
+ PARTITRACK5 = 72, //! < drag 5
+ PARTITRACK6 = 73, //! < drag 6
+ PARTITRACK7 = 74, //! < drag 7
+ PARTITRACK8 = 75, //! < drag 8
+ PARTITRACK9 = 76, //! < drag 9
+ PARTITRACK10 = 77, //! < drag 10
+ PARTITRACK11 = 78, //! < drag 11
+ PARTITRACK12 = 79, //! < drag 12
+ PARTITRACK13 = 80, //! < drag 13
+ PARTITRACK14 = 81, //! < drag 14
+ PARTITRACK15 = 82, //! < drag 15
+ PARTITRACK16 = 83, //! < drag 16
+ PARTITRACK17 = 84, //! < drag 17
+ PARTITRACK18 = 85, //! < drag 18
+ PARTITRACK19 = 86, //! < drag 19
+ PARTITRACK20 = 87, //! < drag 20
+ PARTIGLINTb = 88, //! < blue reflection
+ PARTIGLINTr = 89, //! < red reflection
+ PARTILENS1 = 90, //! < brilliance 1 (orange)
+ PARTILENS2 = 91, //! < brilliance 2 (yellow)
+ PARTILENS3 = 92, //! < brilliance 3 (red)
+ PARTILENS4 = 93, //! < brilliance 4 (violet)
+ PARTICONTROL = 94, //! < reflection on button
+ PARTISHOW = 95, //! < shows a place
+ PARTICHOC = 96, //! < shock wave
+ PARTIGFLAT = 97, //! < shows if the ground is flat
+ PARTIRECOVER = 98, //! < blue ball recycler
+ PARTIROOT = 100, //! < gravity root smoke
+ PARTIPLOUF0 = 101, //! < splash
+ PARTIPLOUF1 = 102, //! < splash
+ PARTIPLOUF2 = 103, //! < splash
+ PARTIPLOUF3 = 104, //! < splash
+ PARTIPLOUF4 = 105, //! < splash
+ PARTIDROP = 106, //! < drop
+ PARTIFOG0 = 107, //! < fog 0
+ PARTIFOG1 = 108, //! < fog 1
+ PARTIFOG2 = 109, //! < fog 2
+ PARTIFOG3 = 110, //! < fog 3
+ PARTIFOG4 = 111, //! < fog 4
+ PARTIFOG5 = 112, //! < fog 5
+ PARTIFOG6 = 113, //! < fog 6
+ PARTIFOG7 = 114, //! < fog 7
+ PARTIFOG8 = 115, //! < fog 8
+ PARTIFOG9 = 116, //! < fog 9
+ PARTILIMIT1 = 117, //! < shows the limits 1
+ PARTILIMIT2 = 118, //! < shows the limits 2
+ PARTILIMIT3 = 119, //! < shows the limits 3
+ PARTILIMIT4 = 120, //! < shows the limits 4
+ PARTIWATER = 121, //! < drop of water
+ PARTIEXPLOG1 = 122, //! < ball explosion 1
+ PARTIEXPLOG2 = 123, //! < ball explosion 2
+ PARTIBASE = 124, //! < gases of spaceship
+ PARTITRACE0 = 140, //! < trace
+ PARTITRACE1 = 141, //! < trace
+ PARTITRACE2 = 142, //! < trace
+ PARTITRACE3 = 143, //! < trace
+ PARTITRACE4 = 144, //! < trace
+ PARTITRACE5 = 145, //! < trace
+ PARTITRACE6 = 146, //! < trace
+ PARTITRACE7 = 147, //! < trace
+ PARTITRACE8 = 148, //! < trace
+ PARTITRACE9 = 149, //! < trace
+ PARTITRACE10 = 150, //! < trace
+ PARTITRACE11 = 151, //! < trace
+ PARTITRACE12 = 152, //! < trace
+ PARTITRACE13 = 153, //! < trace
+ PARTITRACE14 = 154, //! < trace
+ PARTITRACE15 = 155, //! < trace
+ PARTITRACE16 = 156, //! < trace
+ PARTITRACE17 = 157, //! < trace
+ PARTITRACE18 = 158, //! < trace
+ PARTITRACE19 = 159, //! < trace
};
enum ParticlePhase
@@ -262,7 +262,7 @@ struct WheelTrace
* \class CParticle
* \brief Particle engine
*
- * Functions are only stubs for now.
+ * TODO: documentation
*/
class CParticle
{
@@ -270,28 +270,49 @@ public:
CParticle(CInstanceManager* iMan, CEngine* engine);
~CParticle();
+ //! Sets the device to use
void SetDevice(CDevice* device);
+ //! Removes all particles
void FlushParticle();
+
+ //! Removes all particles of a sheet
void FlushParticle(int sheet);
+
+ //! Creates a new particle
int CreateParticle(Math::Vector pos, Math::Vector speed, Math::Point dim,
- ParticleType type, float duration=1.0f, float mass=0.0f,
- float windSensitivity=1.0f, int sheet=0);
- int CreateFrag(Math::Vector pos, Math::Vector speed, EngineTriangle *triangle,
- ParticleType type, float duration=1.0f, float mass=0.0f,
- float windSensitivity=1.0f, int sheet=0);
+ ParticleType type, float duration = 1.0f, float mass = 0.0f,
+ float windSensitivity = 1.0f, int sheet = 0);
+
+ //! Creates a new triangular particle (debris)
+ int CreateFrag(Math::Vector pos, Math::Vector speed, EngineTriangle* triangle,
+ ParticleType type, float duration = 1.0f, float mass = 0.0f,
+ float windSensitivity = 1.0f, int sheet = 0);
+
+ //! Creates a new particle being a part of object
int CreatePart(Math::Vector pos, Math::Vector speed, ParticleType type,
- float duration=1.0f, float mass=0.0f, float weight=0.0f,
- float windSensitivity=1.0f, int sheet=0);
+ float duration = 1.0f, float mass = 0.0f, float weight = 0.0f,
+ float windSensitivity = 1.0f, int sheet = 0);
+
+ //! Creates a new linear particle (radius)
int CreateRay(Math::Vector pos, Math::Vector goal, ParticleType type, Math::Point dim,
- float duration=1.0f, int sheet=0);
+ float duration = 1.0f, int sheet = 0);
+
+ //! Creates a particle with a trail
int CreateTrack(Math::Vector pos, Math::Vector speed, Math::Point dim, ParticleType type,
- float duration=1.0f, float mass=0.0f, float length=10.0f, float width=1.0f);
+ float duration = 1.0f, float mass = 0.0f, float length = 10.0f, float width = 1.0f);
+
+ //! Creates a tire mark
void CreateWheelTrace(const Math::Vector &p1, const Math::Vector &p2, const Math::Vector &p3,
const Math::Vector &p4, ParticleType type);
+
+ //! Removes all particles of a given type
void DeleteParticle(ParticleType type);
+ //! Removes all particles of a given channel
void DeleteParticle(int channel);
+ //! Specifies the object to which the particle is bound
void SetObjectLink(int channel, CObject *object);
+ //! Specifies the parent object that created the particle
void SetObjectFather(int channel, CObject *object);
void SetPosition(int channel, Math::Vector pos);
void SetDimension(int channel, Math::Point dim);
@@ -300,31 +321,53 @@ public:
void SetIntensity(int channel, float intensity);
void SetParam(int channel, Math::Vector pos, Math::Point dim, float zoom, float angle, float intensity);
void SetPhase(int channel, ParticlePhase phase, float duration);
+
+ //! Returns the position of the particle
bool GetPosition(int channel, Math::Vector &pos);
- Color GetFogColor(Math::Vector pos);
+ //! Returns the color if you're in the fog or black if you're not
+ Color GetFogColor(Math::Vector pos);
+ //! Indicates whether a sheet is updated or not
void SetFrameUpdate(int sheet, bool update);
+ //! Updates all the particles.
void FrameParticle(float rTime);
+ //! Draws all the particles
void DrawParticle(int sheet);
+ //! Writes a file containing all the tire tracks
bool WriteWheelTrace(const char *filename, int width, int height, Math::Vector dl, Math::Vector ur);
protected:
+ //! Removes a particle of given rank
void DeleteRank(int rank);
+ //! Check a channel number
bool CheckChannel(int &channel);
+ //! Draws a triangular particle
void DrawParticleTriangle(int i);
+ //! Draw a normal particle
void DrawParticleNorm(int i);
+ //! Draw a particle flat (horizontal)
void DrawParticleFlat(int i);
+ //! Draw a particle to a flat sheet of fog
void DrawParticleFog(int i);
+ //! Draw a particle in the form of radius
void DrawParticleRay(int i);
+ //! Draws a spherical particle
void DrawParticleSphere(int i);
+ //! Draws a cylindrical particle
void DrawParticleCylinder(int i);
+ //! Draws a tire mark
void DrawParticleWheel(int i);
+ //! Seeks if an object collided with a bullet
CObject* SearchObjectGun(Math::Vector old, Math::Vector pos, ParticleType type, CObject *father);
+ //! Seeks if an object collided with a ray
CObject* SearchObjectRay(Math::Vector pos, Math::Vector goal, ParticleType type, CObject *father);
+ //! Sounded one
void Play(Sound sound, Math::Vector pos, float amplitude);
+ //! Moves a drag; returns true if the drag is finished
bool TrackMove(int i, Math::Vector pos, float progress);
+ //! Draws a drag
void TrackDraw(int i, ParticleType type);
protected:
@@ -336,12 +379,12 @@ protected:
CRobotMain* m_main;
CSoundInterface* m_sound;
- Particle m_particule[MAXPARTICULE*MAXPARTITYPE];
+ Particle m_particle[MAXPARTICULE*MAXPARTITYPE];
EngineTriangle m_triangle[MAXPARTICULE]; // triangle if PartiType == 0
- Track m_track[MAXTRACK];
+ Track m_track[MAXTRACK];
int m_wheelTraceTotal;
int m_wheelTraceIndex;
- WheelTrace m_wheelTrace[MAXWHEELTRACE];
+ WheelTrace m_wheelTrace[MAXWHEELTRACE];
int m_totalInterface[MAXPARTITYPE][SH_MAX];
bool m_frameUpdate[SH_MAX];
int m_fogTotal;
diff --git a/src/graphics/engine/pyro.cpp b/src/graphics/engine/pyro.cpp
index 04568ae..978471b 100644
--- a/src/graphics/engine/pyro.cpp
+++ b/src/graphics/engine/pyro.cpp
@@ -20,6 +20,17 @@
#include "common/logger.h"
+#include "graphics/engine/lightman.h"
+#include "graphics/engine/particle.h"
+#include "graphics/engine/terrain.h"
+
+#include "math/geometry.h"
+
+#include "object/robotmain.h"
+#include "object/motion/motionhuman.h"
+
+#include "ui/displaytext.h"
+
// Graphics module namespace
namespace Gfx {
@@ -27,158 +38,2350 @@ namespace Gfx {
CPyro::CPyro(CInstanceManager* iMan)
{
- GetLogger()->Trace("CParticle::CPyro() stub!\n");
- // TODO!
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_PYRO, this, 100);
+
+ m_engine = static_cast<CEngine*>(m_iMan->SearchInstance(CLASS_ENGINE));
+ m_terrain = static_cast<CTerrain*>(m_iMan->SearchInstance(CLASS_TERRAIN));
+ m_camera = static_cast<CCamera*>(m_iMan->SearchInstance(CLASS_CAMERA));
+ m_particle = static_cast<CParticle*>(m_iMan->SearchInstance(CLASS_PARTICULE));
+ m_lightMan = static_cast<CLightManager*>(m_iMan->SearchInstance(CLASS_LIGHT));
+ m_displayText = static_cast<Ui::CDisplayText*>(m_iMan->SearchInstance(CLASS_DISPLAYTEXT));
+ m_main = static_cast<CRobotMain*>(m_iMan->SearchInstance(CLASS_MAIN));
+ m_sound = static_cast<CSoundInterface*>(m_iMan->SearchInstance(CLASS_SOUND));
+ m_object = 0;
+
+ m_progress = 0.0f;
+ m_speed = 0.0f;
+ m_lightRank = -1;
+ m_soundChannel = -1;
+ LightOperFlush();
}
CPyro::~CPyro()
{
- GetLogger()->Trace("CPyro::~CPyro() stub!");
- // TODO!
+ m_iMan->DeleteInstance(CLASS_PYRO, this);
}
-void CPyro::DeleteObject(bool all)
+void CPyro::DeleteObject()
{
- GetLogger()->Trace("CPyro::DeleteObject() stub!");
- // TODO!
+ if ( m_lightRank != -1 )
+ {
+ m_lightMan->DeleteLight(m_lightRank);
+ m_lightRank = -1;
+ }
}
-bool CPyro::Create(PyroType type, CObject* pObj, float force)
+bool CPyro::Create(PyroType type, CObject* obj, float force)
{
- GetLogger()->Trace("CPyro::Create() stub!");
- // TODO!
+ m_object = obj;
+ m_force = force;
+
+ ObjectType oType = obj->GetType();
+ int objRank = obj->GetObjectRank(0);
+ if (objRank == -1) return false;
+
+ Math::Vector min, max;
+ m_engine->GetObjectBBox(objRank, min, max);
+ Math::Vector pos = obj->GetPosition(0);
+
+ DisplayError(type, obj); // displays eventual messages
+
+ int i = 0;
+ // Copies all spheres of the object.
+ for (; i < 50; i++)
+ {
+ if ( !obj->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_lastParticle = 0.0f;
+ m_lastParticleSmoke = 0.0f;
+ m_lightRank = -1;
+
+ if ( oType == OBJECT_TEEN28 ||
+ oType == OBJECT_TEEN31 )
+ {
+ m_pos.y = pos.y+1.0f;
+ }
+
+ // Seeking the position of the battery.
+ CObject* power = obj->GetPower();
+ if ( power == nullptr )
+ {
+ m_power = false;
+ }
+ else
+ {
+ m_power = true;
+ pos = power->GetPosition(0);
+ pos.y += 1.0f;
+ Math::Matrix* mat = obj->GetWorldMatrix(0);
+ m_posPower = Math::Transform(*mat, pos);
+ }
+ if ( oType == OBJECT_POWER ||
+ oType == OBJECT_ATOMIC ||
+ oType == OBJECT_URANIUM ||
+ oType == OBJECT_TNT ||
+ oType == OBJECT_BOMB )
+ {
+ m_power = true;
+ m_posPower = m_pos;
+ m_posPower.y += 1.0f;
+ m_pos = m_posPower;
+ }
+ if ( oType == OBJECT_STATION )
+ {
+ m_power = true;
+ Math::Matrix* mat = obj->GetWorldMatrix(0);
+ m_posPower = Math::Transform(*mat, Math::Vector(-15.0f, 7.0f, 0.0f));
+ m_pos = m_posPower;
+ }
+ if ( oType == OBJECT_ENERGY )
+ {
+ m_power = true;
+ Math::Matrix* mat = obj->GetWorldMatrix(0);
+ m_posPower = Math::Transform(*mat, Math::Vector(-7.0f, 6.0f, 0.0f));
+ m_pos = m_posPower;
+ }
+ if ( oType == OBJECT_NUCLEAR )
+ {
+ m_power = true;
+ m_posPower = m_pos;
+ }
+ if ( oType == OBJECT_PARA )
+ {
+ m_power = true;
+ m_posPower = m_pos;
+ }
+ if ( oType == OBJECT_SCRAP4 ||
+ oType == OBJECT_SCRAP5 ) // plastic material?
+ {
+ m_power = true;
+ m_posPower = m_pos;
+ }
+
+ // Plays the sound of a pyrotechnic effect.
+ if ( type == PT_FRAGT ||
+ type == PT_FRAGW ||
+ type == PT_EXPLOT ||
+ type == PT_EXPLOW )
+ {
+ Sound sound;
+ if ( m_power )
+ {
+ sound = SOUND_EXPLOp;
+ }
+ else
+ {
+ sound = SOUND_EXPLO;
+ }
+ if ( oType == OBJECT_STONE ||
+ oType == OBJECT_METAL ||
+ oType == OBJECT_BULLET ||
+ oType == OBJECT_BBOX ||
+ oType == OBJECT_KEYa ||
+ oType == OBJECT_KEYb ||
+ oType == OBJECT_KEYc ||
+ oType == OBJECT_KEYd )
+ {
+ sound = SOUND_EXPLOl;
+ }
+ if ( oType == OBJECT_URANIUM ||
+ oType == OBJECT_POWER ||
+ oType == OBJECT_ATOMIC ||
+ oType == OBJECT_TNT ||
+ oType == OBJECT_BOMB )
+ {
+ sound = SOUND_EXPLOlp;
+ }
+ m_sound->Play(sound, m_pos);
+ }
+ if ( 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->GetEyePt());
+ }
+ if ( type == PT_EGG )
+ {
+ m_sound->Play(SOUND_EGG, m_pos);
+ }
+ if ( type == PT_WPCHECK ||
+ type == PT_FLCREATE ||
+ type == PT_FLDELETE )
+ {
+ m_sound->Play(SOUND_WAYPOINT, m_pos);
+ }
+ if ( oType == OBJECT_HUMAN )
+ {
+ if ( type == PT_DEADG )
+ {
+ m_sound->Play(SOUND_DEADg, m_pos);
+ }
+ if ( type == PT_DEADW )
+ {
+ m_sound->Play(SOUND_DEADw, m_pos);
+ }
+ if ( type == PT_SHOTH && m_object->GetSelect() )
+ {
+ m_sound->Play(SOUND_AIE, m_pos);
+ m_sound->Play(SOUND_AIE, m_engine->GetEyePt());
+ }
+ }
+
+ if ( m_type == PT_FRAGT ||
+ m_type == PT_FRAGO ||
+ m_type == PT_FRAGW )
+ {
+ m_engine->DeleteShadow(m_object->GetObjectRank(0));
+ }
+
+ if ( m_type == PT_DEADG )
+ {
+ m_object->SetDead(true);
+
+ CMotion* motion = m_object->GetMotion();
+ if (motion != nullptr)
+ motion->SetAction(MHS_DEADg, 1.0f);
+
+ m_camera->StartCentering(m_object, Math::PI*0.5f, 99.9f, 0.0f, 1.5f);
+ m_camera->StartOver(CAM_OVER_EFFECT_FADEOUT_WHITE, m_pos, 1.0f);
+ m_speed = 1.0f/10.0f;
+ return true;
+ }
+ if ( m_type == PT_DEADW )
+ {
+ m_object->SetDead(true);
+
+ CMotion* motion = m_object->GetMotion();
+ if ( motion != nullptr )
+ {
+ motion->SetAction(MHS_DEADw, 4.0f);
+ }
+ m_camera->StartCentering(m_object, Math::PI*0.5f, 99.9f, 0.0f, 3.0f);
+ m_camera->StartOver(CAM_OVER_EFFECT_FADEOUT_BLACK, m_pos, 1.0f);
+ m_speed = 1.0f/10.0f;
+ return true;
+ }
+
+ if ( m_type == PT_SHOTT ||
+ m_type == PT_SHOTM )
+ {
+ m_camera->StartEffect(CAM_EFFECT_SHOT, m_pos, force);
+ m_speed = 1.0f/1.0f;
+ return true;
+ }
+ if ( m_type == PT_SHOTH )
+ {
+ if ( m_object->GetSelect() )
+ {
+ m_camera->StartOver(CAM_OVER_EFFECT_BLOOD, m_pos, force);
+ }
+ m_speed = 1.0f/0.2f;
+ return true;
+ }
+
+ if ( m_type == PT_SHOTW )
+ {
+ m_speed = 1.0f/1.0f;
+ }
+
+ if ( m_type == PT_BURNT )
+ {
+ BurnStart();
+ }
+
+ if ( m_type == PT_WPCHECK )
+ {
+ m_speed = 1.0f/8.0f;
+ m_object->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->GetResetPosition());
+ m_object->SetAngle(0, m_object->GetResetAngle());
+ m_object->SetZoom(0, 0.0f);
+ }
+ if ( m_type == PT_FINDING )
+ {
+ float limit = (m_size-1.0f)/4.0f;
+ if (limit > 8.0f) limit = 8.0f;
+ if (oType == OBJECT_APOLLO2) limit = 2.0f;
+ m_speed = 1.0f/limit;
+ }
+
+ if ( m_type == PT_EXPLOT ||
+ m_type == PT_EXPLOO ||
+ m_type == PT_EXPLOW )
+ {
+ CreateTriangle(obj, oType, 0);
+ m_engine->DeleteShadow(m_object->GetObjectRank(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);
+ Math::Matrix* mat = obj->GetWorldMatrix(0);
+ m_pos = Math::Transform(*mat, pos);
+
+ m_engine->DeleteShadow(m_object->GetObjectRank(0));
+ }
+
+ if ( m_type != PT_EGG &&
+ m_type != PT_WIN &&
+ m_type != PT_LOST )
+ {
+ float h = 40.0f;
+ if ( m_type == PT_FRAGO ||
+ m_type == PT_EXPLOO )
+ {
+ LightOperAdd(0.00f, 0.0f, -1.0f, -0.5f, -1.0f); // dark green
+ LightOperAdd(0.05f, 1.0f, -1.0f, -0.5f, -1.0f); // dark green
+ LightOperAdd(1.00f, 0.0f, -1.0f, -0.5f, -1.0f); // dark green
+ }
+ else if ( m_type == PT_FRAGT ||
+ m_type == PT_EXPLOT )
+ {
+ LightOperAdd(0.00f, 1.0f, 4.0f, 4.0f, 2.0f); // yellow
+ LightOperAdd(0.02f, 1.0f, 4.0f, 2.0f, 0.0f); // red-orange
+ LightOperAdd(0.16f, 1.0f, -0.8f, -0.8f, -0.8f); // dark gray
+ LightOperAdd(1.00f, 0.0f, -0.8f, -0.8f, -0.8f); // dark gray
+ h = m_size*2.0f;
+ }
+ else if ( m_type == PT_SPIDER )
+ {
+ LightOperAdd(0.00f, 0.0f, -0.5f, -1.0f, -1.0f); // dark red
+ LightOperAdd(0.05f, 1.0f, -0.5f, -1.0f, -1.0f); // dark red
+ LightOperAdd(1.00f, 0.0f, -0.5f, -1.0f, -1.0f); // dark red
+ }
+ else if ( m_type == PT_FRAGW ||
+ m_type == PT_EXPLOW ||
+ m_type == PT_SHOTW )
+ {
+ LightOperAdd(0.00f, 0.0f, -0.5f, -0.5f, -1.0f); // dark yellow
+ LightOperAdd(0.05f, 1.0f, -0.5f, -0.5f, -1.0f); // dark yellow
+ LightOperAdd(1.00f, 0.0f, -0.5f, -0.5f, -1.0f); // dark yellow
+ }
+ else if ( m_type == PT_WPCHECK ||
+ m_type == PT_FLCREATE ||
+ m_type == PT_FLDELETE ||
+ m_type == PT_RESET ||
+ m_type == PT_FINDING )
+ {
+ LightOperAdd(0.00f, 1.0f, 4.0f, 4.0f, 2.0f); // yellow
+ LightOperAdd(1.00f, 0.0f, 4.0f, 4.0f, 2.0f); // yellow
+ }
+ else
+ {
+ LightOperAdd(0.00f, 0.0f, -0.8f, -0.8f, -0.8f); // dark gray
+ LightOperAdd(0.05f, 1.0f, -0.8f, -0.8f, -0.8f); // dark gray
+ LightOperAdd(1.00f, 0.0f, -0.8f, -0.8f, -0.8f); // dark gray
+ }
+ CreateLight(m_pos, h);
+
+ if ( m_type != PT_SHOTW &&
+ m_type != PT_WPCHECK &&
+ m_type != PT_FLCREATE &&
+ m_type != PT_FLDELETE &&
+ m_type != PT_RESET &&
+ m_type != PT_FINDING )
+ {
+ m_camera->StartEffect(CAM_EFFECT_EXPLO, m_pos, force);
+ }
+ }
+
+ if ( m_type == PT_SHOTW ) return true;
+
+ // Generates the triangles of the explosion.
+ if ( m_type == PT_FRAGT ||
+ m_type == PT_FRAGO ||
+ m_type == PT_FRAGW ||
+ 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 (int part = 0; part < OBJECTMAXPART; part++)
+ {
+ CreateTriangle(obj, oType, part);
+ }
+ }
+
+ if ( m_type == PT_FRAGT ||
+ m_type == PT_EXPLOT )
+ {
+ if ( m_power )
+ {
+ int total = static_cast<int>(10.0f*m_engine->GetParticleDensity());
+ if ( oType == OBJECT_TNT ||
+ oType == OBJECT_BOMB ) total *= 3;
+ for (int i = 0; i < total; i++)
+ {
+ pos = m_posPower;
+ Math::Vector speed;
+ speed.x = (Math::Rand()-0.5f)*30.0f;
+ speed.z = (Math::Rand()-0.5f)*30.0f;
+ speed.y = Math::Rand()*30.0f;
+ Math::Point dim;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ float duration = Math::Rand()*3.0f+2.0f;
+ float mass = Math::Rand()*10.0f+15.0f;
+ m_particle->CreateTrack(pos, speed, dim, PARTITRACK1,
+ duration, mass, Math::Rand()+0.7f, 1.0f);
+ }
+ }
+
+ if (m_size > 10.0f) // large enough (freight excluded)?
+ {
+ if (m_power)
+ {
+ pos = m_posPower;
+ }
+ else
+ {
+ pos = m_pos;
+ m_terrain->AdjustToFloor(pos);
+ pos.y += 1.0f;
+ }
+ Math::Point dim;
+ dim.x = m_size*0.4f;
+ dim.y = dim.x;
+ m_particle->CreateParticle(pos, Math::Vector(0.0f,0.0f,0.0f), dim, PARTISPHERE0, 2.0f, 0.0f, 0.0f);
+ }
+ }
+
+ if ( m_type == PT_FRAGO ||
+ m_type == PT_EXPLOO )
+ {
+ int total = static_cast<int>(10.0f*m_engine->GetParticleDensity());
+ for (int i = 0; i < total; i++)
+ {
+ pos = m_pos;
+ Math::Vector speed;
+ speed.x = (Math::Rand()-0.5f)*30.0f;
+ speed.z = (Math::Rand()-0.5f)*30.0f;
+ speed.y = Math::Rand()*50.0f;
+ Math::Point dim;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ float duration = Math::Rand()*1.0f+0.8f;
+ float mass = Math::Rand()*10.0f+15.0f;
+ m_particle->CreateParticle(pos, speed, dim, PARTIORGANIC1,
+ duration, mass);
+ }
+ total = static_cast<int>(5.0f*m_engine->GetParticleDensity());
+ for (int i = 0; i < total; i++)
+ {
+ pos = m_pos;
+ Math::Vector speed;
+ speed.x = (Math::Rand()-0.5f)*30.0f;
+ speed.z = (Math::Rand()-0.5f)*30.0f;
+ speed.y = Math::Rand()*50.0f;
+ Math::Point dim;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ float duration = Math::Rand()*2.0f+1.4f;
+ float mass = Math::Rand()*10.0f+15.0f;
+ m_particle->CreateTrack(pos, speed, dim, PARTITRACK4,
+ duration, mass, duration*0.5f, dim.x*2.0f);
+ }
+ }
+
+ if ( m_type == PT_SPIDER )
+ {
+ for (int i = 0; i < 50; i++)
+ {
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*3.0f;
+ pos.z += (Math::Rand()-0.5f)*3.0f;
+ pos.y += (Math::Rand()-0.5f)*2.0f;
+ Math::Vector speed;
+ speed.x = (Math::Rand()-0.5f)*24.0f;
+ speed.z = (Math::Rand()-0.5f)*24.0f;
+ speed.y = 10.0f+Math::Rand()*10.0f;
+ Math::Point dim;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ int channel = m_particle->CreateParticle(pos, speed, dim, PARTIGUN3, 2.0f+Math::Rand()*2.0f, 10.0f);
+ m_particle->SetObjectFather(channel, obj);
+ }
+ int total = static_cast<int>(10.0f*m_engine->GetParticleDensity());
+ for (int i = 0; i < total; i++)
+ {
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*3.0f;
+ pos.z += (Math::Rand()-0.5f)*3.0f;
+ pos.y += (Math::Rand()-0.5f)*2.0f;
+ Math::Vector speed;
+ speed.x = (Math::Rand()-0.5f)*24.0f;
+ speed.z = (Math::Rand()-0.5f)*24.0f;
+ speed.y = 7.0f+Math::Rand()*7.0f;
+ Math::Point dim;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ m_particle->CreateTrack(pos, speed, dim, PARTITRACK3,
+ 2.0f+Math::Rand()*2.0f, 10.0f, 2.0f, 0.6f);
+ }
+ }
+
+ if ( type == PT_FRAGT ||
+ type == PT_FRAGW ||
+ type == PT_EXPLOT ||
+ type == PT_EXPLOW )
+ {
+ if (m_size > 10.0f || m_power)
+ {
+ pos = m_pos;
+ Math::Vector speed(0.0f, 0.0f, 0.0f);
+ Math::Point dim;
+ dim.x = m_size;
+ dim.y = dim.x;
+ m_particle->CreateParticle(pos, speed, dim, PARTICHOC, 2.0f);
+ }
+ }
+
return true;
}
bool CPyro::EventProcess(const Event &event)
{
- GetLogger()->Trace("CPyro::EventProcess() stub!\n");
- // TODO!
+ if (event.type != EVENT_FRAME) return true;
+ if (m_engine->GetPause()) return true;
+
+ m_time += event.rTime;
+ m_progress += event.rTime*m_speed;
+
+ if (m_soundChannel != -1 && m_object != 0)
+ {
+ Math::Vector pos = m_object->GetPosition(0);
+ m_sound->Position(m_soundChannel, pos);
+
+ if (m_lightRank != -1)
+ {
+ pos.y += m_lightHeight;
+ m_lightMan->SetLightPos(m_lightRank, pos);
+ }
+ }
+
+ if ( m_type == PT_SHOTT &&
+ m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticle = m_time;
+
+ if ( m_crashSphereUsed > 0 )
+ {
+ int i = rand()%m_crashSphereUsed;
+ Math::Vector 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;
+ Math::Vector speed;
+ 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;
+ Math::Point dim;
+ dim.x = Math::Rand()*m_crashSphereRadius[i]*0.5f+m_crashSphereRadius[i]*0.75f*m_force;
+ dim.y = dim.x;
+ m_particle->CreateParticle(pos, speed, dim, PARTISMOKE1, 3.0f);
+ }
+ else
+ {
+ Math::Vector pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*m_size*0.3f;
+ pos.z += (Math::Rand()-0.5f)*m_size*0.3f;
+ Math::Vector speed;
+ speed.x = (Math::Rand()-0.5f)*m_size*0.1f;
+ speed.z = (Math::Rand()-0.5f)*m_size*0.1f;
+ speed.y = Math::Rand()*m_size*0.2f;
+ Math::Point dim;
+ dim.x = Math::Rand()*m_size/10.0f+m_size/10.0f*m_force;
+ dim.y = dim.x;
+ m_particle->CreateParticle(pos, speed, dim, PARTISMOKE1, 3.0f);
+ }
+ }
+
+ if ( m_type == PT_SHOTH &&
+ m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticle = m_time;
+
+ for (int i = 0; i < 10; i++)
+ {
+ Math::Vector pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*m_size*0.2f;
+ pos.z += (Math::Rand()-0.5f)*m_size*0.2f;
+ pos.y += (Math::Rand()-0.5f)*m_size*0.5f;
+ Math::Vector speed;
+ speed.x = (Math::Rand()-0.5f)*5.0f;
+ speed.z = (Math::Rand()-0.5f)*5.0f;
+ speed.y = Math::Rand()*1.0f;
+ Math::Point dim;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ m_particle->CreateParticle(pos, speed, dim, PARTIBLOOD, Math::Rand()*3.0f+3.0f, Math::Rand()*10.0f+15.0f, 0.5f);
+ }
+ }
+
+ if ( m_type == PT_SHOTM &&
+ m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticle = m_time;
+
+ int r = static_cast<int>(10.0f*m_engine->GetParticleDensity());
+ for (int i = 0; i < r; i++)
+ {
+ Math::Vector pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*20.0f;
+ pos.z += (Math::Rand()-0.5f)*20.0f;
+ pos.y += 8.0f;
+ Math::Vector speed;
+ speed.x = (Math::Rand()-0.5f)*40.0f;
+ speed.z = (Math::Rand()-0.5f)*40.0f;
+ speed.y = Math::Rand()*40.0f;
+ Math::Point dim;
+ dim.x = Math::Rand()*8.0f+8.0f*m_force;
+ dim.y = dim.x;
+
+ m_particle->CreateParticle(pos, speed, dim, PARTIBLOODM, 2.0f, 50.0f, 0.0f);
+ }
+ }
+
+ if ( m_type == PT_SHOTW &&
+ m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticle = m_time;
+
+ if ( m_crashSphereUsed > 0 )
+ {
+ int i = rand()%m_crashSphereUsed;
+ Math::Vector 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;
+ Math::Vector speed;
+ 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;
+ Math::Point dim;
+ dim.x = 1.0f*m_force;
+ dim.y = dim.x;
+ m_particle->CreateParticle(pos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f);
+ }
+ else
+ {
+ Math::Vector pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*m_size*0.3f;
+ pos.z += (Math::Rand()-0.5f)*m_size*0.3f;
+ Math::Vector speed;
+ speed.x = (Math::Rand()-0.5f)*m_size*0.1f;
+ speed.z = (Math::Rand()-0.5f)*m_size*0.1f;
+ speed.y = Math::Rand()*m_size*0.2f;
+ Math::Point dim;
+ dim.x = 1.0f*m_force;
+ dim.y = dim.x;
+ m_particle->CreateParticle(pos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f);
+ }
+ }
+
+ if ( m_type == PT_SHOTW &&
+ m_lastParticleSmoke+m_engine->ParticleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticleSmoke = m_time;
+
+ Math::Vector pos = m_pos;
+ pos.y -= 2.0f;
+ pos.x += (Math::Rand()-0.5f)*4.0f;
+ pos.z += (Math::Rand()-0.5f)*4.0f;
+ Math::Vector speed;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 10.0f+Math::Rand()*10.0f;
+ Math::Point dim;
+ dim.x = Math::Rand()*2.5f+2.0f*m_force;
+ dim.y = dim.x;
+ m_particle->CreateParticle(pos, speed, dim, PARTICRASH, 4.0f);
+ }
+
+ if ( (m_type == PT_FRAGT || m_type == PT_EXPLOT) &&
+ m_progress < 0.05f &&
+ m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticle = m_time;
+
+ Math::Vector pos = m_pos;
+ Math::Vector speed;
+ speed.x = (Math::Rand()-0.5f)*m_size*1.0f;
+ speed.z = (Math::Rand()-0.5f)*m_size*1.0f;
+ speed.y = Math::Rand()*m_size*0.50f;
+ Math::Point dim;
+ dim.x = Math::Rand()*m_size/5.0f+m_size/5.0f;
+ dim.y = dim.x;
+
+ m_particle->CreateParticle(pos, speed, dim, PARTIEXPLOT);
+ }
+
+ if ( (m_type == PT_FRAGT || m_type == PT_EXPLOT) &&
+ m_progress < 0.10f &&
+ m_lastParticleSmoke+m_engine->ParticleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticleSmoke = m_time;
+
+ Math::Point dim;
+ dim.x = Math::Rand()*m_size/3.0f+m_size/3.0f;
+ dim.y = dim.x;
+ Math::Vector pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*m_size*0.5f;
+ pos.z += (Math::Rand()-0.5f)*m_size*0.5f;
+ m_terrain->AdjustToFloor(pos);
+ Math::Vector speed;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = -dim.x/2.0f/4.0f;
+ pos.y += dim.x/2.0f;
+
+ ParticleType type;
+ int r = rand()%2;
+ if (r == 0) type = PARTISMOKE1;
+ if (r == 1) type = PARTISMOKE2;
+ m_particle->CreateParticle(pos, speed, dim, type, 6.0f);
+ }
+
+ if ( (m_type == PT_FRAGO || m_type == PT_EXPLOO) &&
+ m_progress < 0.03f &&
+ m_lastParticle+m_engine->ParticleAdapt(0.1f) <= m_time )
+ {
+ m_lastParticle = m_time;
+
+ Math::Vector pos = m_pos;
+ Math::Vector speed;
+ speed.x = (Math::Rand()-0.5f)*m_size*2.0f;
+ speed.z = (Math::Rand()-0.5f)*m_size*2.0f;
+ speed.y = Math::Rand()*m_size*1.0f;
+ Math::Point dim;
+ dim.x = Math::Rand()*m_size/2.0f+m_size/2.0f;
+ dim.y = dim.x;
+
+ m_particle->CreateParticle(pos, speed, dim, PARTIEXPLOO);
+ }
+
+ if ( (m_type == PT_FRAGW || m_type == PT_EXPLOW) &&
+ m_progress < 0.05f &&
+ m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticle = m_time;
+
+ Math::Vector pos = m_pos;
+ Math::Vector speed;
+ speed.x = (Math::Rand()-0.5f)*m_size*1.0f;
+ speed.z = (Math::Rand()-0.5f)*m_size*1.0f;
+ speed.y = Math::Rand()*m_size*0.50f;
+ Math::Point dim;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+
+ m_particle->CreateParticle(pos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f);
+ }
+
+ if ( (m_type == PT_FRAGW || m_type == PT_EXPLOW) &&
+ m_progress < 0.25f &&
+ m_lastParticleSmoke+m_engine->ParticleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticleSmoke = m_time;
+
+ Math::Vector pos = m_pos;
+ pos.y -= 2.0f;
+ pos.x += (Math::Rand()-0.5f)*4.0f;
+ pos.z += (Math::Rand()-0.5f)*4.0f;
+ Math::Vector speed;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 4.0f+Math::Rand()*4.0f;
+ Math::Point dim;
+ dim.x = Math::Rand()*2.5f+2.0f;
+ dim.y = dim.x;
+ m_particle->CreateParticle(pos, speed, dim, PARTICRASH, 4.0f);
+ }
+
+ if ( m_type == PT_WPCHECK )
+ {
+ float factor;
+ if (m_progress < 0.25f)
+ factor = 0.0f;
+ else
+ factor = powf((m_progress-0.25f)/0.75f, 2.0f)*30.0f;
+
+ if ( m_progress < 0.85f &&
+ m_lastParticle+m_engine->ParticleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticle = m_time;
+
+ Math::Vector pos = m_pos;
+ pos.y += factor;
+ pos.x += (Math::Rand()-0.5f)*3.0f;
+ pos.z += (Math::Rand()-0.5f)*3.0f;
+ Math::Vector speed;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 5.0f+Math::Rand()*5.0f;
+ Math::Point dim;
+ dim.x = Math::Rand()*1.5f+1.5f;
+ dim.y = dim.x;
+ m_particle->CreateParticle(pos, speed, dim, PARTIGLINT, 2.0f);
+ }
+
+ Math::Vector angle = m_object->GetAngle(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);
+
+ Math::Vector 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_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticle = m_time;
+
+ Math::Vector pos = m_pos;
+ m_terrain->AdjustToFloor(pos);
+ pos.x += (Math::Rand()-0.5f)*1.0f;
+ pos.z += (Math::Rand()-0.5f)*1.0f;
+ Math::Vector speed;
+ speed.x = (Math::Rand()-0.5f)*2.0f;
+ speed.z = (Math::Rand()-0.5f)*2.0f;
+ speed.y = 2.0f+Math::Rand()*2.0f;
+ Math::Point dim;
+ dim.x = (Math::Rand()*1.0f+1.0f)*(0.2f+m_progress*0.8f);
+ dim.y = dim.x;
+ m_particle->CreateParticle(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.0f);
+ }
+
+ Math::Vector angle = m_object->GetAngle(0);
+ 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_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticle = m_time;
+
+ Math::Vector pos = m_pos;
+ m_terrain->AdjustToFloor(pos);
+ pos.x += (Math::Rand()-0.5f)*1.0f;
+ pos.z += (Math::Rand()-0.5f)*1.0f;
+ Math::Vector speed;
+ speed.x = (Math::Rand()-0.5f)*2.0f;
+ speed.z = (Math::Rand()-0.5f)*2.0f;
+ speed.y = 2.0f+Math::Rand()*2.0f;
+ Math::Point dim;
+ dim.x = (Math::Rand()*1.0f+1.0f)*(0.2f+m_progress*0.8f);
+ dim.y = dim.x;
+ m_particle->CreateParticle(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.5f);
+ }
+
+ Math::Vector angle = m_object->GetAngle(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 ( m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticle = m_time;
+
+ Math::Vector pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*5.0f;
+ pos.z += (Math::Rand()-0.5f)*5.0f;
+ Math::Vector speed;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 5.0f+Math::Rand()*5.0f;
+ Math::Point dim;
+ dim.x = Math::Rand()*2.0f+2.0f;
+ dim.y = dim.x;
+ m_particle->CreateParticle(pos, speed, dim, PARTIGLINTb, 2.0f);
+
+ pos = m_pos;
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ speed.y = Math::Rand()*10.0f;
+ speed *= 0.5f+m_progress*0.5f;
+ dim.x = 0.6f;
+ dim.y = dim.x;
+ pos.y += dim.y;
+ float duration = Math::Rand()*1.5f+1.5f;
+ m_particle->CreateTrack(pos, speed, dim, PARTITRACK6,
+ duration, 0.0f,
+ duration*0.9f, 0.7f);
+ }
+
+ Math::Vector angle = m_object->GetResetAngle();
+ 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_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticle = m_time;
+
+ float factor = m_size*0.3f;
+ if (m_object->GetType() == OBJECT_SAFE) factor *= 1.3f;
+ if (factor > 40.0f) factor = 40.0f;
+ Math::Vector pos = m_pos;
+ m_terrain->AdjustToFloor(pos);
+ pos.x += (Math::Rand()-0.5f)*factor;
+ pos.z += (Math::Rand()-0.5f)*factor;
+ Math::Vector speed;
+ speed.x = (Math::Rand()-0.5f)*2.0f;
+ speed.z = (Math::Rand()-0.5f)*2.0f;
+ speed.y = 4.0f+Math::Rand()*4.0f;
+ Math::Point dim;
+ dim.x = (Math::Rand()*3.0f+3.0f)*(1.0f-m_progress*0.9f);
+ dim.y = dim.x;
+ m_particle->CreateParticle(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.5f);
+ }
+ }
+
+ if ( (m_type == PT_BURNT || m_type == PT_BURNO) &&
+ m_object != 0 )
+ {
+ if ( m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticle = m_time;
+
+ float factor = m_size/25.0f; // 1 = standard size
+
+ Math::Vector pos = m_object->GetPosition(0);
+ pos.y -= m_object->GetCharacter()->height;
+ pos.x += (Math::Rand()-0.5f)*(4.0f+8.0f*m_progress)*factor;
+ pos.z += (Math::Rand()-0.5f)*(4.0f+8.0f*m_progress)*factor;
+ Math::Vector speed;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 0.0f;
+ Math::Point dim;
+ dim.x = (Math::Rand()*2.5f+1.0f)*factor;
+ dim.y = dim.x;
+ m_particle->CreateParticle(pos, speed, dim, PARTIFLAME, 2.0f, 0.0f, 0.2f);
+
+ pos = m_object->GetPosition(0);
+ pos.y -= m_object->GetCharacter()->height;
+ pos.x += (Math::Rand()-0.5f)*(2.0f+4.0f*m_progress)*factor;
+ pos.z += (Math::Rand()-0.5f)*(2.0f+4.0f*m_progress)*factor;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = (Math::Rand()*5.0f*m_progress+3.0f)*factor;
+ dim.x = (Math::Rand()*2.0f+1.0f)*factor;
+ dim.y = dim.x;
+ m_particle->CreateParticle(pos, speed, dim, PARTIFLAME, 2.0f, 0.0f, 0.2f);
+
+ pos = m_object->GetPosition(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_particle->CreateParticle(pos, speed, dim, PARTISMOKE3, 4.0f);
+ }
+
+ if ( m_type == PT_BURNT )
+ {
+ BurnProgress();
+ }
+ else
+ {
+ Math::Vector speed;
+ speed.y = 0.0f;
+ speed.x = (Math::Rand()-0.5f)*m_progress*1.0f;
+ speed.z = (Math::Rand()-0.5f)*m_progress*1.0f;
+ if ( m_progress > 0.8f )
+ {
+ float prog = (m_progress-0.8f)/0.2f; // 0..1
+ speed.y = -prog*6.0f; // sinks into the ground
+ m_object->SetZoom(0, 1.0f-prog*0.5f);
+ }
+ m_object->SetLinVibration(speed);
+ }
+ }
+
+ if ( m_type == PT_WIN )
+ {
+ if ( m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticle = m_time;
+
+ Math::Vector pos = m_object->GetPosition(0);
+ pos.y += 1.5f;
+ Math::Vector speed;
+ speed.x = (Math::Rand()-0.5f)*10.0f;
+ speed.z = (Math::Rand()-0.5f)*10.0f;
+ speed.y = 8.0f+Math::Rand()*8.0f;
+ Math::Point dim;
+ dim.x = Math::Rand()*0.2f+0.2f;
+ dim.y = dim.x;
+ m_particle->CreateTrack(pos, speed, dim,
+ static_cast<ParticleType>(PARTITRACK7+rand()%4),
+ 3.0f, 20.0f, 1.0f, 0.4f);
+ }
+ }
+
+ if ( m_type == PT_LOST )
+ {
+ if ( m_lastParticle+m_engine->ParticleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticle = m_time;
+
+ Math::Vector pos = m_object->GetPosition(0);
+ pos.y -= 2.0f;
+ pos.x += (Math::Rand()-0.5f)*10.0f;
+ pos.z += (Math::Rand()-0.5f)*10.0f;
+ Math::Vector speed;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 1.0f+Math::Rand()*1.0f;
+ Math::Point dim;
+ dim.x = Math::Rand()*1.0f+1.0f;
+ dim.y = dim.x;
+ m_particle->CreateParticle(pos, speed, dim, PARTISMOKE1, 8.0f, 0.0f, 0.0f);
+ }
+ }
+
+ if (m_type == PT_FALL)
+ FallProgress(event.rTime);
+
+ if (m_lightRank != -1)
+ LightOperFrame(event.rTime);
+
return true;
}
Error CPyro::IsEnded()
{
- GetLogger()->Trace("CPyro::IsEnded() stub!\n");
- // TODO!
- return ERR_OK;
+ // 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->GetResetPosition());
+ m_object->SetAngle(0, m_object->GetResetAngle());
+ m_object->SetZoom(0, 1.0f);
+ }
+
+ if ( m_lightRank != -1 )
+ {
+ m_lightMan->DeleteLight(m_lightRank);
+ m_lightRank = -1;
+ }
+
+ return ERR_STOP;
}
-void CPyro::CutObjectLink(CObject* pObj)
+void CPyro::CutObjectLink(CObject* obj)
{
- GetLogger()->Trace("CPyro::CutObjectLink() stub!\n");
- // TODO!
+ if (m_object == obj)
+ m_object = nullptr;
}
-void CPyro::DisplayError(PyroType type, CObject* pObj)
+void CPyro::DisplayError(PyroType type, CObject* obj)
{
- GetLogger()->Trace("CPyro::DisplayError() stub!\n");
- // TODO!
+ ObjectType oType = obj->GetType();
+
+ if ( type == PT_FRAGT ||
+ type == PT_FRAGO ||
+ type == PT_FRAGW ||
+ type == PT_EXPLOT ||
+ type == PT_EXPLOO ||
+ type == PT_EXPLOW ||
+ type == PT_BURNT ||
+ type == PT_BURNO )
+ {
+ Error err = ERR_OK;
+ if ( oType == OBJECT_MOTHER ) err = INFO_DELETEMOTHER;
+ if ( oType == OBJECT_ANT ) err = INFO_DELETEANT;
+ if ( oType == OBJECT_BEE ) err = INFO_DELETEBEE;
+ if ( oType == OBJECT_WORM ) err = INFO_DELETEWORM;
+ if ( oType == OBJECT_SPIDER ) err = INFO_DELETESPIDER;
+
+ if ( oType == OBJECT_MOBILEwa ||
+ oType == OBJECT_MOBILEta ||
+ oType == OBJECT_MOBILEfa ||
+ oType == OBJECT_MOBILEia ||
+ 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, obj->GetPosition(0), 5.0f);
+ return;
+ }
+
+ if ( err != ERR_OK )
+ {
+ m_displayText->DisplayError(err, obj);
+ }
+ }
}
-bool CPyro::CreateLight(Math::Vector pos, float height)
+void CPyro::CreateLight(Math::Vector pos, float height)
{
- GetLogger()->Trace("CPyro::CreateLight() stub!\n");
- // TODO!
- return true;
+ if (!m_engine->GetLightMode()) return;
+
+ m_lightHeight = height;
+
+ Gfx::Light light;
+ light.type = LIGHT_SPOT;
+ light.position.x = pos.x;
+ light.position.y = pos.y+height;
+ light.position.z = pos.z;
+ light.direction.x = 0.0f;
+ light.direction.y = -1.0f; // against the bottom
+ light.direction.z = 0.0f;
+ light.spotIntensity = 1.0f;
+ light.attenuation0 = 1.0f;
+ light.attenuation1 = 0.0f;
+ light.attenuation2 = 0.0f;
+ light.spotAngle = Math::PI/4.0f;
+
+ m_lightRank = m_lightMan->CreateLight();
+
+ m_lightMan->SetLight(m_lightRank, light);
+ m_lightMan->SetLightIntensity(m_lightRank, 0.0f);
+
+ // Only illuminates the objects on the ground.
+ m_lightMan->SetLightIncludeType(m_lightRank, ENG_OBJTYPE_TERRAIN);
}
void CPyro::DeleteObject(bool primary, bool secondary)
{
- GetLogger()->Trace("CPyro::DeleteObject() stub!\n");
- // TODO!
+ if (m_object == nullptr) return;
+
+ if (m_object->GetResetCap() == RESET_MOVE) // resettable object?
+ {
+ m_object->SetEnable(false); // object cache and inactive
+ Math::Vector pos = m_object->GetPosition(0);
+ pos.y = -100.0f;
+ m_object->SetPosition(0, pos);
+ return;
+ }
+
+ ObjectType type = m_object->GetType();
+ if ( secondary &&
+ type != OBJECT_FACTORY &&
+ type != OBJECT_NUCLEAR &&
+ type != OBJECT_ENERGY )
+ {
+ CObject* sub = m_object->GetPower();
+ if ( sub != 0 )
+ {
+ sub->DeleteObject(); // removes the battery
+ delete sub;
+ m_object->SetPower(0);
+ }
+
+ sub = m_object->GetFret();
+ if ( sub != 0 )
+ {
+ sub->DeleteObject(); // removes the object transported
+ delete sub;
+ m_object->SetFret(nullptr);
+ }
+ }
+
+ if (primary)
+ {
+ CObject* truck = m_object->GetTruck();
+ if ( truck != 0 ) // object carries?
+ {
+ if (truck->GetPower() == m_object)
+ truck->SetPower(nullptr);
+
+ if (truck->GetFret() == m_object)
+ truck->SetFret(nullptr);
+ }
+
+ CObject* sub = m_object;
+ sub->DeleteObject(); // removes the object (*)
+ delete sub;
+ m_object = nullptr;
+ }
}
-void CPyro::CreateTriangle(CObject* pObj, ObjectType oType, int part)
+void CPyro::CreateTriangle(CObject* obj, ObjectType oType, int part)
{
- GetLogger()->Trace("CPyro::CreateTriangle() stub!\n");
- // TODO!
+ int objRank = obj->GetObjectRank(part);
+ if (objRank == -1) return;
+
+ float min = 0.0f;
+ float max = m_engine->GetLimitLOD(0);
+ int total = m_engine->GetObjectTotalTriangles(objRank);
+ float 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;
+
+ std::vector<EngineTriangle> buffer;
+ total = m_engine->GetPartialTriangles(objRank, min, max, percent, 100, buffer);
+
+ for (int i = 0; i < total; i++)
+ {
+ Math::Vector p1, p2, p3;
+
+ p1.x = buffer[i].triangle[0].coord.x;
+ p1.y = buffer[i].triangle[0].coord.y;
+ p1.z = buffer[i].triangle[0].coord.z;
+ p2.x = buffer[i].triangle[1].coord.x;
+ p2.y = buffer[i].triangle[1].coord.y;
+ p2.z = buffer[i].triangle[1].coord.z;
+ p3.x = buffer[i].triangle[2].coord.x;
+ p3.y = buffer[i].triangle[2].coord.y;
+ p3.z = buffer[i].triangle[2].coord.z;
+
+ float h;
+
+ h = Math::Distance(p1, p2);
+ if ( h > 5.0f )
+ {
+ p2.x = p1.x+((p2.x-p1.x)*5.0f/h);
+ p2.y = p1.y+((p2.y-p1.y)*5.0f/h);
+ p2.z = p1.z+((p2.z-p1.z)*5.0f/h);
+ }
+
+ h = Math::Distance(p2, p3);
+ if ( h > 5.0f )
+ {
+ p3.x = p2.x+((p3.x-p2.x)*5.0f/h);
+ p3.y = p2.y+((p3.y-p2.y)*5.0f/h);
+ p3.z = p2.z+((p3.z-p2.z)*5.0f/h);
+ }
+
+ h = Math::Distance(p3, p1);
+ if ( h > 5.0f )
+ {
+ p1.x = p3.x+((p1.x-p3.x)*5.0f/h);
+ p1.y = p3.y+((p1.y-p3.y)*5.0f/h);
+ p1.z = p3.z+((p1.z-p3.z)*5.0f/h);
+ }
+
+ buffer[i].triangle[0].coord.x = p1.x;
+ buffer[i].triangle[0].coord.y = p1.y;
+ buffer[i].triangle[0].coord.z = p1.z;
+ buffer[i].triangle[1].coord.x = p2.x;
+ buffer[i].triangle[1].coord.y = p2.y;
+ buffer[i].triangle[1].coord.z = p2.z;
+ buffer[i].triangle[2].coord.x = p3.x;
+ buffer[i].triangle[2].coord.y = p3.y;
+ buffer[i].triangle[2].coord.z = p3.z;
+
+ Math::Vector offset;
+ offset.x = (buffer[i].triangle[0].coord.x+buffer[i].triangle[1].coord.x+buffer[i].triangle[2].coord.x)/3.0f;
+ offset.y = (buffer[i].triangle[0].coord.y+buffer[i].triangle[1].coord.y+buffer[i].triangle[2].coord.y)/3.0f;
+ offset.z = (buffer[i].triangle[0].coord.z+buffer[i].triangle[1].coord.z+buffer[i].triangle[2].coord.z)/3.0f;
+
+ buffer[i].triangle[0].coord.x -= offset.x;
+ buffer[i].triangle[1].coord.x -= offset.x;
+ buffer[i].triangle[2].coord.x -= offset.x;
+
+ buffer[i].triangle[0].coord.y -= offset.y;
+ buffer[i].triangle[1].coord.y -= offset.y;
+ buffer[i].triangle[2].coord.y -= offset.y;
+
+ buffer[i].triangle[0].coord.z -= offset.z;
+ buffer[i].triangle[1].coord.z -= offset.z;
+ buffer[i].triangle[2].coord.z -= offset.z;
+
+ Math::Vector speed;
+ float mass;
+
+ Math::Matrix* mat = obj->GetWorldMatrix(part);
+ Math::Vector pos = Math::Transform(*mat, offset);
+ 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;
+ float duration = Math::Rand()*3.0f+3.0f;
+ m_particle->CreateFrag(pos, speed, &buffer[i], PARTIFRAG,
+ duration, mass, 0.5f);
+ }
}
void CPyro::ExploStart()
{
- GetLogger()->Trace("CPyro::ExploStart() stub!\n");
- // TODO!
+ m_burnType = m_object->GetType();
+
+ Math::Vector oPos = m_object->GetPosition(0);
+ m_burnFall = m_terrain->GetHeightToFloor(oPos, true);
+
+ m_object->Simplify();
+ m_object->SetLock(true); // ruin not usable yet
+ m_object->SetExplo(true); // being destroyed
+ m_object->FlatParent();
+
+ if ( m_object->GetSelect() )
+ {
+ m_object->SetSelect(false); // deselects the object
+ m_camera->SetType(CAM_TYPE_EXPLO);
+ m_main->DeselectAll();
+ }
+ m_object->DeleteDeselList(m_object);
+
+ for (int i = 0; i < OBJECTMAXPART; i++)
+ {
+ int objRank = m_object->GetObjectRank(i);
+ if ( objRank == -1 ) continue;
+ m_engine->ChangeSecondTexture(objRank, "dirty04.tga");
+
+ Math::Vector pos = m_object->GetPosition(i);
+
+ Math::Vector speed;
+ float weight;
+
+ if (i == 0) // main part?
+ {
+ weight = 0.0f;
+
+ speed.y = -1.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ }
+ else
+ {
+ Math::Vector min, max;
+ m_engine->GetObjectBBox(objRank, min, max);
+ weight = Math::Distance(min, max); // weight according to size!
+
+ speed.y = 10.0f+Math::Rand()*20.0f;
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ }
+
+ int channel = m_particle->CreatePart(pos, speed, PARTIPART, 10.0f, 20.0f, weight, 0.5f);
+ if (channel != -1)
+ m_object->SetMasterParticle(i, channel);
+ }
+ m_engine->LoadTexture("dirty04.png");
+
+ DeleteObject(false, true); // destroys the object transported + the battery
}
void CPyro::ExploTerminate()
{
- GetLogger()->Trace("CPyro::ExploTerminate() stub!\n");
- // TODO!
+ DeleteObject(true, false); // removes the main object
}
void CPyro::BurnStart()
{
- GetLogger()->Trace("CPyro::BurnStart() stub!\n");
- // TODO!
+ m_burnType = m_object->GetType();
+
+ Math::Vector oPos = m_object->GetPosition(0);
+ m_burnFall = m_terrain->GetHeightToFloor(oPos, true);
+
+ m_object->Simplify();
+ m_object->SetLock(true); // ruin not usable yet
+
+ if ( m_object->GetSelect() )
+ {
+ m_object->SetSelect(false); // deselects the object
+ m_camera->SetType(CAM_TYPE_EXPLO);
+ m_main->DeselectAll();
+ }
+ m_object->DeleteDeselList(m_object);
+
+ for (int i = 0; i < OBJECTMAXPART; i++)
+ {
+ int objRank = m_object->GetObjectRank(i);
+ if (objRank == -1) continue;
+ m_engine->ChangeSecondTexture(objRank, "dirty04.png");
+ }
+ m_engine->LoadTexture("dirty04.png");
+
+ m_burnPartTotal = 0;
+
+ Math::Vector pos, angle;
+
+ if ( m_burnType == OBJECT_DERRICK ||
+ m_burnType == OBJECT_FACTORY ||
+ m_burnType == OBJECT_REPAIR ||
+ m_burnType == OBJECT_DESTROYER||
+ m_burnType == OBJECT_CONVERT ||
+ m_burnType == OBJECT_TOWER ||
+ m_burnType == OBJECT_RESEARCH ||
+ m_burnType == OBJECT_ENERGY ||
+ m_burnType == OBJECT_LABO )
+ {
+ pos.x = 0.0f;
+ pos.y = -(4.0f+Math::Rand()*4.0f);
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.4f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*0.4f;
+ }
+ else if ( m_burnType == OBJECT_STATION ||
+ m_burnType == OBJECT_RADAR ||
+ m_burnType == OBJECT_INFO )
+ {
+ pos.x = 0.0f;
+ pos.y = -(1.0f+Math::Rand()*1.0f);
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.2f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*0.2f;
+ }
+ else if ( m_burnType == OBJECT_NUCLEAR )
+ {
+ pos.x = 0.0f;
+ pos.y = -(10.0f+Math::Rand()*10.0f);
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.4f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*0.4f;
+ }
+ else if ( m_burnType == OBJECT_PARA )
+ {
+ pos.x = 0.0f;
+ pos.y = -(10.0f+Math::Rand()*10.0f);
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.4f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*0.4f;
+ }
+ else if ( m_burnType == OBJECT_SAFE )
+ {
+ pos.x = 0.0f;
+ pos.y = -(10.0f+Math::Rand()*10.0f);
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.4f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*0.4f;
+ }
+ else if ( m_burnType == OBJECT_HUSTON )
+ {
+ pos.x = 0.0f;
+ pos.y = -(10.0f+Math::Rand()*10.0f);
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.4f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*0.4f;
+ }
+ else if ( m_burnType == OBJECT_MOBILEwa ||
+ m_burnType == OBJECT_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?
+ {
+ int i = 0;
+ for (; i < 4; i++)
+ {
+ pos.x = 0.0f;
+ pos.y = Math::Rand()*0.5f;
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*Math::PI/2.0f;
+ angle.y = (Math::Rand()-0.5f)*Math::PI/2.0f;
+ angle.z = 0.0f;
+ BurnAddPart(6+i, pos, angle); // wheel
+
+ m_burnKeepPart[i] = 6+i; // we keep the wheels
+ }
+ m_burnKeepPart[i] = -1;
+ }
+
+ if ( m_burnType == OBJECT_MOBILEta ||
+ m_burnType == OBJECT_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?
+ {
+ int i = 0;
+ for (; i<3; i++)
+ {
+ pos.x = 0.0f;
+ pos.y = -3.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*Math::PI/2.0f;
+ BurnAddPart(6+i, pos, angle); // foot
+ }
+ m_burnKeepPart[i] = -1;
+ }
+
+ if ( m_burnType == OBJECT_MOBILEia ||
+ m_burnType == OBJECT_MOBILEic ||
+ m_burnType == OBJECT_MOBILEii ||
+ m_burnType == OBJECT_MOBILEis ) // legs?
+ {
+ for (int i = 0; i < 6; i++)
+ {
+ pos.x = 0.0f;
+ pos.y = -3.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = (Math::Rand()-0.5f)*Math::PI/4.0f;
+ angle.z = (Math::Rand()-0.5f)*Math::PI/4.0f;
+ BurnAddPart(6+i, pos, angle); // leg
+ }
+ }
}
void CPyro::BurnAddPart(int part, Math::Vector pos, Math::Vector angle)
{
- GetLogger()->Trace("CPyro::BurnAddPart() stub!\n");
- // TODO!
+ int i = m_burnPartTotal;
+ m_burnPart[i].part = part;
+ m_burnPart[i].initialPos = m_object->GetPosition(part);
+ m_burnPart[i].finalPos = m_burnPart[i].initialPos+pos;
+ m_burnPart[i].initialAngle = m_object->GetAngle(part);
+ m_burnPart[i].finalAngle = m_burnPart[i].initialAngle+angle;
+
+ m_burnPartTotal++;
}
void CPyro::BurnProgress()
{
- GetLogger()->Trace("CPyro::BurnProgress() stub!\n");
- // TODO!
+ if ( m_burnType == OBJECT_TEEN31 ) // basket?
+ {
+ m_object->SetZoomY(0, 1.0f-m_progress*0.5f); // slight flattening
+ }
+
+ for (int i = 0; i < m_burnPartTotal; i++)
+ {
+ Math::Vector pos = m_burnPart[i].initialPos + m_progress*(m_burnPart[i].finalPos-m_burnPart[i].initialPos);
+ if ( i == 0 && m_burnFall > 0.0f )
+ {
+ float h = powf(m_progress, 2.0f)*1000.0f;
+ if ( h > m_burnFall ) h = m_burnFall;
+ pos.y -= h;
+ }
+ 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);
+ }
+
+ CObject* sub = m_object->GetPower();
+ if (sub != nullptr) // is there a battery?
+ sub->SetZoomY(0, 1.0f - m_progress); // complete flattening
}
bool CPyro::BurnIsKeepPart(int part)
{
- GetLogger()->Trace("CPyro::BurnIsKeepPart() stub!\n");
- // TODO!
- return true;
+ int i = 0;
+ while (m_burnKeepPart[i] != -1)
+ {
+ if (part == m_burnKeepPart[i++]) return true; // must keep
+ }
+ return false; // must destroy
}
void CPyro::BurnTerminate()
{
- GetLogger()->Trace("CPyro::BurnTerminate() stub!\n");
- // TODO!
+ if (m_type == PT_BURNO) // organic object is burning?
+ {
+ DeleteObject(true, true); // removes the insect
+ return;
+ }
+
+ for (int i = 1; i < OBJECTMAXPART; i++)
+ {
+ int objRank = m_object->GetObjectRank(i);
+ if (objRank == -1) continue;
+ if (BurnIsKeepPart(i)) continue;
+
+ m_object->DeletePart(i);
+ }
+
+ DeleteObject(false, true); // destroys the object transported + the battery
+
+ if ( m_burnType == OBJECT_DERRICK ||
+ m_burnType == OBJECT_STATION ||
+ m_burnType == OBJECT_FACTORY ||
+ m_burnType == OBJECT_REPAIR ||
+ m_burnType == OBJECT_DESTROYER||
+ m_burnType == OBJECT_CONVERT ||
+ m_burnType == OBJECT_TOWER ||
+ m_burnType == OBJECT_RESEARCH ||
+ m_burnType == OBJECT_RADAR ||
+ m_burnType == OBJECT_INFO ||
+ m_burnType == OBJECT_ENERGY ||
+ m_burnType == OBJECT_LABO ||
+ m_burnType == OBJECT_NUCLEAR ||
+ m_burnType == OBJECT_PARA ||
+ m_burnType == OBJECT_SAFE ||
+ m_burnType == OBJECT_HUSTON ||
+ m_burnType == OBJECT_START ||
+ m_burnType == OBJECT_END )
+ {
+ m_object->SetType(OBJECT_RUINfactory); // 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)
}
void CPyro::FallStart()
{
- GetLogger()->Trace("CPyro::FallStart() stub!\n");
- // TODO!
+ m_object->SetBurn(true); // usable
+
+ Math::Vector pos = m_object->GetPosition(0);
+ m_fallFloor = m_terrain->GetFloorLevel(pos);
+ m_fallSpeed = 0.0f;
+ m_fallBulletTime = 0.0f;
+ m_fallEnding = false;
}
CObject* CPyro::FallSearchBeeExplo()
{
- GetLogger()->Trace("CPyro::FallSearchBeeExplo() stub!\n");
- // TODO!
+ Math::Vector iPos;
+ float iRadius;
+ m_object->GetCrashSphere(0, iPos, iRadius);
+
+ for (int i = 0; i < 1000000; i++)
+ {
+ CObject* pObj = static_cast<CObject*>(m_iMan->SearchInstance(CLASS_OBJECT, i));
+ if ( pObj == 0 ) break;
+
+ ObjectType oType = pObj->GetType();
+ if ( oType != OBJECT_HUMAN &&
+ oType != OBJECT_MOBILEfa &&
+ oType != OBJECT_MOBILEta &&
+ oType != OBJECT_MOBILEwa &&
+ oType != OBJECT_MOBILEia &&
+ oType != OBJECT_MOBILEfc &&
+ oType != OBJECT_MOBILEtc &&
+ oType != OBJECT_MOBILEwc &&
+ oType != OBJECT_MOBILEic &&
+ oType != OBJECT_MOBILEfi &&
+ oType != OBJECT_MOBILEti &&
+ oType != OBJECT_MOBILEwi &&
+ oType != OBJECT_MOBILEii &&
+ oType != OBJECT_MOBILEfs &&
+ oType != OBJECT_MOBILEts &&
+ oType != OBJECT_MOBILEws &&
+ oType != OBJECT_MOBILEis &&
+ oType != OBJECT_MOBILErt &&
+ oType != OBJECT_MOBILErc &&
+ oType != OBJECT_MOBILErr &&
+ oType != OBJECT_MOBILErs &&
+ oType != OBJECT_MOBILEsa &&
+ oType != OBJECT_MOBILEtg &&
+ oType != OBJECT_MOBILEft &&
+ oType != OBJECT_MOBILEtt &&
+ oType != OBJECT_MOBILEwt &&
+ oType != OBJECT_MOBILEit &&
+ oType != OBJECT_MOBILEdr &&
+ oType != OBJECT_BASE &&
+ oType != OBJECT_DERRICK &&
+ oType != OBJECT_STATION &&
+ oType != OBJECT_FACTORY &&
+ oType != OBJECT_REPAIR &&
+ oType != OBJECT_DESTROYER&&
+ oType != OBJECT_CONVERT &&
+ oType != OBJECT_TOWER &&
+ oType != OBJECT_RESEARCH &&
+ oType != OBJECT_RADAR &&
+ oType != OBJECT_INFO &&
+ oType != OBJECT_ENERGY &&
+ oType != OBJECT_LABO &&
+ oType != OBJECT_NUCLEAR &&
+ oType != OBJECT_PARA &&
+ oType != OBJECT_SAFE &&
+ oType != OBJECT_HUSTON &&
+ oType != OBJECT_METAL &&
+ oType != OBJECT_POWER &&
+ oType != OBJECT_ATOMIC ) continue;
+
+ if ( pObj->GetTruck() != 0 ) continue; // object transported?
+
+ Math::Vector oPos = pObj->GetPosition(0);
+
+ float distance;
+
+ float shieldRadius = pObj->GetShieldRadius();
+ 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.
+ Math::Vector ooPos;
+ float ooRadius;
+ int j = 0;
+ while (pObj->GetCrashSphere(j++, ooPos, ooRadius))
+ {
+ distance = Math::Distance(ooPos, iPos);
+ if (distance <= iRadius+ooRadius)
+ {
+ return pObj;
+ }
+ }
+ }
+
return nullptr;
}
void CPyro::FallProgress(float rTime)
{
- GetLogger()->Trace("CPyro::FallProgress() stub!\n");
- // TODO!
+ if (m_object == nullptr) return;
+
+ m_fallSpeed += rTime*50.0f; // v2 = v1 + a*dt
+ Math::Vector pos;
+ pos = m_object->GetPosition(0);
+ pos.y -= m_fallSpeed*rTime; // dd -= v2*dt
+
+ bool floor = false;
+
+ if (pos.y <= m_fallFloor) // below the ground level?
+ {
+ pos.y = m_fallFloor;
+ floor = true;
+ }
+ m_object->SetPosition(0, pos);
+
+ if (m_object->GetType() == OBJECT_BULLET)
+ {
+ m_fallBulletTime += rTime;
+
+ if (m_fallBulletTime > 0.2f || floor)
+ {
+ m_fallBulletTime = 0.0f;
+
+ CObject* obj = FallSearchBeeExplo();
+ if (obj == nullptr)
+ {
+ if (floor) // reaches the ground?
+ {
+ m_object->ExploObject(EXPLO_BOUM, 0.0f); // start explosion
+ }
+ }
+ else
+ {
+ if (obj->GetShieldRadius() > 0.0f) // protected by shield?
+ {
+ m_particle->CreateParticle(pos, Math::Vector(0.0f, 0.0f, 0.0f),
+ Math::Point(6.0f, 6.0f), PARTIGUNDEL, 2.0f, 0.0f, 0.0f);
+ m_sound->Play(SOUND_GUNDEL);
+
+ DeleteObject(true, true); // removes the ball
+ }
+ else
+ {
+ if (obj->ExploObject(EXPLO_BOUM, 1.0f)) // start explosion
+ {
+ DeleteObject(true, true); // removes the ball
+ }
+ else
+ {
+ m_object->ExploObject(EXPLO_BOUM, 0.0f); // start explosion
+ }
+ }
+ }
+
+ if (floor || obj != nullptr)
+ {
+ m_fallEnding = true;
+ }
+ }
+ }
}
Error CPyro::FallIsEnded()
{
- GetLogger()->Trace("CPyro::FallIsEnded() stub!\n");
- // TODO!
- return ERR_OK;
+ if (m_fallEnding || m_object == 0) return ERR_STOP;
+
+ Math::Vector pos = m_object->GetPosition(0);
+ if (pos.y > m_fallFloor) return ERR_CONTINUE;
+
+ m_sound->Play(SOUND_BOUM, pos);
+ m_object->SetBurn(false); // usable again
+
+ return ERR_STOP;
}
void CPyro::LightOperFlush()
{
- GetLogger()->Trace("CPyro::LightOperFlush() stub!\n");
- // TODO!
+ m_lightOperTotal = 0;
}
void CPyro::LightOperAdd(float progress, float intensity, float r, float g, float b)
{
- GetLogger()->Trace("CPyro::LightOperAdd() stub!\n");
- // TODO!
+ int 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++;
}
void CPyro::LightOperFrame(float rTime)
{
- GetLogger()->Trace("CPyro::LightOperFrame() stub!\n");
- // TODO!
+ for (int i = 0; i < m_lightOperTotal; i++)
+ {
+ if ( m_progress < m_lightOper[i].progress )
+ {
+ float progress = (m_progress-m_lightOper[i-1].progress) / (m_lightOper[i].progress-m_lightOper[i-1].progress);
+
+ float intensity = m_lightOper[i-1].intensity + (m_lightOper[i].intensity-m_lightOper[i-1].intensity)*progress;
+ Gfx::Color color;
+ color.r = m_lightOper[i-1].color.r + (m_lightOper[i].color.r-m_lightOper[i-1].color.r)*progress;
+ color.g = m_lightOper[i-1].color.g + (m_lightOper[i].color.g-m_lightOper[i-1].color.g)*progress;
+ color.b = m_lightOper[i-1].color.b + (m_lightOper[i].color.b-m_lightOper[i-1].color.b)*progress;
+
+ m_lightMan->SetLightIntensity(m_lightRank, intensity);
+ m_lightMan->SetLightColor(m_lightRank, color);
+ break;
+ }
+ }
}
diff --git a/src/graphics/engine/pyro.h b/src/graphics/engine/pyro.h
index d91b049..0204070 100644
--- a/src/graphics/engine/pyro.h
+++ b/src/graphics/engine/pyro.h
@@ -33,10 +33,13 @@
class CInstanceManager;
class CObject;
-class CDisplayText;
class CRobotMain;
class CSoundInterface;
+namespace Ui {
+class CDisplayText;
+}
+
// Graphics module namespace
namespace Gfx {
@@ -48,33 +51,37 @@ class CParticle;
class CLight;
+/**
+ * \enum PyroType
+ * \brief Type of pyro effect
+ */
enum PyroType
{
PT_NULL = 0,
- PT_FRAGT = 1, // fragmentation of technical object
- PT_FRAGO = 2, // fragmentation of organic object
- PT_FRAGW = 4, // fragmentation of object under water
- PT_EXPLOT = 5, // explosion of technical object
- PT_EXPLOO = 6, // explosion of organic object
- PT_EXPLOW = 8, // explosion of object under water
- PT_SHOTT = 9, // hit technical object
- PT_SHOTH = 10, // hit human
- PT_SHOTM = 11, // hit queen
- PT_SHOTW = 12, // hit under water
- PT_EGG = 13, // break the egg
- PT_BURNT = 14, // burning of technical object
- PT_BURNO = 15, // burning of organic object
- PT_SPIDER = 16, // spider explosion
- PT_FALL = 17, // cargo falling
- PT_WPCHECK = 18, // indicator reaches
- PT_FLCREATE = 19, // flag create
- PT_FLDELETE = 20, // flag destroy
- PT_RESET = 21, // reset position of the object
- PT_WIN = 22, // fireworks
- PT_LOST = 23, // black smoke
- PT_DEADG = 24, // shooting death
- PT_DEADW = 25, // drowning death
- PT_FINDING = 26, // object discovered
+ PT_FRAGT = 1, //! < fragmentation of technical object
+ PT_FRAGO = 2, //! < fragmentation of organic object
+ PT_FRAGW = 4, //! < fragmentation of object under water
+ PT_EXPLOT = 5, //! < explosion of technical object
+ PT_EXPLOO = 6, //! < explosion of organic object
+ PT_EXPLOW = 8, //! < explosion of object under water
+ PT_SHOTT = 9, //! < hit technical object
+ PT_SHOTH = 10, //! < hit human
+ PT_SHOTM = 11, //! < hit queen
+ PT_SHOTW = 12, //! < hit under water
+ PT_EGG = 13, //! < break the egg
+ PT_BURNT = 14, //! < burning of technical object
+ PT_BURNO = 15, //! < burning of organic object
+ PT_SPIDER = 16, //! < spider explosion
+ PT_FALL = 17, //! < cargo falling
+ PT_WPCHECK = 18, //! < indicator reaches
+ PT_FLCREATE = 19, //! < flag create
+ PT_FLDELETE = 20, //! < flag destroy
+ PT_RESET = 21, //! < reset position of the object
+ PT_WIN = 22, //! < fireworks
+ PT_LOST = 23, //! < black smoke
+ PT_DEADG = 24, //! < shooting death
+ PT_DEADW = 25, //! < drowning death
+ PT_FINDING = 26, //! < object discovered
};
@@ -89,8 +96,8 @@ struct PyroBurnPart
struct PyroLightOper
{
- float progress;
- float intensity;
+ float progress;
+ float intensity;
Color color;
};
@@ -99,7 +106,7 @@ struct PyroLightOper
* \class CPyro
* \brief Fire effect renderer
*
- * Functions are only stubs for now.
+ * TODO: documentation
*/
class CPyro
{
@@ -107,70 +114,98 @@ public:
CPyro(CInstanceManager* iMan);
~CPyro();
- void DeleteObject(bool all=false);
- bool Create(PyroType type, CObject* pObj, float force=1.0f);
- bool EventProcess(const Event &event);
+ //! Creates pyrotechnic effect
+ bool Create(PyroType type, CObject* obj, float force=1.0f);
+ //! Destroys the object
+ void DeleteObject();
+
+ //! Indicates whether the pyrotechnic effect is complete
Error IsEnded();
- void CutObjectLink(CObject* pObj);
+
+ //! Indicates that the object binds to the effect no longer exists, without deleting it
+ void CutObjectLink(CObject* obj);
+
+ //! Management of an event
+ bool EventProcess(const Event& event);
protected:
- void DisplayError(PyroType type, CObject* pObj);
- bool CreateLight(Math::Vector pos, float height);
+ //! Displays the error or eventual information
+ //! Information can be linked to the destruction of an insect, a vehicle or building
+ void DisplayError(PyroType type, CObject* obj);
+
+ //! Creates light to accompany a pyrotechnic effect
+ void CreateLight(Math::Vector pos, float height);
+ //! Removes the binding to a pyrotechnic effect
void DeleteObject(bool primary, bool secondary);
- void CreateTriangle(CObject* pObj, ObjectType oType, int part);
+ //! Creates an explosion with triangular form of particles
+ void CreateTriangle(CObject* obj, ObjectType type, int part);
+ //! Starts the explosion of a vehicle
void ExploStart();
+ //! Ends the explosion of a vehicle
void ExploTerminate();
+ //! Starts a vehicle fire
void BurnStart();
+ //! Adds a part move
void BurnAddPart(int part, Math::Vector pos, Math::Vector angle);
+ //! Advances of a vehicle fire
void BurnProgress();
+ //! Indicates whether a part should be retained
bool BurnIsKeepPart(int part);
+ //! Ends the fire of an insect or a vehicle
void BurnTerminate();
+ //! Start of an object freight falling
void FallStart();
+ //! Seeks an object to explode by the falling ball of bees
CObject* FallSearchBeeExplo();
+ //! Fall of an object's freight
void FallProgress(float rTime);
+ //! Indicates whether the fall is over
Error FallIsEnded();
+ //! Empty the table of operations of animation of light
void LightOperFlush();
+ //! Adds an animation operation of the light
void LightOperAdd(float progress, float intensity, float r, float g, float b);
+ //! Updates the associated light
void LightOperFrame(float rTime);
protected:
- CInstanceManager* m_iMan;
- CEngine* m_engine;
- CTerrain* m_terrain;
- CCamera* m_camera;
- CParticle* m_particule;
- CLightManager* m_lightMan;
- CObject* m_object;
- CDisplayText* m_displayText;
- CRobotMain* m_main;
- CSoundInterface* m_sound;
+ CInstanceManager* m_iMan;
+ CEngine* m_engine;
+ CTerrain* m_terrain;
+ CCamera* m_camera;
+ CParticle* m_particle;
+ CLightManager* m_lightMan;
+ CObject* m_object;
+ Ui::CDisplayText* m_displayText;
+ CRobotMain* m_main;
+ CSoundInterface* m_sound;
Math::Vector m_pos; // center of the effect
Math::Vector m_posPower; // center of the battery
bool m_power; // battery exists?
- PyroType m_type;
+ PyroType m_type;
float m_force;
float m_size;
float m_progress;
float m_speed;
float m_time;
- float m_lastParticule;
- float m_lastParticuleSmoke;
+ float m_lastParticle;
+ float m_lastParticleSmoke;
int m_soundChannel;
int m_lightRank;
int m_lightOperTotal;
- PyroLightOper m_lightOper[10];
+ PyroLightOper m_lightOper[10];
float m_lightHeight;
ObjectType m_burnType;
int m_burnPartTotal;
- PyroBurnPart m_burnPart[10];
+ PyroBurnPart m_burnPart[10];
int m_burnKeepPart[10];
float m_burnFall;
diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp
index ee77420..94b0dbc 100644
--- a/src/graphics/opengl/gldevice.cpp
+++ b/src/graphics/opengl/gldevice.cpp
@@ -309,7 +309,7 @@ void CGLDevice::SetLight(int index, const Light &light)
if (light.type == LIGHT_SPOT)
{
- glLightf(GL_LIGHT0 + index, GL_SPOT_CUTOFF, light.spotAngle);
+ glLightf(GL_LIGHT0 + index, GL_SPOT_CUTOFF, light.spotAngle * Math::RAD_TO_DEG);
glLightf(GL_LIGHT0 + index, GL_SPOT_EXPONENT, light.spotIntensity);
}
else
diff --git a/src/object/brain.cpp b/src/object/brain.cpp
index 7b580d7..5403903 100644
--- a/src/object/brain.cpp
+++ b/src/object/brain.cpp
@@ -203,8 +203,8 @@ bool CBrain::EventProcess(const Event &event)
action = EVENT_NULL;
if ( event.type == EVENT_KEY_DOWN &&
- (event.key.key == m_main->GetInputBinding(INPUT_SLOT_ACTION).key ||
- event.key.key == m_main->GetInputBinding(INPUT_SLOT_ACTION).joy ) &&
+ (event.key.key == m_main->GetInputBinding(INPUT_SLOT_ACTION).primary ||
+ event.key.key == m_main->GetInputBinding(INPUT_SLOT_ACTION).secondary ) &&
!m_main->GetEditLock() )
{
pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
diff --git a/src/object/object.cpp b/src/object/object.cpp
index ec8b3c5..5a1631f 100644
--- a/src/object/object.cpp
+++ b/src/object/object.cpp
@@ -2264,7 +2264,7 @@ bool CObject::CreateShadowLight(float height, Gfx::Color color)
light.attenuation0 = 1.0f;
light.attenuation1 = 0.0f;
light.attenuation2 = 0.0f;
- light.spotAngle = 90;
+ light.spotAngle = 90.0f*Math::PI/180.0f;
m_shadowLight = m_lightMan->CreateLight();
if ( m_shadowLight == -1 ) return false;
@@ -2307,7 +2307,7 @@ bool CObject::CreateEffectLight(float height, Gfx::Color color)
light.attenuation0 = 1.0f;
light.attenuation1 = 0.0f;
light.attenuation2 = 0.0f;
- light.spotAngle = 90;
+ light.spotAngle = 90.0f*Math::PI/180.0f;
m_effectLight = m_lightMan->CreateLight();
if ( m_effectLight == -1 ) return false;
@@ -2995,7 +2995,7 @@ bool CObject::CreateBuilding(Math::Vector pos, float angle, float height,
m_character.posPower = Math::Vector(5.0f, 3.0f, 0.0f);
CreateShadowCircle(6.0f, 1.0f);
- m_showLimitRadius = Gfx::BLITZPARA;
+ m_showLimitRadius = Gfx::LTNG_PROTECTION_RADIUS;
}
if ( m_type == OBJECT_NUCLEAR )
@@ -3048,7 +3048,7 @@ bool CObject::CreateBuilding(Math::Vector pos, float angle, float height,
SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 20.0f);
CreateShadowCircle(21.0f, 1.0f);
- m_showLimitRadius = Gfx::BLITZPARA;
+ m_showLimitRadius = Gfx::LTNG_PROTECTION_RADIUS;
}
if ( m_type == OBJECT_SAFE )
diff --git a/src/object/robotmain.cpp b/src/object/robotmain.cpp
index 5f851c4..0f84ff7 100644
--- a/src/object/robotmain.cpp
+++ b/src/object/robotmain.cpp
@@ -730,7 +730,7 @@ CRobotMain::CRobotMain(CInstanceManager* iMan, CApplication* app)
g_build = 0;
g_researchDone = 0; // no research done
g_researchEnable = 0;
- g_unit = 4.0f;
+ g_unit = UNIT;
m_gamerName[0] = 0;
/* TODO: profile
@@ -878,7 +878,7 @@ void CRobotMain::SetDefaultInputBindings()
{
for (int i = 0; i < INPUT_SLOT_MAX; i++)
{
- m_inputBindings[i].key = m_inputBindings[i].joy = KEY_INVALID;
+ m_inputBindings[i].primary = m_inputBindings[i].secondary = KEY_INVALID;
}
for (int i = 0; i < JOY_AXIS_SLOT_MAX; i++)
@@ -887,34 +887,34 @@ void CRobotMain::SetDefaultInputBindings()
m_joyAxisBindings[i].invert = false;
}
- m_inputBindings[INPUT_SLOT_LEFT ].key = KEY(LEFT);
- m_inputBindings[INPUT_SLOT_RIGHT ].key = KEY(RIGHT);
- m_inputBindings[INPUT_SLOT_UP ].key = KEY(UP);
- m_inputBindings[INPUT_SLOT_DOWN ].key = KEY(DOWN);
- m_inputBindings[INPUT_SLOT_GUP ].key = VIRTUAL_KMOD(SHIFT);
- m_inputBindings[INPUT_SLOT_GDOWN ].key = VIRTUAL_KMOD(CTRL);
- m_inputBindings[INPUT_SLOT_CAMERA ].key = KEY(SPACE);
- m_inputBindings[INPUT_SLOT_CAMERA ].joy = VIRTUAL_JOY(2);
- m_inputBindings[INPUT_SLOT_DESEL ].key = KEY(KP0);
- m_inputBindings[INPUT_SLOT_DESEL ].joy = VIRTUAL_JOY(6);
- m_inputBindings[INPUT_SLOT_ACTION ].key = KEY(RETURN);
- m_inputBindings[INPUT_SLOT_ACTION ].joy = VIRTUAL_JOY(1);
- m_inputBindings[INPUT_SLOT_NEAR ].key = KEY(KP_PLUS);
- m_inputBindings[INPUT_SLOT_NEAR ].joy = VIRTUAL_JOY(5);
- m_inputBindings[INPUT_SLOT_AWAY ].key = KEY(KP_MINUS);
- m_inputBindings[INPUT_SLOT_AWAY ].joy = VIRTUAL_JOY(4);
- m_inputBindings[INPUT_SLOT_NEXT ].key = KEY(TAB);
- m_inputBindings[INPUT_SLOT_NEXT ].joy = VIRTUAL_JOY(3);
- m_inputBindings[INPUT_SLOT_HUMAN ].key = KEY(HOME);
- m_inputBindings[INPUT_SLOT_HUMAN ].joy = VIRTUAL_JOY(7);
- m_inputBindings[INPUT_SLOT_QUIT ].key = KEY(ESCAPE);
- m_inputBindings[INPUT_SLOT_HELP ].key = KEY(F1);
- m_inputBindings[INPUT_SLOT_PROG ].key = KEY(F2);
- m_inputBindings[INPUT_SLOT_CBOT ].key = KEY(F3);
- m_inputBindings[INPUT_SLOT_VISIT ].key = KEY(KP_PERIOD);
- m_inputBindings[INPUT_SLOT_SPEED10].key = KEY(F4);
- m_inputBindings[INPUT_SLOT_SPEED15].key = KEY(F5);
- m_inputBindings[INPUT_SLOT_SPEED20].key = KEY(F6);
+ m_inputBindings[INPUT_SLOT_LEFT ].primary = KEY(LEFT);
+ m_inputBindings[INPUT_SLOT_RIGHT ].primary = KEY(RIGHT);
+ m_inputBindings[INPUT_SLOT_UP ].primary = KEY(UP);
+ m_inputBindings[INPUT_SLOT_DOWN ].primary = KEY(DOWN);
+ m_inputBindings[INPUT_SLOT_GUP ].primary = VIRTUAL_KMOD(SHIFT);
+ m_inputBindings[INPUT_SLOT_GDOWN ].primary = VIRTUAL_KMOD(CTRL);
+ m_inputBindings[INPUT_SLOT_CAMERA ].primary = KEY(SPACE);
+ m_inputBindings[INPUT_SLOT_CAMERA ].secondary = VIRTUAL_JOY(2);
+ m_inputBindings[INPUT_SLOT_DESEL ].primary = KEY(KP0);
+ m_inputBindings[INPUT_SLOT_DESEL ].secondary = VIRTUAL_JOY(6);
+ m_inputBindings[INPUT_SLOT_ACTION ].primary = KEY(RETURN);
+ m_inputBindings[INPUT_SLOT_ACTION ].secondary = VIRTUAL_JOY(1);
+ m_inputBindings[INPUT_SLOT_NEAR ].primary = KEY(KP_PLUS);
+ m_inputBindings[INPUT_SLOT_NEAR ].secondary = VIRTUAL_JOY(5);
+ m_inputBindings[INPUT_SLOT_AWAY ].primary = KEY(KP_MINUS);
+ m_inputBindings[INPUT_SLOT_AWAY ].secondary = VIRTUAL_JOY(4);
+ m_inputBindings[INPUT_SLOT_NEXT ].primary = KEY(TAB);
+ m_inputBindings[INPUT_SLOT_NEXT ].secondary = VIRTUAL_JOY(3);
+ m_inputBindings[INPUT_SLOT_HUMAN ].primary = KEY(HOME);
+ m_inputBindings[INPUT_SLOT_HUMAN ].secondary = VIRTUAL_JOY(7);
+ m_inputBindings[INPUT_SLOT_QUIT ].primary = KEY(ESCAPE);
+ m_inputBindings[INPUT_SLOT_HELP ].primary = KEY(F1);
+ m_inputBindings[INPUT_SLOT_PROG ].primary = KEY(F2);
+ m_inputBindings[INPUT_SLOT_CBOT ].primary = KEY(F3);
+ m_inputBindings[INPUT_SLOT_VISIT ].primary = KEY(KP_PERIOD);
+ m_inputBindings[INPUT_SLOT_SPEED10].primary = KEY(F4);
+ m_inputBindings[INPUT_SLOT_SPEED15].primary = KEY(F5);
+ m_inputBindings[INPUT_SLOT_SPEED20].primary = KEY(F6);
m_joyAxisBindings[JOY_AXIS_SLOT_X].axis = 0;
m_joyAxisBindings[JOY_AXIS_SLOT_Y].axis = 1;
@@ -1214,33 +1214,33 @@ bool CRobotMain::EventProcess(Event &event)
if (event.type == EVENT_KEY_DOWN)
{
- if (event.key.key == GetInputBinding(INPUT_SLOT_UP ).key) m_keyMotion.y = 1.0f;
- if (event.key.key == GetInputBinding(INPUT_SLOT_UP ).joy) m_keyMotion.y = 1.0f;
- if (event.key.key == GetInputBinding(INPUT_SLOT_DOWN ).key) m_keyMotion.y = -1.0f;
- if (event.key.key == GetInputBinding(INPUT_SLOT_DOWN ).joy) m_keyMotion.y = -1.0f;
- if (event.key.key == GetInputBinding(INPUT_SLOT_LEFT ).key) m_keyMotion.x = -1.0f;
- if (event.key.key == GetInputBinding(INPUT_SLOT_LEFT ).joy) m_keyMotion.x = -1.0f;
- if (event.key.key == GetInputBinding(INPUT_SLOT_RIGHT).key) m_keyMotion.x = 1.0f;
- if (event.key.key == GetInputBinding(INPUT_SLOT_RIGHT).joy) m_keyMotion.x = 1.0f;
- if (event.key.key == GetInputBinding(INPUT_SLOT_GUP ).key) m_keyMotion.z = 1.0f;
- if (event.key.key == GetInputBinding(INPUT_SLOT_GUP ).joy) m_keyMotion.z = 1.0f;
- if (event.key.key == GetInputBinding(INPUT_SLOT_GDOWN).key) m_keyMotion.z = -1.0f;
- if (event.key.key == GetInputBinding(INPUT_SLOT_GDOWN).joy) m_keyMotion.z = -1.0f;
+ if (event.key.key == GetInputBinding(INPUT_SLOT_UP ).primary) m_keyMotion.y = 1.0f;
+ if (event.key.key == GetInputBinding(INPUT_SLOT_UP ).secondary) m_keyMotion.y = 1.0f;
+ if (event.key.key == GetInputBinding(INPUT_SLOT_DOWN ).primary) m_keyMotion.y = -1.0f;
+ if (event.key.key == GetInputBinding(INPUT_SLOT_DOWN ).secondary) m_keyMotion.y = -1.0f;
+ if (event.key.key == GetInputBinding(INPUT_SLOT_LEFT ).primary) m_keyMotion.x = -1.0f;
+ if (event.key.key == GetInputBinding(INPUT_SLOT_LEFT ).secondary) m_keyMotion.x = -1.0f;
+ if (event.key.key == GetInputBinding(INPUT_SLOT_RIGHT).primary) m_keyMotion.x = 1.0f;
+ if (event.key.key == GetInputBinding(INPUT_SLOT_RIGHT).secondary) m_keyMotion.x = 1.0f;
+ if (event.key.key == GetInputBinding(INPUT_SLOT_GUP ).primary) m_keyMotion.z = 1.0f;
+ if (event.key.key == GetInputBinding(INPUT_SLOT_GUP ).secondary) m_keyMotion.z = 1.0f;
+ if (event.key.key == GetInputBinding(INPUT_SLOT_GDOWN).primary) m_keyMotion.z = -1.0f;
+ if (event.key.key == GetInputBinding(INPUT_SLOT_GDOWN).secondary) m_keyMotion.z = -1.0f;
}
else if (event.type == EVENT_KEY_UP)
{
- if (event.key.key == GetInputBinding(INPUT_SLOT_UP ).key) m_keyMotion.y = 0.0f;
- if (event.key.key == GetInputBinding(INPUT_SLOT_UP ).joy) m_keyMotion.y = 0.0f;
- if (event.key.key == GetInputBinding(INPUT_SLOT_DOWN ).key) m_keyMotion.y = 0.0f;
- if (event.key.key == GetInputBinding(INPUT_SLOT_DOWN ).joy) m_keyMotion.y = 0.0f;
- if (event.key.key == GetInputBinding(INPUT_SLOT_LEFT ).key) m_keyMotion.x = 0.0f;
- if (event.key.key == GetInputBinding(INPUT_SLOT_LEFT ).joy) m_keyMotion.x = 0.0f;
- if (event.key.key == GetInputBinding(INPUT_SLOT_RIGHT).key) m_keyMotion.x = 0.0f;
- if (event.key.key == GetInputBinding(INPUT_SLOT_RIGHT).joy) m_keyMotion.x = 0.0f;
- if (event.key.key == GetInputBinding(INPUT_SLOT_GUP ).key) m_keyMotion.z = 0.0f;
- if (event.key.key == GetInputBinding(INPUT_SLOT_GUP ).joy) m_keyMotion.z = 0.0f;
- if (event.key.key == GetInputBinding(INPUT_SLOT_GDOWN).key) m_keyMotion.z = 0.0f;
- if (event.key.key == GetInputBinding(INPUT_SLOT_GDOWN).joy) m_keyMotion.z = 0.0f;
+ if (event.key.key == GetInputBinding(INPUT_SLOT_UP ).primary) m_keyMotion.y = 0.0f;
+ if (event.key.key == GetInputBinding(INPUT_SLOT_UP ).secondary) m_keyMotion.y = 0.0f;
+ if (event.key.key == GetInputBinding(INPUT_SLOT_DOWN ).primary) m_keyMotion.y = 0.0f;
+ if (event.key.key == GetInputBinding(INPUT_SLOT_DOWN ).secondary) m_keyMotion.y = 0.0f;
+ if (event.key.key == GetInputBinding(INPUT_SLOT_LEFT ).primary) m_keyMotion.x = 0.0f;
+ if (event.key.key == GetInputBinding(INPUT_SLOT_LEFT ).secondary) m_keyMotion.x = 0.0f;
+ if (event.key.key == GetInputBinding(INPUT_SLOT_RIGHT).primary) m_keyMotion.x = 0.0f;
+ if (event.key.key == GetInputBinding(INPUT_SLOT_RIGHT).secondary) m_keyMotion.x = 0.0f;
+ if (event.key.key == GetInputBinding(INPUT_SLOT_GUP ).primary) m_keyMotion.z = 0.0f;
+ if (event.key.key == GetInputBinding(INPUT_SLOT_GUP ).secondary) m_keyMotion.z = 0.0f;
+ if (event.key.key == GetInputBinding(INPUT_SLOT_GDOWN).primary) m_keyMotion.z = 0.0f;
+ if (event.key.key == GetInputBinding(INPUT_SLOT_GDOWN).secondary) m_keyMotion.z = 0.0f;
}
else if (event.type == EVENT_JOY_AXIS)
{
@@ -1356,10 +1356,10 @@ bool CRobotMain::EventProcess(Event &event)
if (event.type == EVENT_KEY_DOWN)
{
- if (event.key.key == GetInputBinding(INPUT_SLOT_HELP).key ||
- event.key.key == GetInputBinding(INPUT_SLOT_HELP).joy ||
- event.key.key == GetInputBinding(INPUT_SLOT_PROG).key ||
- event.key.key == GetInputBinding(INPUT_SLOT_PROG).joy ||
+ if (event.key.key == GetInputBinding(INPUT_SLOT_HELP).primary ||
+ event.key.key == GetInputBinding(INPUT_SLOT_HELP).secondary ||
+ event.key.key == GetInputBinding(INPUT_SLOT_PROG).primary ||
+ event.key.key == GetInputBinding(INPUT_SLOT_PROG).secondary ||
event.key.key == KEY(ESCAPE))
{
StopDisplayInfo();
@@ -1394,14 +1394,14 @@ bool CRobotMain::EventProcess(Event &event)
}
if (m_editLock) // current edition?
{
- if (event.key.key == GetInputBinding(INPUT_SLOT_HELP).key ||
- event.key.key == GetInputBinding(INPUT_SLOT_HELP).joy)
+ if (event.key.key == GetInputBinding(INPUT_SLOT_HELP).primary ||
+ event.key.key == GetInputBinding(INPUT_SLOT_HELP).secondary)
{
StartDisplayInfo(SATCOM_HUSTON, false);
return false;
}
- if (event.key.key == GetInputBinding(INPUT_SLOT_PROG).key ||
- event.key.key == GetInputBinding(INPUT_SLOT_PROG).joy)
+ if (event.key.key == GetInputBinding(INPUT_SLOT_PROG).primary ||
+ event.key.key == GetInputBinding(INPUT_SLOT_PROG).secondary)
{
StartDisplayInfo(SATCOM_PROG, false);
return false;
@@ -1410,8 +1410,8 @@ bool CRobotMain::EventProcess(Event &event)
}
if (m_movieLock) // current movie?
{
- if (event.key.key == GetInputBinding(INPUT_SLOT_QUIT).key ||
- event.key.key == GetInputBinding(INPUT_SLOT_QUIT).joy ||
+ if (event.key.key == GetInputBinding(INPUT_SLOT_QUIT).primary ||
+ event.key.key == GetInputBinding(INPUT_SLOT_QUIT).secondary ||
event.key.key == KEY(ESCAPE))
{
AbortMovie();
@@ -1420,21 +1420,21 @@ bool CRobotMain::EventProcess(Event &event)
}
if (m_camera->GetType() == Gfx::CAM_TYPE_VISIT)
{
- if (event.key.key == GetInputBinding(INPUT_SLOT_VISIT).key ||
- event.key.key == GetInputBinding(INPUT_SLOT_VISIT).joy)
+ if (event.key.key == GetInputBinding(INPUT_SLOT_VISIT).primary ||
+ event.key.key == GetInputBinding(INPUT_SLOT_VISIT).secondary)
{
StartDisplayVisit(EVENT_NULL);
}
- if (event.key.key == GetInputBinding(INPUT_SLOT_QUIT).key ||
- event.key.key == GetInputBinding(INPUT_SLOT_QUIT).joy ||
+ if (event.key.key == GetInputBinding(INPUT_SLOT_QUIT).primary ||
+ event.key.key == GetInputBinding(INPUT_SLOT_QUIT).secondary ||
event.key.key == KEY(ESCAPE))
{
StopDisplayVisit();
}
return false;
}
- if (event.key.key == GetInputBinding(INPUT_SLOT_QUIT).key ||
- event.key.key == GetInputBinding(INPUT_SLOT_QUIT).joy)
+ if (event.key.key == GetInputBinding(INPUT_SLOT_QUIT).primary ||
+ event.key.key == GetInputBinding(INPUT_SLOT_QUIT).secondary)
{
if (m_movie->IsExist())
StartDisplayInfo(SATCOM_HUSTON, false);
@@ -1454,55 +1454,55 @@ bool CRobotMain::EventProcess(Event &event)
ChangePause(!m_engine->GetPause());
}
}
- if (event.key.key == GetInputBinding(INPUT_SLOT_CAMERA).key ||
- event.key.key == GetInputBinding(INPUT_SLOT_CAMERA).joy)
+ if (event.key.key == GetInputBinding(INPUT_SLOT_CAMERA).primary ||
+ event.key.key == GetInputBinding(INPUT_SLOT_CAMERA).secondary)
{
ChangeCamera();
}
- if (event.key.key == GetInputBinding(INPUT_SLOT_DESEL).key ||
- event.key.key == GetInputBinding(INPUT_SLOT_DESEL).joy)
+ if (event.key.key == GetInputBinding(INPUT_SLOT_DESEL).primary ||
+ event.key.key == GetInputBinding(INPUT_SLOT_DESEL).secondary)
{
if (m_shortCut)
DeselectObject();
}
- if (event.key.key == GetInputBinding(INPUT_SLOT_HUMAN).key ||
- event.key.key == GetInputBinding(INPUT_SLOT_HUMAN).joy)
+ if (event.key.key == GetInputBinding(INPUT_SLOT_HUMAN).primary ||
+ event.key.key == GetInputBinding(INPUT_SLOT_HUMAN).secondary)
{
SelectHuman();
}
- if (event.key.key == GetInputBinding(INPUT_SLOT_NEXT).key ||
- event.key.key == GetInputBinding(INPUT_SLOT_NEXT).joy)
+ if (event.key.key == GetInputBinding(INPUT_SLOT_NEXT).primary ||
+ event.key.key == GetInputBinding(INPUT_SLOT_NEXT).secondary)
{
if (m_shortCut)
m_short->SelectNext();
}
- if (event.key.key == GetInputBinding(INPUT_SLOT_HELP).key ||
- event.key.key == GetInputBinding(INPUT_SLOT_HELP).joy)
+ if (event.key.key == GetInputBinding(INPUT_SLOT_HELP).primary ||
+ event.key.key == GetInputBinding(INPUT_SLOT_HELP).secondary)
{
StartDisplayInfo(SATCOM_HUSTON, true);
}
- if (event.key.key == GetInputBinding(INPUT_SLOT_PROG).key ||
- event.key.key == GetInputBinding(INPUT_SLOT_PROG).joy)
+ if (event.key.key == GetInputBinding(INPUT_SLOT_PROG).primary ||
+ event.key.key == GetInputBinding(INPUT_SLOT_PROG).secondary)
{
StartDisplayInfo(SATCOM_PROG, true);
}
- if (event.key.key == GetInputBinding(INPUT_SLOT_VISIT).key ||
- event.key.key == GetInputBinding(INPUT_SLOT_VISIT).joy)
+ if (event.key.key == GetInputBinding(INPUT_SLOT_VISIT).primary ||
+ event.key.key == GetInputBinding(INPUT_SLOT_VISIT).secondary)
{
StartDisplayVisit(EVENT_NULL);
}
- if (event.key.key == GetInputBinding(INPUT_SLOT_SPEED10).key ||
- event.key.key == GetInputBinding(INPUT_SLOT_SPEED10).joy)
+ if (event.key.key == GetInputBinding(INPUT_SLOT_SPEED10).primary ||
+ event.key.key == GetInputBinding(INPUT_SLOT_SPEED10).secondary)
{
SetSpeed(1.0f);
}
- if (event.key.key == GetInputBinding(INPUT_SLOT_SPEED15).key ||
- event.key.key == GetInputBinding(INPUT_SLOT_SPEED15).joy)
+ if (event.key.key == GetInputBinding(INPUT_SLOT_SPEED15).primary ||
+ event.key.key == GetInputBinding(INPUT_SLOT_SPEED15).secondary)
{
SetSpeed(1.5f);
}
- if (event.key.key == GetInputBinding(INPUT_SLOT_SPEED20).key ||
- event.key.key == GetInputBinding(INPUT_SLOT_SPEED20).joy)
+ if (event.key.key == GetInputBinding(INPUT_SLOT_SPEED20).primary ||
+ event.key.key == GetInputBinding(INPUT_SLOT_SPEED20).secondary)
{
SetSpeed(2.0f);
}
@@ -1956,6 +1956,17 @@ void CRobotMain::ExecuteCmd(char *cmd)
return;
}
+ if (strcmp(cmd, "speed4") == 0) {
+ SetSpeed(4.0f);
+ UpdateSpeedLabel();
+ return;
+ }
+ if (strcmp(cmd, "speed8") == 0) {
+ SetSpeed(8.0f);
+ UpdateSpeedLabel();
+ return;
+ }
+
if (m_phase == PHASE_SIMUL)
m_displayText->DisplayError(ERR_CMD, Math::Vector(0.0f,0.0f,0.0f));
}
@@ -3098,26 +3109,26 @@ void CRobotMain::KeyCamera(EventType type, unsigned int key)
if (type == EVENT_KEY_UP)
{
- if (key == GetInputBinding(INPUT_SLOT_LEFT).key ||
- key == GetInputBinding(INPUT_SLOT_LEFT).joy)
+ if (key == GetInputBinding(INPUT_SLOT_LEFT).primary ||
+ key == GetInputBinding(INPUT_SLOT_LEFT).secondary)
{
m_cameraPan = 0.0f;
}
- if (key == GetInputBinding(INPUT_SLOT_RIGHT).key ||
- key == GetInputBinding(INPUT_SLOT_RIGHT).joy)
+ if (key == GetInputBinding(INPUT_SLOT_RIGHT).primary ||
+ key == GetInputBinding(INPUT_SLOT_RIGHT).secondary)
{
m_cameraPan = 0.0f;
}
- if (key == GetInputBinding(INPUT_SLOT_UP).key ||
- key == GetInputBinding(INPUT_SLOT_UP).joy)
+ if (key == GetInputBinding(INPUT_SLOT_UP).primary ||
+ key == GetInputBinding(INPUT_SLOT_UP).secondary)
{
m_cameraZoom = 0.0f;
}
- if (key == GetInputBinding(INPUT_SLOT_DOWN).key ||
- key == GetInputBinding(INPUT_SLOT_DOWN).joy)
+ if (key == GetInputBinding(INPUT_SLOT_DOWN).primary ||
+ key == GetInputBinding(INPUT_SLOT_DOWN).secondary)
{
m_cameraZoom = 0.0f;
}
@@ -3133,26 +3144,26 @@ void CRobotMain::KeyCamera(EventType type, unsigned int key)
if (type == EVENT_KEY_DOWN)
{
- if (key == GetInputBinding(INPUT_SLOT_LEFT).key ||
- key == GetInputBinding(INPUT_SLOT_LEFT).joy)
+ if (key == GetInputBinding(INPUT_SLOT_LEFT).primary ||
+ key == GetInputBinding(INPUT_SLOT_LEFT).secondary)
{
m_cameraPan = -1.0f;
}
- if (key == GetInputBinding(INPUT_SLOT_RIGHT).key ||
- key == GetInputBinding(INPUT_SLOT_RIGHT).joy)
+ if (key == GetInputBinding(INPUT_SLOT_RIGHT).primary ||
+ key == GetInputBinding(INPUT_SLOT_RIGHT).secondary)
{
m_cameraPan = 1.0f;
}
- if (key == GetInputBinding(INPUT_SLOT_UP).key ||
- key == GetInputBinding(INPUT_SLOT_UP).joy)
+ if (key == GetInputBinding(INPUT_SLOT_UP).primary ||
+ key == GetInputBinding(INPUT_SLOT_UP).secondary)
{
m_cameraZoom = -1.0f;
}
- if (key == GetInputBinding(INPUT_SLOT_DOWN).key ||
- key == GetInputBinding(INPUT_SLOT_DOWN).joy)
+ if (key == GetInputBinding(INPUT_SLOT_DOWN).primary ||
+ key == GetInputBinding(INPUT_SLOT_DOWN).secondary)
{
m_cameraZoom = 1.0f;
}
@@ -3889,8 +3900,8 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
if (Cmd(line, "DeepView") && !resetObject)
{
- m_engine->SetDeepView(OpFloat(line, "air", 500.0f)*UNIT, 0, true);
- m_engine->SetDeepView(OpFloat(line, "water", 100.0f)*UNIT, 1, true);
+ m_engine->SetDeepView(OpFloat(line, "air", 500.0f)*g_unit, 0, true);
+ m_engine->SetDeepView(OpFloat(line, "water", 100.0f)*g_unit, 1, true);
}
if (Cmd(line, "FogStart") && !resetObject)
@@ -3951,7 +3962,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
m_terrain->Generate(OpInt(line, "mosaic", 20),
OpInt(line, "brick", 3),
OpFloat(line, "size", 20.0f),
- OpFloat(line, "vision", 500.0f)*UNIT,
+ OpFloat(line, "vision", 500.0f)*g_unit,
OpInt(line, "depth", 2),
OpFloat(line, "hard", 0.5f));
}
@@ -3983,7 +3994,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
name,
OpColor(line, "diffuse", Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f)),
OpColor(line, "ambient", Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f)),
- OpFloat(line, "level", 100.0f)*UNIT,
+ OpFloat(line, "level", 100.0f)*g_unit,
OpFloat(line, "glint", 1.0f),
pos);
m_colorNewWater = OpColor(line, "color", m_colorRefWater);
@@ -3999,14 +4010,14 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
m_cloud->Create(name,
OpColor(line, "diffuse", Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f)),
OpColor(line, "ambient", Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f)),
- OpFloat(line, "level", 500.0f) * UNIT);
+ OpFloat(line, "level", 500.0f) * g_unit);
}
if (Cmd(line, "TerrainBlitz") && !resetObject)
{
m_lightning->Create(OpFloat(line, "sleep", 0.0f),
OpFloat(line, "delay", 3.0f),
- OpFloat(line, "magnetic", 50.0f) * UNIT);
+ OpFloat(line, "magnetic", 50.0f) * g_unit);
}
if (Cmd(line, "TerrainInitTextures") && !resetObject)
@@ -4059,8 +4070,8 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
}
m_terrain->GenerateMaterials(id,
- OpFloat(line, "min", 0.0f)*UNIT,
- OpFloat(line, "max", 100.0f)*UNIT,
+ OpFloat(line, "min", 0.0f)*g_unit,
+ OpFloat(line, "max", 100.0f)*g_unit,
OpFloat(line, "slope", 5.0f),
OpFloat(line, "freq", 100.0f),
OpPos(line, "center")*g_unit,
@@ -6615,9 +6626,20 @@ void CRobotMain::ChangePause(bool pause)
//! Changes game speed
void CRobotMain::SetSpeed(float speed)
{
- // TODO: m_app->SetSimulationSpeed(speed);
+ m_app->SetSimulationSpeed(speed);
+ UpdateSpeedLabel();
+}
+
+float CRobotMain::GetSpeed()
+{
+ return m_app->GetSimulationSpeed();
+}
+void CRobotMain::UpdateSpeedLabel()
+{
Ui::CButton* pb = dynamic_cast<Ui::CButton*>(m_interface->SearchControl(EVENT_SPEED));
+ float speed = m_app->GetSimulationSpeed();
+
if (pb != nullptr)
{
if (speed == 1.0f)
@@ -6632,11 +6654,7 @@ void CRobotMain::SetSpeed(float speed)
pb->SetState(Ui::STATE_VISIBLE);
}
}
-}
-float CRobotMain::GetSpeed()
-{
- return m_app->GetSimulationSpeed();
}
diff --git a/src/object/robotmain.h b/src/object/robotmain.h
index 70fbc8d..e475c43 100644
--- a/src/object/robotmain.h
+++ b/src/object/robotmain.h
@@ -148,12 +148,12 @@ const int SATCOM_MAX = 6;
*/
struct InputBinding
{
- //! Keyboard binding code (can be regular or virtual)
- unsigned int key;
- //! Joystick binding code (virtual)
- unsigned int joy;
+ //! Primary and secondary bindings
+ //! Can be regular key, virtual key or virtual joystick button
+ unsigned int primary, secondary;
- InputBinding() : key(KEY_INVALID), joy(KEY_INVALID) {}
+ InputBinding(unsigned int p = KEY_INVALID, unsigned int s = KEY_INVALID)
+ : primary(p), secondary(s) {}
};
/**
@@ -383,6 +383,7 @@ protected:
void StopDisplayVisit();
void ExecuteCmd(char *cmd);
bool TestGadgetQuantity(int rank);
+ void UpdateSpeedLabel();
protected:
CInstanceManager* m_iMan;
diff --git a/src/object/task/taskbuild.cpp b/src/object/task/taskbuild.cpp
index 469e9cb..d82874c 100644
--- a/src/object/task/taskbuild.cpp
+++ b/src/object/task/taskbuild.cpp
@@ -153,8 +153,7 @@ void CTaskBuild::CreateLight()
light.attenuation0 = 1.0f;
light.attenuation1 = 0.0f;
light.attenuation2 = 0.0f;
- //TODO Is this value correct
- light.spotAngle = 90;
+ light.spotAngle = 90.0f*Math::PI/180.0f;
m_lightMan->SetLight(m_lightRank[i], light);
color.r = -1.0f;
diff --git a/src/object/task/taskshield.cpp b/src/object/task/taskshield.cpp
index 682bcb1..93afd62 100644
--- a/src/object/task/taskshield.cpp
+++ b/src/object/task/taskshield.cpp
@@ -499,7 +499,7 @@ bool CTaskShield::CreateLight(Math::Vector pos)
light.attenuation0 = 1.0f;
light.attenuation1 = 0.0f;
light.attenuation2 = 0.0f;
- light.spotAngle = 90;
+ light.spotAngle = 90.0f*Math::PI/180.0f;
m_effectLight = m_lightMan->CreateLight();
if ( m_effectLight == -1 ) return false;
diff --git a/src/script/script.cpp b/src/script/script.cpp
index 4df7a51..001443b 100644
--- a/src/script/script.cpp
+++ b/src/script/script.cpp
@@ -19,6 +19,7 @@
#include "script/script.h"
+#include "app/app.h"
#include "common/global.h"
#include "common/iman.h"
#include "common/restext.h"
diff --git a/src/ui/edit.cpp b/src/ui/edit.cpp
index 547e73a..e14b19d 100644
--- a/src/ui/edit.cpp
+++ b/src/ui/edit.cpp
@@ -1794,7 +1794,7 @@ bool CEdit::ReadText(const char *filename, int addSize)
if ( SearchKey(buffer+i+5, slot) )
{
CRobotMain* main = CRobotMain::GetInstancePointer();
- res = main->GetInputBinding(slot).key;
+ res = main->GetInputBinding(slot).primary;
if ( res != 0 )
{
if ( GetResource(RES_KEY, res, iName) )
@@ -1813,7 +1813,7 @@ bool CEdit::ReadText(const char *filename, int addSize)
m_format[j] = font;
j ++;
- res = main->GetInputBinding(slot).joy;
+ res = main->GetInputBinding(slot).secondary;
if ( res != 0 )
{
if ( GetResource(RES_KEY, res, iName) )
diff --git a/src/ui/key.cpp b/src/ui/key.cpp
index 26d99ac..9a76127 100644
--- a/src/ui/key.cpp
+++ b/src/ui/key.cpp
@@ -15,65 +15,48 @@
// * You should have received a copy of the GNU General Public License
// * along with this program. If not, see http://www.gnu.org/licenses/.
-// key.cpp
-
-
#include "ui/key.h"
-#include <string.h>
+#include "common/global.h"
+
+#include <cstring>
namespace Ui {
-void GetKeyName(char *name, int key)
+
+void GetKeyName(char* name, unsigned int key)
{
- if ( !GetResource(RES_KEY, key, name) ) {
- if (isalnum(key)) {
- name[0] = key;
- name[1] = 0;
- }
- else {
- sprintf(name, "Code %d", key);
- }
- }
+ if (!GetResource(RES_KEY, key, name))
+ sprintf(name, "Code %d", key);
}
-// Object's constructor.
-
CKey::CKey() : CControl()
{
- m_key[0] = 0;
- m_key[1] = 0;
- m_bCatch = false;
+ m_catch = false;
- m_app = CApplication::GetInstancePointer();
+ m_robotMain = CRobotMain::GetInstancePointer();
}
-// Object's destructor.
-
CKey::~CKey()
{
+ m_robotMain = nullptr;
}
-
-// Creates a new button.
-
bool CKey::Create(Math::Point pos, Math::Point dim, int icon, EventType eventMsg)
{
- char name[100];
if (eventMsg == EVENT_NULL)
eventMsg = GetUniqueEventType();
CControl::Create(pos, dim, icon, eventMsg);
+
+ char name[100];
GetResource(RES_EVENT, eventMsg, name);
SetName(std::string(name));
return true;
}
-
-// Management of an event.
-
bool CKey::EventProcess(const Event &event)
{
if (m_state & STATE_DEAD)
@@ -81,24 +64,31 @@ bool CKey::EventProcess(const Event &event)
CControl::EventProcess(event);
- if (event.type == EVENT_MOUSE_BUTTON_DOWN) {
+ if (event.type == EVENT_MOUSE_BUTTON_DOWN)
+ {
if (event.mouseButton.button == MOUSE_BUTTON_LEFT) // left
- m_bCatch = Detect(event.mousePos);
+ m_catch = Detect(event.mousePos);
}
- if (event.type == EVENT_KEY_DOWN && m_bCatch) {
- m_bCatch = false;
+ if (event.type == EVENT_KEY_DOWN && m_catch)
+ {
+ m_catch = false;
- if ( TestKey(event.key.key) ) { // impossible ?
+ if (TestKey(event.key.key)) // impossible ?
+ {
m_sound->Play(SOUND_TZOING);
- } else {
- // TODO: test for virtual, joystick, etc.
- if ( event.key.key == m_key[0] || event.key.key == m_key[1] ) {
- m_key[0] = event.key.key;
- m_key[1] = 0;
- } else {
- m_key[1] = m_key[0];
- m_key[0] = event.key.key;
+ }
+ else
+ {
+ if (event.key.key == m_binding.primary || event.key.key == m_binding.secondary)
+ {
+ m_binding.secondary = KEY_INVALID;
+ m_binding.primary = event.key.key;
+ }
+ else
+ {
+ m_binding.secondary = m_binding.primary;
+ m_binding.primary = event.key.key;
}
m_sound->Play(SOUND_CLICK);
@@ -112,96 +102,88 @@ bool CKey::EventProcess(const Event &event)
return true;
}
-
-// Seeks when a key is already used.
-
-bool CKey::TestKey(int key)
+bool CKey::TestKey(unsigned int key)
{
- if ( key == KEY(PAUSE) || key == KEY(PRINT) ) return true; // blocked key
+ if (key == KEY(PAUSE) || key == KEY(PRINT)) return true; // blocked key
- /* TODO: input bindings
- for (int i = 0; i < 20; i++) {
- for (int j = 0; j < 2; j++) {
- if (key == m_app->GetKey(i, j) ) // key used?
- m_app->SetKey(i, j, 0); // nothing!
- }
+ for (int i = 0; i < INPUT_SLOT_MAX; i++)
+ {
+ InputSlot slot = static_cast<InputSlot>(i);
+ InputBinding b = m_robotMain->GetInputBinding(slot);
+ if (key == b.primary || key == b.secondary)
+ m_robotMain->SetInputBinding(slot, InputBinding()); // nothing!
- if ( m_app->GetKey(i, 0) == 0 ) { // first free option?
- m_app->SetKey(i, 0, m_app->GetKey(i, 1)); // shift
- m_app->SetKey(i, 1, 0);
- }
- } */
+ if (b.primary == KEY_INVALID) // first free option?
+ m_robotMain->SetInputBinding(slot, InputBinding(b.secondary, b.primary)); // shift
+ }
return false; // not used
}
-
-// Draws button.
-
void CKey::Draw()
{
- Math::Point iDim, pos;
- float zoomExt, zoomInt, h;
- int icon;
- char text[100];
-
- if ( (m_state & STATE_VISIBLE) == 0 )
+ if ((m_state & STATE_VISIBLE) == 0)
return;
- iDim = m_dim;
+ Math::Point iDim = m_dim;
m_dim.x = 200.0f/640.0f;
- if ( m_state & STATE_SHADOW )
+ if (m_state & STATE_SHADOW)
DrawShadow(m_pos, m_dim);
m_engine->SetTexture("button1.png");
m_engine->SetState(Gfx::ENG_RSTATE_NORMAL); // was D3DSTATENORMAL
- zoomExt = 1.00f;
- zoomInt = 0.95f;
+ float zoomExt = 1.00f;
+ float zoomInt = 0.95f;
- icon = 2;
- if ( m_key[0] == 0 && m_key[1] == 0 ) // no shortcut?
+ int icon = 2;
+ if (m_binding.primary == KEY_INVALID && m_binding.secondary == KEY_INVALID) // no shortcut?
icon = 3;
- if ( m_state & STATE_DEFAULT ) {
+ if (m_state & STATE_DEFAULT)
+ {
DrawPart(23, 1.3f, 0.0f);
zoomExt *= 1.15f;
zoomInt *= 1.15f;
}
- if ( m_state & STATE_HILIGHT )
+ if (m_state & STATE_HILIGHT)
icon = 1;
- if ( m_state & STATE_CHECK )
+ if (m_state & STATE_CHECK)
icon = 0;
- if ( m_state & STATE_PRESS ) {
+ if (m_state & STATE_PRESS)
+ {
icon = 3;
zoomInt *= 0.9f;
}
- if ( (m_state & STATE_ENABLE) == 0 )
+ if ((m_state & STATE_ENABLE) == 0)
icon = 7;
- if ( m_state & STATE_DEAD )
+ if (m_state & STATE_DEAD)
icon = 17;
- if ( m_bCatch )
+ if (m_catch)
icon = 23;
DrawPart(icon, zoomExt, 8.0f / 256.0f); // draws the button
- h = m_engine->GetText()->GetHeight(m_fontType, m_fontSize) / 2.0f;
+ float h = m_engine->GetText()->GetHeight(m_fontType, m_fontSize) / 2.0f;
- GetKeyName(text, m_key[0]);
- if ( m_key[1] != 0 ) {
+ char text[100];
+ GetKeyName(text, m_binding.primary);
+ if (m_binding.secondary != KEY_INVALID)
+ {
GetResource(RES_TEXT, RT_KEY_OR, text+strlen(text));
- GetKeyName(text+strlen(text), m_key[1]);
+ GetKeyName(text+strlen(text), m_binding.secondary);
}
+ Math::Point pos;
pos.x = m_pos.x + m_dim.x * 0.5f;
pos.y = m_pos.y + m_dim.y * 0.5f;
pos.y -= h;
@@ -209,7 +191,7 @@ void CKey::Draw()
m_dim = iDim;
- if ( m_state & STATE_DEAD )
+ if (m_state & STATE_DEAD)
return;
// Draws the name.
@@ -219,20 +201,15 @@ void CKey::Draw()
m_engine->GetText()->DrawText(std::string(m_name), m_fontType, m_fontSize, pos, m_dim.x, Gfx::TEXT_ALIGN_LEFT, 0);
}
-
-
-void CKey::SetKey(int option, int key)
+void CKey::SetBinding(InputBinding b)
{
- if ( option < 0 || option > 1 ) return;
-
- m_key[option] = key;
+ m_binding = b;
}
-int CKey::GetKey(int option)
+InputBinding CKey::GetBinding()
{
- if ( option < 0 || option > 1 ) return 0;
-
- return m_key[option];
+ return m_binding;
}
-}
+
+} // namespace Ui
diff --git a/src/ui/key.h b/src/ui/key.h
index 1943f61..2332c9b 100644
--- a/src/ui/key.h
+++ b/src/ui/key.h
@@ -15,13 +15,13 @@
// * You should have received a copy of the GNU General Public License
// * along with this program. If not, see http://www.gnu.org/licenses/.
-// key.h
+/**
+ * \file ui/key.h
+ * \brief Key slot control
+ */
#pragma once
-#include <cctype>
-#include <string>
-
#include "ui/control.h"
#include "common/iman.h"
@@ -29,33 +29,40 @@
#include "common/restext.h"
#include "common/key.h"
-#include "app/app.h"
namespace Ui {
class CKey : public CControl
{
- public:
- CKey();
- virtual ~CKey();
+public:
+ CKey();
+ virtual ~CKey();
- bool Create(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
- bool EventProcess(const Event &event);
+ //! Creates a new key slot button
+ bool Create(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
+ //! Management of an event
+ bool EventProcess(const Event &event);
- void Draw();
+ //! Draws button
+ void Draw();
- void SetKey(int option, int key);
- int GetKey(int option);
+ //! Management of binding
+ //@{
+ void SetBinding(InputBinding b);
+ InputBinding GetBinding();
+ //@}
- protected:
- bool TestKey(int key);
+protected:
+ //! Checks if a key is already used
+ bool TestKey(unsigned int key);
- unsigned int m_key[2];
- bool m_bCatch;
+protected:
+ CRobotMain* m_robotMain;
- CApplication *m_app;
+ InputBinding m_binding;
+ bool m_catch;
};
-}
+} // namespace Ui
diff --git a/src/ui/maindialog.cpp b/src/ui/maindialog.cpp
index d7295eb..5136a41 100644
--- a/src/ui/maindialog.cpp
+++ b/src/ui/maindialog.cpp
@@ -8,7 +8,7 @@
// *
// * 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 Gfx::PARTICULAR PURPOSE. See the
+// * 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
@@ -5476,7 +5476,6 @@ void CMainDialog::SetupMemorize()
{
float fValue;
int iValue, i, j;
- char key[500];
char num[10];
GetProfile().SetLocalProfileString("Directory", "scene", m_sceneDir);
@@ -5518,21 +5517,16 @@ void CMainDialog::SetupMemorize()
// GetProfile()->SetLocalProfileInt("Setup", "UseJoystick", m_engine->GetJoystick());
// GetProfile()->SetLocalProfileInt("Setup", "MidiVolume", m_sound->GetMidiVolume());
- // key[0] = 0;
- // for ( i=0 ; i<100 ; i++ )
- // {
- // if ( m_engine->GetKey(i, 0) == 0 ) break;
-
- // for ( j=0 ; j<2 ; j++ )
- // {
- // iValue = m_engine->GetKey(i, j);
- // sprintf(num, "%d%c", iValue, j==0?'+':' ');
- // strcat(key, num);
- // }
- // }
+ std::stringstream key;
+ for (int i = 0; i < INPUT_SLOT_MAX; i++)
+ {
+ InputBinding b = m_main->GetInputBinding(static_cast<InputSlot>(i));
- /* TODO: profile
- SetLocalProfileString("Setup", "KeyMap", key); */
+ key << b.primary << " ";
+ key << b.secondary << " ";
+ }
+
+ GetProfile().SetLocalProfileString("Setup", "KeyMap", key.str());
#if _NET
if ( m_accessEnable )
@@ -5556,9 +5550,8 @@ void CMainDialog::SetupMemorize()
void CMainDialog::SetupRecall()
{
float fValue;
- int iValue, i, j;
+ int iValue;
std::string key;
- char* p;
if ( GetProfile().GetLocalProfileString("Directory", "scene", key) )
{
@@ -5747,22 +5740,18 @@ void CMainDialog::SetupRecall()
m_engine->SetEditIndentValue(iValue);
}
- // if ( GetLocalProfileString("Setup", "KeyMap", key, 500) )
- // {
- // p = key;
- // for ( i=0 ; i<100 ; i++ )
- // {
- // if ( p[0] == 0 ) break;
-
- // for ( j=0 ; j<2 ; j++ )
- // {
- // sscanf(p, "%d", &iValue);
- // m_engine->SetKey(i, j, iValue);
- // while ( *p >= '0' && *p <= '9' ) p++;
- // while ( *p == ' ' || *p == '+' ) p++;
- // }
- // }
- // }
+ if (GetProfile().GetLocalProfileString("Setup", "KeyMap", key))
+ {
+ std::stringstream skey;
+ skey.str(key);
+ for (int i = 0; i < INPUT_SLOT_MAX; i++)
+ {
+ InputBinding b;
+ skey >> b.primary;
+ skey >> b.secondary;
+ m_main->SetInputBinding(static_cast<InputSlot>(i), b);
+ }
+ }
#if _NET
if ( m_accessEnable )
@@ -5837,7 +5826,7 @@ void CMainDialog::ChangeSetupQuality(int quality)
// Redefinable keys:
-static int key_table[KEY_TOTAL] =
+static InputSlot key_table[KEY_TOTAL] =
{
INPUT_SLOT_LEFT,
INPUT_SLOT_RIGHT,
@@ -5891,37 +5880,30 @@ static EventType key_event[KEY_TOTAL] =
void CMainDialog::UpdateKey()
{
- CWindow* pw;
- CScroll* ps;
- CKey* pk;
- Math::Point pos, dim;
- int first, i;
+ CWindow* pw = static_cast<CWindow*>(m_interface->SearchControl(EVENT_WINDOW5));
+ if (pw == nullptr) return;
- pw = static_cast<CWindow*>(m_interface->SearchControl(EVENT_WINDOW5));
- if ( pw == 0 ) return;
-
- ps = static_cast<CScroll*>(pw->SearchControl(EVENT_INTERFACE_KSCROLL));
- if ( ps == 0 ) return;
+ CScroll* ps = static_cast<CScroll*>(pw->SearchControl(EVENT_INTERFACE_KSCROLL));
+ if (ps == nullptr) return;
- first = static_cast<int>(ps->GetVisibleValue()*(KEY_TOTAL-KEY_VISIBLE));
+ int first = static_cast<int>(ps->GetVisibleValue()*(KEY_TOTAL-KEY_VISIBLE));
- for ( i=0 ; i<KEY_TOTAL ; i++ )
- {
+ for (int i = 0; i < KEY_TOTAL; i++)
pw->DeleteControl(key_event[i]);
- }
+ Math::Point dim;
dim.x = 400.0f/640.0f;
dim.y = 20.0f/480.0f;
+ Math::Point pos;
pos.x = 110.0f/640.0f;
pos.y = 168.0f/480.0f + dim.y*(KEY_VISIBLE-1);
- for ( i=0 ; i<KEY_VISIBLE ; i++ )
+ for (int i = 0; i < KEY_VISIBLE; i++)
{
pw->CreateKey(pos, dim, -1, key_event[first+i]);
- pk = static_cast<CKey*>(pw->SearchControl(key_event[first+i]));
- if ( pk == 0 ) break;
- /* TODO: set input bindings
- pk->SetKey(0, m_engine->GetKey(key_table[first+i], 0));
- pk->SetKey(1, m_engine->GetKey(key_table[first+i], 1)); */
+ CKey* pk = static_cast<CKey*>(pw->SearchControl(key_event[first+i]));
+ if (pk == nullptr) break;
+
+ pk->SetBinding(m_main->GetInputBinding(key_table[first+i]));
pos.y -= dim.y;
}
}
@@ -5930,26 +5912,20 @@ void CMainDialog::UpdateKey()
void CMainDialog::ChangeKey(EventType event)
{
- CWindow* pw;
- CScroll* ps;
- CKey* pk;
- int i;
-
- pw = static_cast<CWindow*>(m_interface->SearchControl(EVENT_WINDOW5));
- if ( pw == 0 ) return;
+ CWindow* pw = static_cast<CWindow*>(m_interface->SearchControl(EVENT_WINDOW5));
+ if (pw == nullptr) return;
- ps = static_cast<CScroll*>(pw->SearchControl(EVENT_INTERFACE_KSCROLL));
- if ( ps == 0 ) return;
+ CScroll* ps = static_cast<CScroll*>(pw->SearchControl(EVENT_INTERFACE_KSCROLL));
+ if (ps == nullptr) return;
- for ( i=0 ; i<KEY_TOTAL ; i++ )
+ for (int i = 0; i < KEY_TOTAL; i++)
{
if ( key_event[i] == event )
{
- pk = static_cast<CKey*>(pw->SearchControl(key_event[i]));
- if ( pk == 0 ) break;
- /* TODO: set key binding
- m_engine->SetKey(key_table[i], 0, pk->GetKey(0));
- m_engine->SetKey(key_table[i], 1, pk->GetKey(1)); */
+ CKey* pk = static_cast<CKey*>(pw->SearchControl(key_event[i]));
+ if (pk == nullptr) break;
+
+ m_main->SetInputBinding(key_table[i], pk->GetBinding());
}
}
}
@@ -6803,4 +6779,3 @@ bool CMainDialog::NextMission()
} // namespace Ui
-
diff --git a/src/ui/mainshort.cpp b/src/ui/mainshort.cpp
index ac6d7fc..55b9612 100644
--- a/src/ui/mainshort.cpp
+++ b/src/ui/mainshort.cpp
@@ -30,7 +30,7 @@ CMainShort::CMainShort()
m_iMan->AddInstance(CLASS_SHORT, this);
m_interface = static_cast<CInterface*>(m_iMan->SearchInstance(CLASS_INTERFACE));
- m_event = static_cast<CEvent*>(m_iMan->SearchInstance(CLASS_EVENT));
+ m_event = static_cast<CEventQueue*>(m_iMan->SearchInstance(CLASS_EVENT));
m_engine = static_cast<Gfx::CEngine*>(m_iMan->SearchInstance(CLASS_ENGINE));
m_main = static_cast<CRobotMain*>(m_iMan->SearchInstance(CLASS_MAIN));
diff --git a/src/ui/mainshort.h b/src/ui/mainshort.h
index e97bdcc..0912e68 100644
--- a/src/ui/mainshort.h
+++ b/src/ui/mainshort.h
@@ -47,7 +47,7 @@ class CMainShort
protected:
CInstanceManager* m_iMan;
- CEvent* m_event;
+ CEventQueue* m_event;
Gfx::CEngine* m_engine;
CInterface* m_interface;
CRobotMain* m_main;
diff --git a/src/ui/studio.cpp b/src/ui/studio.cpp
index a581baa..2f58c95 100644
--- a/src/ui/studio.cpp
+++ b/src/ui/studio.cpp
@@ -241,8 +241,8 @@ bool CStudio::EventProcess(const Event &event)
if ( event.type == EVENT_KEY_DOWN )
{
- if ( event.key.key == m_main->GetInputBinding(INPUT_SLOT_CBOT).key ||
- event.key.key == m_main->GetInputBinding(INPUT_SLOT_CBOT).joy )
+ if ( event.key.key == m_main->GetInputBinding(INPUT_SLOT_CBOT).primary ||
+ event.key.key == m_main->GetInputBinding(INPUT_SLOT_CBOT).secondary )
{
if ( m_helpFilename.length() > 0 )
{